if_usb.c 18 KB

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