xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/usb/if_usb.c (revision dd4dc88b837a295134aa9869114a2efee0f4894b)
1 /*
2  * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <linux/usb.h>
20 #include <linux/usb/hcd.h>
21 #include "if_usb.h"
22 #include "hif_usb_internal.h"
23 #include "target_type.h"		/* TARGET_TYPE_ */
24 #include "regtable_usb.h"
25 #include "ol_fw.h"
26 #include "hif_debug.h"
27 #include "epping_main.h"
28 #include "hif_main.h"
29 #include "qwlan_version.h"
30 #include "usb_api.h"
31 
32 #define DELAY_FOR_TARGET_READY 200	/* 200ms */
33 
34 /* Save memory addresses where we save FW ram dump, and then we could obtain
35  * them by symbol table.
36  */
37 uint32_t fw_stack_addr;
38 void *fw_ram_seg_addr[FW_RAM_SEG_CNT];
39 
40 
41 
42 static int hif_usb_unload_dev_num = -1;
43 struct hif_usb_softc *g_usb_sc;
44 
45 /**
46  * hif_usb_diag_write_cold_reset() - reset SOC by sending a diag command
47  * @scn: pointer to ol_softc structure
48  *
49  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
50  */
51 static inline QDF_STATUS
52 hif_usb_diag_write_cold_reset(struct hif_softc *scn)
53 {
54 	struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn);
55 	struct hif_target_info *tgt_info = &scn->target_info;
56 
57 	/* For Genoa, chip-reset is handled in CNSS driver */
58 	if (tgt_info->target_type == TARGET_TYPE_QCN7605)
59 		return QDF_STATUS_SUCCESS;
60 
61 	HIF_DBG("%s: resetting SOC", __func__);
62 
63 	return hif_diag_write_access(hif_hdl,
64 				(ROME_USB_SOC_RESET_CONTROL_COLD_RST_LSB |
65 				ROME_USB_RTC_SOC_BASE_ADDRESS),
66 				SOC_RESET_CONTROL_COLD_RST_SET(1));
67 }
68 
69 /**
70  * hif_usb_procfs_init() - create init procfs
71  * @scn: pointer to hif_usb_softc structure
72  *
73  * Return: int 0 if success else an appropriate error number
74  */
75 static int
76 hif_usb_procfs_init(struct hif_softc *scn)
77 {
78 	int ret = 0;
79 
80 	HIF_ENTER();
81 
82 	if (athdiag_procfs_init(scn) != 0) {
83 		HIF_ERROR("athdiag_procfs_init failed");
84 		ret = A_ERROR;
85 	}
86 
87 	scn->athdiag_procfs_inited = true;
88 
89 	HIF_EXIT();
90 	return ret;
91 }
92 
93 /**
94  * hif_nointrs(): disable IRQ
95  * @scn: pointer to struct hif_softc
96  *
97  * This function stops interrupt(s)
98  *
99  * Return: none
100  */
101 void hif_usb_nointrs(struct hif_softc *scn)
102 {
103 
104 }
105 
106 /**
107  * hif_usb_reboot() - called at reboot time to reset WLAN SOC
108  * @nb: pointer to notifier_block registered during register_reboot_notifier
109  * @val: code indicating reboot reason
110  * @v: unused pointer
111  *
112  * Return: int 0 if success else an appropriate error number
113  */
114 static int hif_usb_reboot(struct notifier_block *nb, unsigned long val,
115 				void *v)
116 {
117 	struct hif_usb_softc *sc;
118 
119 	HIF_ENTER();
120 	sc = container_of(nb, struct hif_usb_softc, reboot_notifier);
121 	/* do cold reset */
122 	hif_usb_diag_write_cold_reset(HIF_GET_SOFTC(sc));
123 	HIF_EXIT();
124 	return NOTIFY_DONE;
125 }
126 
127 /**
128  * hif_usb_disable_lpm() - Disable lpm feature of usb2.0
129  * @udev: pointer to usb_device for which LPM is to be disabled
130  *
131  * LPM needs to be disabled to avoid usb2.0 probe timeout
132  *
133  * Return: int 0 if success else an appropriate error number
134  */
135 static int hif_usb_disable_lpm(struct usb_device *udev)
136 {
137 	struct usb_hcd *hcd;
138 	int ret = -EPERM;
139 
140 	HIF_ENTER();
141 
142 	if (!udev || !udev->bus) {
143 		HIF_ERROR("Invalid input parameters");
144 		goto exit;
145 	}
146 
147 	hcd = bus_to_hcd(udev->bus);
148 	if (udev->usb2_hw_lpm_enabled) {
149 		if (hcd->driver->set_usb2_hw_lpm) {
150 			ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, false);
151 			if (!ret) {
152 				udev->usb2_hw_lpm_enabled = false;
153 				udev->usb2_hw_lpm_capable = false;
154 				HIF_TRACE("%s: LPM is disabled", __func__);
155 			} else {
156 				HIF_TRACE("%s: Fail to disable LPM",
157 						__func__);
158 			}
159 		} else {
160 			HIF_TRACE("%s: hcd doesn't support LPM",
161 						__func__);
162 		}
163 	} else {
164 		HIF_TRACE("%s: LPM isn't enabled", __func__);
165 	}
166 exit:
167 	HIF_EXIT();
168 	return ret;
169 }
170 
171 /**
172  * hif_usb_enable_bus() - enable usb bus
173  * @ol_sc: hif_softc struct
174  * @dev: device pointer
175  * @bdev: bus dev pointer
176  * @bid: bus id pointer
177  * @type: enum hif_enable_type such as HIF_ENABLE_TYPE_PROBE
178  *
179  * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure
180  */
181 QDF_STATUS hif_usb_enable_bus(struct hif_softc *scn,
182 			struct device *dev, void *bdev,
183 			const struct hif_bus_id *bid,
184 			enum hif_enable_type type)
185 
186 {
187 	struct usb_interface *interface = (struct usb_interface *)bdev;
188 	struct usb_device_id *id = (struct usb_device_id *)bid;
189 	int ret = 0;
190 	struct hif_usb_softc *sc;
191 	struct usb_device *usbdev = interface_to_usbdev(interface);
192 	int vendor_id, product_id;
193 	struct hif_target_info *tgt_info;
194 	struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn);
195 	u32 hif_type;
196 	u32 target_type;
197 
198 	usb_get_dev(usbdev);
199 
200 	if (!scn) {
201 		HIF_ERROR("%s: hif_ctx is NULL", __func__);
202 		goto err_usb;
203 	}
204 
205 	sc = HIF_GET_USB_SOFTC(scn);
206 
207 	HIF_INFO("%s hif_softc %pK usbdev %pK interface %pK\n",
208 		__func__,
209 		scn,
210 		usbdev,
211 		interface);
212 
213 	vendor_id = qdf_le16_to_cpu(usbdev->descriptor.idVendor);
214 	product_id = qdf_le16_to_cpu(usbdev->descriptor.idProduct);
215 
216 	HIF_ERROR("%s: con_mode = 0x%x, vendor_id = 0x%x product_id = 0x%x",
217 		__func__, hif_get_conparam(scn), vendor_id, product_id);
218 
219 	sc->pdev = (void *)usbdev;
220 	sc->dev = &usbdev->dev;
221 	sc->devid = id->idProduct;
222 
223 	hif_get_device_type(product_id, 0, &hif_type, &target_type);
224 	tgt_info = hif_get_target_info_handle(hif_hdl);
225 	if (target_type == TARGET_TYPE_QCN7605)
226 		tgt_info->target_type = TARGET_TYPE_QCN7605;
227 
228 	/*
229 	 * For Genoa, skip set_configuration, since it is handled
230 	 * by CNSS driver.
231 	 */
232 	if (target_type != TARGET_TYPE_QCN7605) {
233 		if ((usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
234 				     USB_REQ_SET_CONFIGURATION, 0, 1, 0,
235 				     NULL, 0, HZ)) < 0) {
236 			HIF_ERROR("%s[%d]", __func__, __LINE__);
237 			goto err_usb;
238 		}
239 		usb_set_interface(usbdev, 0, 0);
240 		sc->reboot_notifier.notifier_call = hif_usb_reboot;
241 		register_reboot_notifier(&sc->reboot_notifier);
242 	}
243 
244 	/* disable lpm to avoid usb2.0 probe timeout */
245 	hif_usb_disable_lpm(usbdev);
246 
247 	/* params need to be added - TODO
248 	 * scn->enableuartprint = 1;
249 	 * scn->enablefwlog = 0;
250 	 * scn->max_no_of_peers = 1;
251 	 */
252 
253 	sc->interface = interface;
254 	if (hif_usb_device_init(sc) != QDF_STATUS_SUCCESS) {
255 		HIF_ERROR("ath: %s: hif_usb_device_init failed", __func__);
256 		goto err_reset;
257 	}
258 
259 	if (hif_usb_procfs_init(scn))
260 		goto err_reset;
261 
262 	hif_usb_unload_dev_num = usbdev->devnum;
263 	g_usb_sc = sc;
264 	HIF_EXIT();
265 	return 0;
266 
267 err_reset:
268 	hif_usb_diag_write_cold_reset(scn);
269 	g_usb_sc = NULL;
270 	hif_usb_unload_dev_num = -1;
271 	if (target_type != TARGET_TYPE_QCN7605)
272 		unregister_reboot_notifier(&sc->reboot_notifier);
273 err_usb:
274 	ret = QDF_STATUS_E_FAILURE;
275 	usb_put_dev(usbdev);
276 	return ret;
277 }
278 
279 
280 /**
281  * hif_usb_close(): close bus, delete hif_sc
282  * @ol_sc: soft_sc struct
283  *
284  * Return: none
285  */
286 void hif_usb_close(struct hif_softc *scn)
287 {
288 	g_usb_sc = NULL;
289 }
290 
291 /**
292  * hif_usb_disable_bus(): This function disables usb bus
293  * @hif_ctx: pointer to struct hif_softc
294  *
295  * Return: none
296  */
297 void hif_usb_disable_bus(struct hif_softc *hif_ctx)
298 {
299 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(hif_ctx);
300 	struct usb_interface *interface = sc->interface;
301 	struct usb_device *udev = interface_to_usbdev(interface);
302 	struct hif_target_info *tgt_info = &hif_ctx->target_info;
303 
304 	HIF_TRACE("%s: trying to remove hif_usb!", __func__);
305 
306 	/* disable lpm to avoid following cold reset will
307 	 * cause xHCI U1/U2 timeout
308 	 */
309 	usb_disable_lpm(udev);
310 
311 	/* wait for disable lpm */
312 	set_current_state(TASK_INTERRUPTIBLE);
313 	schedule_timeout(msecs_to_jiffies(DELAY_FOR_TARGET_READY));
314 	set_current_state(TASK_RUNNING);
315 
316 	/* do cold reset */
317 	hif_usb_diag_write_cold_reset(hif_ctx);
318 
319 	if (g_usb_sc->suspend_state)
320 		hif_bus_resume(GET_HIF_OPAQUE_HDL(hif_ctx));
321 
322 	if (tgt_info->target_type != TARGET_TYPE_QCN7605)
323 		unregister_reboot_notifier(&sc->reboot_notifier);
324 
325 	usb_put_dev(interface_to_usbdev(interface));
326 
327 	hif_usb_device_deinit(sc);
328 
329 	HIF_TRACE("%s hif_usb removed !!!!!!", __func__);
330 }
331 
332 /**
333  * hif_usb_bus_suspend() - suspend the bus
334  * @hif_ctx: hif_ctx
335  *
336  * This function suspends the bus, but usb doesn't need to suspend.
337  * Therefore just remove all the pending urb transactions
338  *
339  * Return: 0 for success and non-zero for failure
340  */
341 int hif_usb_bus_suspend(struct hif_softc *hif_ctx)
342 {
343 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(hif_ctx);
344 	struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(hif_ctx);
345 
346 	HIF_ENTER();
347 	sc->suspend_state = 1;
348 	usb_hif_flush_all(device);
349 	HIF_EXIT();
350 	return 0;
351 }
352 
353 /**
354  * hif_usb_bus_resume() - hif resume API
355  * @hif_ctx: struct hif_opaque_softc
356  *
357  * This function resumes the bus. but usb doesn't need to resume.
358  * Post recv urbs for RX data pipe
359  *
360  * Return: 0 for success and non-zero for failure
361  */
362 int hif_usb_bus_resume(struct hif_softc *hif_ctx)
363 {
364 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(hif_ctx);
365 	struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(hif_ctx);
366 
367 	HIF_ENTER();
368 	sc->suspend_state = 0;
369 	usb_hif_start_recv_pipes(device);
370 
371 	HIF_EXIT();
372 	return 0;
373 }
374 
375 /**
376  * hif_usb_bus_reset_resume() - resume the bus after reset
377  * @scn: struct hif_opaque_softc
378  *
379  * This function is called to tell the driver that USB device has been resumed
380  * and it has also been reset. The driver should redo any necessary
381  * initialization. This function resets WLAN SOC.
382  *
383  * Return: int 0 for success, non zero for failure
384  */
385 int hif_usb_bus_reset_resume(struct hif_softc *hif_ctx)
386 {
387 	int ret = 0;
388 
389 	HIF_ENTER();
390 	if (hif_usb_diag_write_cold_reset(hif_ctx) != QDF_STATUS_SUCCESS)
391 		ret = 1;
392 
393 	HIF_EXIT();
394 	return ret;
395 }
396 
397 /**
398  * hif_usb_open()- initialization routine for usb bus
399  * @ol_sc: ol_sc
400  * @bus_type: bus type
401  *
402  * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure
403  */
404 QDF_STATUS hif_usb_open(struct hif_softc *hif_ctx,
405 		enum qdf_bus_type bus_type)
406 {
407 	hif_ctx->bus_type = bus_type;
408 	return QDF_STATUS_SUCCESS;
409 }
410 
411 /**
412  * hif_usb_disable_isr(): disable isr
413  * @hif_ctx: struct hif_softc
414  *
415  * Return: void
416  */
417 void hif_usb_disable_isr(struct hif_softc *hif_ctx)
418 {
419 	/* TODO */
420 }
421 
422 /**
423  * hif_usb_reg_tbl_attach()- attach hif, target register tables
424  * @scn: pointer to ol_softc structure
425  *
426  * Attach host and target register tables based on target_type, target_version
427  *
428  * Return: none
429  */
430 void hif_usb_reg_tbl_attach(struct hif_softc *scn)
431 {
432 	u_int32_t hif_type, target_type;
433 	int32_t ret = 0;
434 	uint32_t chip_id;
435 	QDF_STATUS rv;
436 	struct hif_target_info *tgt_info = &scn->target_info;
437 	struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn);
438 
439 	if (!scn->hostdef && !scn->targetdef) {
440 		switch (tgt_info->target_type) {
441 		case TARGET_TYPE_AR6320:
442 			switch (tgt_info->target_version) {
443 			case AR6320_REV1_VERSION:
444 			case AR6320_REV1_1_VERSION:
445 			case AR6320_REV1_3_VERSION:
446 				hif_type = HIF_TYPE_AR6320;
447 				target_type = TARGET_TYPE_AR6320;
448 				break;
449 			case AR6320_REV2_1_VERSION:
450 			case AR6320_REV3_VERSION:
451 			case QCA9377_REV1_1_VERSION:
452 			case QCA9379_REV1_VERSION:
453 				hif_type = HIF_TYPE_AR6320V2;
454 				target_type = TARGET_TYPE_AR6320V2;
455 				break;
456 			default:
457 				ret = -1;
458 				break;
459 			}
460 			break;
461 		default:
462 			ret = -1;
463 			break;
464 		}
465 
466 		if (ret)
467 			return;
468 
469 		/* assign target register table if we find
470 		 * corresponding type
471 		 */
472 		hif_register_tbl_attach(scn, hif_type);
473 		target_register_tbl_attach(scn, target_type);
474 		/* read the chip revision*/
475 		rv = hif_diag_read_access(hif_hdl,
476 					(CHIP_ID_ADDRESS |
477 					RTC_SOC_BASE_ADDRESS),
478 					&chip_id);
479 		if (rv != QDF_STATUS_SUCCESS) {
480 			HIF_ERROR("%s: get chip id val (%d)", __func__,
481 				rv);
482 		}
483 		tgt_info->target_revision =
484 				CHIP_ID_REVISION_GET(chip_id);
485 	}
486 }
487 
488 /**
489  * hif_usb_get_hw_info()- attach register table for USB
490  * @hif_ctx: pointer to hif_softc structure
491 
492  * This function is used to attach the host and target register tables.
493  * Ideally, we should not attach register tables as a part of this function.
494  * There is scope of cleanup to move register table attach during
495  * initialization for USB bus.
496  *
497  * The reason we are doing register table attach for USB here is that, it relies
498  * on target_info->target_type and target_info->target_version,
499  * which get populated during bmi_firmware_download. "hif_get_fw_info" is the
500  * only initialization related call into HIF there after.
501  *
502  * To fix this, we can move the "get target info, functionality currently in
503  * bmi_firmware_download into hif initialization functions. This change will
504  * affect all buses. Can be taken up as a part of convergence.
505  *
506  * Return: none
507  */
508 void hif_usb_get_hw_info(struct hif_softc *hif_ctx)
509 {
510 	hif_usb_reg_tbl_attach(hif_ctx);
511 }
512 
513 #if defined(CONFIG_PLD_USB_CNSS) && !defined(CONFIG_BYPASS_QMI)
514 /**
515  * hif_bus_configure() - configure the bus
516  * @scn: pointer to the hif context.
517  *
518  * return: 0 for success. nonzero for failure.
519  */
520 int hif_usb_bus_configure(struct hif_softc *scn)
521 {
522 	struct pld_wlan_enable_cfg cfg;
523 	enum pld_driver_mode mode;
524 	uint32_t con_mode = hif_get_conparam(scn);
525 
526 	if (QDF_GLOBAL_FTM_MODE == con_mode)
527 		mode = PLD_FTM;
528 	else if (QDF_GLOBAL_COLDBOOT_CALIB_MODE == con_mode)
529 		mode = PLD_COLDBOOT_CALIBRATION;
530 	else if (QDF_IS_EPPING_ENABLED(con_mode))
531 		mode = PLD_EPPING;
532 	else
533 		mode = PLD_MISSION;
534 
535 	return pld_wlan_enable(scn->qdf_dev->dev, &cfg,
536 			       mode, QWLAN_VERSIONSTR);
537 }
538 #else
539 /**
540  * hif_bus_configure() - configure the bus
541  * @scn: pointer to the hif context.
542  *
543  * return: 0 for success. nonzero for failure.
544  */
545 int hif_usb_bus_configure(struct hif_softc *scn)
546 {
547 	return 0;
548 }
549 #endif
550 
551 /**
552  * hif_usb_irq_enable() - hif_usb_irq_enable
553  * @scn: hif_softc
554  * @ce_id: ce_id
555  *
556  * Return: void
557  */
558 void hif_usb_irq_enable(struct hif_softc *scn, int ce_id)
559 {
560 }
561 
562 /**
563  * hif_usb_irq_disable() - hif_usb_irq_disable
564  * @scn: hif_softc
565  * @ce_id: ce_id
566  *
567  * Return: void
568  */
569 void hif_usb_irq_disable(struct hif_softc *scn, int ce_id)
570 {
571 }
572 
573 /**
574  * hif_usb_shutdown_bus_device() - This function shuts down the device
575  * @scn: hif opaque pointer
576  *
577  * Return: void
578  */
579 void hif_usb_shutdown_bus_device(struct hif_softc *scn)
580 {
581 }
582 
583 /**
584  * hif_trigger_dump() - trigger various dump cmd
585  * @scn: struct hif_opaque_softc
586  * @cmd_id: dump command id
587  * @start: start/stop dump
588  *
589  * Return: None
590  */
591 void hif_trigger_dump(struct hif_opaque_softc *scn, uint8_t cmd_id, bool start)
592 {
593 }
594 
595 /**
596  * hif_wlan_disable() - call the platform driver to disable wlan
597  * @scn: scn
598  *
599  * Return: void
600  */
601 void hif_wlan_disable(struct hif_softc *scn)
602 {
603 }
604 
605 /**
606  * hif_fw_assert_ramdump_pattern() - handle firmware assert with ramdump pattern
607  * @sc: pointer to hif_usb_softc structure
608  *
609  * Return: void
610  */
611 
612 void hif_fw_assert_ramdump_pattern(struct hif_usb_softc *sc)
613 {
614 	uint32_t *reg, pattern, i = 0;
615 	uint32_t len;
616 	uint8_t *data;
617 	uint8_t *ram_ptr = NULL;
618 	char *fw_ram_seg_name[FW_RAM_SEG_CNT] = {"DRAM", "IRAM", "AXI"};
619 	size_t fw_ram_reg_size[FW_RAM_SEG_CNT] = {
620 				  FW_RAMDUMP_DRAMSIZE,
621 				  FW_RAMDUMP_IRAMSIZE,
622 				  FW_RAMDUMP_AXISIZE };
623 
624 	data = sc->fw_data;
625 	len = sc->fw_data_len;
626 	pattern = *((uint32_t *) data);
627 
628 	qdf_assert(sc->ramdump_index < FW_RAM_SEG_CNT);
629 	i = sc->ramdump_index;
630 	reg = (uint32_t *) (data + 4);
631 	if (sc->fw_ram_dumping == 0) {
632 		sc->fw_ram_dumping = 1;
633 		HIF_ERROR("Firmware %s dump:\n", fw_ram_seg_name[i]);
634 		sc->ramdump[i] =
635 			qdf_mem_malloc(sizeof(struct fw_ramdump) +
636 					fw_ram_reg_size[i]);
637 		if (!sc->ramdump[i])
638 			QDF_BUG(0);
639 
640 		(sc->ramdump[i])->mem = (uint8_t *) (sc->ramdump[i] + 1);
641 		fw_ram_seg_addr[i] = (sc->ramdump[i])->mem;
642 		HIF_ERROR("FW %s start addr = %#08x\n",
643 			fw_ram_seg_name[i], *reg);
644 		HIF_ERROR("Memory addr for %s = %pK\n",
645 			fw_ram_seg_name[i],
646 			(sc->ramdump[i])->mem);
647 		(sc->ramdump[i])->start_addr = *reg;
648 		(sc->ramdump[i])->length = 0;
649 	}
650 	reg++;
651 	ram_ptr = (sc->ramdump[i])->mem + (sc->ramdump[i])->length;
652 	(sc->ramdump[i])->length += (len - 8);
653 	if (sc->ramdump[i]->length <= fw_ram_reg_size[i]) {
654 		qdf_mem_copy(ram_ptr, (uint8_t *) reg, len - 8);
655 	} else {
656 		HIF_ERROR("memory copy overlap\n");
657 		QDF_BUG(0);
658 	}
659 
660 	if (pattern == FW_RAMDUMP_END_PATTERN) {
661 		HIF_ERROR("%s memory size = %d\n", fw_ram_seg_name[i],
662 				(sc->ramdump[i])->length);
663 		if (i == (FW_RAM_SEG_CNT - 1))
664 			QDF_BUG(0);
665 
666 		sc->ramdump_index++;
667 		sc->fw_ram_dumping = 0;
668 	}
669 }
670 
671 /**
672  * hif_usb_ramdump_handler(): dump bus debug registers
673  * @scn: struct hif_opaque_softc
674  *
675  * This function is to receive information of firmware crash dump, and
676  * save it in host memory. It consists of 5 parts: registers, call stack,
677  * DRAM dump, IRAM dump, and AXI dump, and they are reported to host in order.
678  *
679  * registers: wrapped in a USB packet by starting as FW_ASSERT_PATTERN and
680  *            60 registers.
681  * call stack: wrapped in multiple USB packets, and each of them starts as
682  *             FW_REG_PATTERN and contains multiple double-words. The tail
683  *             of the last packet is FW_REG_END_PATTERN.
684  * DRAM dump: wrapped in multiple USB pakcets, and each of them start as
685  *            FW_RAMDUMP_PATTERN and contains multiple double-wors. The tail
686  *            of the last packet is FW_RAMDUMP_END_PATTERN;
687  * IRAM dump and AXI dump are with the same format as DRAM dump.
688  *
689  * Return: 0 for success or error code
690  */
691 
692 void hif_usb_ramdump_handler(struct hif_opaque_softc *scn)
693 {
694 	uint32_t *reg, pattern, i, start_addr = 0;
695 	uint32_t len;
696 	uint8_t *data;
697 	uint8_t str_buf[128];
698 	uint32_t remaining;
699 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(scn);
700 	struct hif_softc *hif_ctx = HIF_GET_SOFTC(scn);
701 	struct hif_target_info *tgt_info = &hif_ctx->target_info;
702 
703 	data = sc->fw_data;
704 	len = sc->fw_data_len;
705 	pattern = *((uint32_t *) data);
706 
707 	if (pattern == FW_ASSERT_PATTERN) {
708 		HIF_ERROR("Firmware crash detected...\n");
709 		HIF_ERROR("Host SW version: %s\n", QWLAN_VERSIONSTR);
710 		HIF_ERROR("target_type: %d.target_version %d. target_revision%d.",
711 			tgt_info->target_type,
712 			tgt_info->target_version,
713 			tgt_info->target_revision);
714 
715 		reg = (uint32_t *) (data + 4);
716 		print_hex_dump(KERN_DEBUG, " ", DUMP_PREFIX_OFFSET, 16, 4, reg,
717 				min_t(uint32_t, len - 4, FW_REG_DUMP_CNT * 4),
718 				false);
719 		sc->fw_ram_dumping = 0;
720 
721 	} else if (pattern == FW_REG_PATTERN) {
722 		reg = (uint32_t *) (data + 4);
723 		start_addr = *reg++;
724 		if (sc->fw_ram_dumping == 0) {
725 			pr_err("Firmware stack dump:");
726 			sc->fw_ram_dumping = 1;
727 			fw_stack_addr = start_addr;
728 		}
729 		remaining = len - 8;
730 		/* len is in byte, but it's printed in double-word. */
731 		for (i = 0; i < (len - 8); i += 16) {
732 			if ((*reg == FW_REG_END_PATTERN) && (i == len - 12)) {
733 				sc->fw_ram_dumping = 0;
734 				pr_err("Stack start address = %#08x\n",
735 					fw_stack_addr);
736 				break;
737 			}
738 			hex_dump_to_buffer(reg, remaining, 16, 4, str_buf,
739 						sizeof(str_buf), false);
740 			pr_err("%#08x: %s\n", start_addr + i, str_buf);
741 			remaining -= 16;
742 			reg += 4;
743 		}
744 	} else if ((!sc->enable_self_recovery) &&
745 			((pattern & FW_RAMDUMP_PATTERN_MASK) ==
746 						FW_RAMDUMP_PATTERN)) {
747 		hif_fw_assert_ramdump_pattern(sc);
748 	}
749 }
750 
751 #ifndef QCA_WIFI_3_0
752 /**
753  * hif_check_fw_reg(): hif_check_fw_reg
754  * @scn: scn
755  * @state:
756  *
757  * Return: int
758  */
759 int hif_check_fw_reg(struct hif_opaque_softc *scn)
760 {
761 	return 0;
762 }
763 #endif
764 
765 /**
766  * hif_usb_needs_bmi() - return true if the soc needs bmi through the driver
767  * @scn: hif context
768  *
769  * Return: true if soc needs driver bmi otherwise false
770  */
771 bool hif_usb_needs_bmi(struct hif_softc *scn)
772 {
773 	struct hif_target_info *tgt_info = &scn->target_info;
774 
775 	/* BMI is not supported in Genoa */
776 	if (tgt_info->target_type == TARGET_TYPE_QCN7605)
777 		return false;
778 
779 	return true;
780 }
781