summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChien-Ming Chen <mingc@qca.qualcomm.com>2014-11-25 17:44:53 +0800
committerAnjaneeDevi Kapparapu <c_akappa@qti.qualcomm.com>2014-12-01 16:19:24 +0530
commit350abab61a9ddaba7d9e5e5bc705f752f0662e0d (patch)
tree6be8b0c00631465bfb4a64cfdf3bab20ffbc5ce2
parentd78975a6b4da8d8723690b433a7564730f115551 (diff)
qcacld: Fix USB SSR failure from target assertion
USB SSR uses uevent to trigger unloading/loading driver again. It could meet the timing issue due to target's cold reset. To prevent this race condition, issuing the uevent in usb disconnect cb function. To ensure that usb probe is completed after cold reset, adding delay to check it in usb probe function. Change-Id: I8c2acc05e0e367c073d7b27a5223d375b26724cb CRs-Fixed: 762484
-rw-r--r--CORE/SERVICES/BMI/ol_fw.c9
-rw-r--r--CORE/SERVICES/HIF/USB/if_usb.c17
2 files changed, 25 insertions, 1 deletions
diff --git a/CORE/SERVICES/BMI/ol_fw.c b/CORE/SERVICES/BMI/ol_fw.c
index f32ba8f88619..6da6486006f9 100644
--- a/CORE/SERVICES/BMI/ol_fw.c
+++ b/CORE/SERVICES/BMI/ol_fw.c
@@ -1072,6 +1072,13 @@ void ol_ramdump_handler(struct ol_softc *scn)
pr_err("Firmware crash detected...\n");
pr_err("Host SW version: %s\n", QWLAN_VERSIONSTR);
pr_err("FW version: %d.%d.%d.%d", MSPId, mSPId, SIId, CRMId);
+
+ if (vos_is_load_unload_in_progress(VOS_MODULE_ID_VOSS, NULL)) {
+ printk("%s: Loading/Unloading is in progress, ignore!\n",
+ __func__);
+ return;
+ }
+
reg = (A_UINT32 *) (data + 4);
print_hex_dump(KERN_DEBUG, " ", DUMP_PREFIX_OFFSET, 16, 4, reg,
min_t(A_UINT32, len - 4, FW_REG_DUMP_CNT * 4),
@@ -1079,7 +1086,7 @@ void ol_ramdump_handler(struct ol_softc *scn)
scn->fw_ram_dumping = 0;
if (scn->enableFwSelfRecovery)
- kobject_uevent(&scn->adf_dev->dev->kobj, KOBJ_OFFLINE);
+ vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, TRUE);
}
else if (pattern == FW_REG_PATTERN) {
reg = (A_UINT32 *) (data + 4);
diff --git a/CORE/SERVICES/HIF/USB/if_usb.c b/CORE/SERVICES/HIF/USB/if_usb.c
index 6fde4c865e38..da81b57debdf 100644
--- a/CORE/SERVICES/HIF/USB/if_usb.c
+++ b/CORE/SERVICES/HIF/USB/if_usb.c
@@ -256,6 +256,15 @@ static void hif_usb_remove(struct usb_interface *interface)
HIF_USB_UNLOAD_STATE_TARGET_RESET);
scn = sc->ol_sc;
+ /* The logp is set by target failure's ol_ramdump_handler.
+ * Coldreset occurs and do this disconnect cb, try to issue
+ * offline uevent to restart driver.
+ */
+ if (vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL)) {
+ /* dispatch 'offline' uevent to restart module */
+ kobject_uevent(&scn->adf_dev->dev->kobj, KOBJ_OFFLINE);
+ vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
+ }
if (atomic_inc_and_test(&usb_sc->hdd_removed)) {
atomic_set(&usb_sc->hdd_removed_processing, 1);
@@ -267,6 +276,7 @@ static void hif_usb_remove(struct usb_interface *interface)
__hdd_wlan_exit();
atomic_set(&usb_sc->hdd_removed_processing, 0);
}
+
hif_nointrs(sc);
HIF_USBDeviceDetached(interface, 1);
hif_deinit_adf_ctx(scn);
@@ -462,12 +472,19 @@ static int is_usb_driver_register = 0;
int hif_register_driver(void)
{
int status = 0;
+ int probe_wait_cnt = 0;
is_usb_driver_register = 1;
init_waitqueue_head(&hif_usb_unload_event_wq);
atomic_set(&hif_usb_unload_state, HIF_USB_UNLOAD_STATE_NULL);
usb_register_notify(&hif_usb_dev_nb);
status = usb_register(&hif_usb_drv_id);
+ /* wait for usb probe done, 2s at most*/
+ while(!usb_sc && probe_wait_cnt < 10) {
+ A_MSLEEP(200);
+ probe_wait_cnt++;
+ }
+
if (usb_sc && status == 0)
return 0;
else