From: Dmitry Shmidt Date: Mon, 2 Apr 2012 17:27:13 +0000 (-0700) Subject: net: wireless: bcmdhd: Move FW hang processign to work queue X-Git-Tag: firefly_0821_release~7613^2~148 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=1dd49da642eb92855fe41a30f8e1e50e70dbac8e;p=firefly-linux-kernel-4.4.55.git net: wireless: bcmdhd: Move FW hang processign to work queue Signed-off-by: Dmitry Shmidt --- diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 0205e7ce6017..1e28fb88d721 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -129,6 +129,9 @@ DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait); #if defined(OOB_INTR_ONLY) extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable); #endif /* defined(OOB_INTR_ONLY) */ + +static void dhd_hang_process(struct work_struct *work); + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) MODULE_LICENSE("GPL v2"); #endif /* LinuxVer */ @@ -247,6 +250,7 @@ typedef struct dhd_info { bool dhd_tasklet_create; #endif /* DHDTHREAD */ tsk_ctl_t thr_sysioc_ctl; + struct work_struct work_hang; /* Wakelocks */ #if defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) @@ -2750,6 +2754,8 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) } dhd_state |= DHD_ATTACH_STATE_THREADS_CREATED; + INIT_WORK(&dhd->work_hang, dhd_hang_process); + /* * Save the dhd_info into the priv */ @@ -3632,6 +3638,8 @@ void dhd_detach(dhd_pub_t *dhdp) } #endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ + cancel_work_sync(&dhd->work_hang); + #if defined(WL_WIRELESS_EXT) if (dhd->dhd_state & DHD_ATTACH_STATE_WL_ATTACH) { /* Detatch and unlink in the iw */ @@ -4443,29 +4451,37 @@ dhd_dev_get_pno_status(struct net_device *dev) #endif /* PNO_SUPPORT */ +static void dhd_hang_process(struct work_struct *work) +{ + dhd_info_t *dhd; + struct net_device *dev; + + dhd = (dhd_info_t *)container_of(work, dhd_info_t, work_hang); + dev = dhd->iflist[0]->net; + + if (dev) { + rtnl_lock(); + dev_close(dev); + rtnl_unlock(); +#if defined(WL_WIRELESS_EXT) + wl_iw_send_priv_event(dev, "HANG"); +#endif +#if defined(WL_CFG80211) + wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); +#endif + } +} + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) int net_os_send_hang_message(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); int ret = 0; - int need_unlock = 0; if (dhd) { if (!dhd->pub.hang_was_sent) { dhd->pub.hang_was_sent = 1; - if (!rtnl_is_locked()) { - need_unlock = 1; - rtnl_lock(); - } - dev_close(dev); - if (need_unlock) - rtnl_unlock(); -#if defined(WL_WIRELESS_EXT) - ret = wl_iw_send_priv_event(dev, "HANG"); -#endif -#if defined(WL_CFG80211) - ret = wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); -#endif + schedule_work(&dhd->work_hang); } } return ret;