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