From 325c547f8b9797b9dfe253b8147b54dc4691109b Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Wed, 21 Jul 2010 18:49:49 -0700 Subject: [PATCH] net: wireless: bcm4329: Add wakelock processing in ioctl and messaging Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcm4329/dhd_linux.c | 31 ++++++++--- drivers/net/wireless/bcm4329/wl_iw.c | 65 +++++++++++++++--------- 2 files changed, 66 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/bcm4329/dhd_linux.c b/drivers/net/wireless/bcm4329/dhd_linux.c index 48c2ef777b13..00f545045cdc 100644 --- a/drivers/net/wireless/bcm4329/dhd_linux.c +++ b/drivers/net/wireless/bcm4329/dhd_linux.c @@ -1082,6 +1082,8 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + dhd_os_wake_lock(&dhd->pub); + /* Reject if down */ if (!dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN)) { DHD_ERROR(("%s: xmit rejected pub.up=%d busstate=%d\n", @@ -1092,6 +1094,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) DHD_ERROR(("%s: Event HANG send up\n", __FUNCTION__)); wl_iw_send_priv_event(net, "HANG"); } + dhd_os_wake_unlock(&dhd->pub); return -ENODEV; } @@ -1099,6 +1102,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) if (ifidx == DHD_BAD_IF) { DHD_ERROR(("%s: bad ifidx %d\n", __FUNCTION__, ifidx)); netif_stop_queue(net); + dhd_os_wake_unlock(&dhd->pub); return -ENODEV; } @@ -1130,13 +1134,14 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) ret = dhd_sendpkt(&dhd->pub, ifidx, pktbuf); - done: if (ret) dhd->pub.dstats.tx_dropped++; else dhd->pub.tx_packets++; + dhd_os_wake_unlock(&dhd->pub); + /* Return ok: we always eat the packet */ return 0; } @@ -1666,28 +1671,40 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) uint driver = 0; int ifidx; bool is_set_key_cmd; + int ret; + + dhd_os_wake_lock(&dhd->pub); ifidx = dhd_net2idx(dhd, net); DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd)); - if (ifidx == DHD_BAD_IF) + if (ifidx == DHD_BAD_IF) { + dhd_os_wake_unlock(&dhd->pub); return -1; + } #if defined(CONFIG_WIRELESS_EXT) /* linux wireless extensions */ if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { /* may recurse, do NOT lock */ - return wl_iw_ioctl(net, ifr, cmd); + ret = wl_iw_ioctl(net, ifr, cmd); + dhd_os_wake_unlock(&dhd->pub); + return ret; } #endif /* defined(CONFIG_WIRELESS_EXT) */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) - if (cmd == SIOCETHTOOL) - return (dhd_ethtool(dhd, (void*)ifr->ifr_data)); + if (cmd == SIOCETHTOOL) { + ret = dhd_ethtool(dhd, (void*)ifr->ifr_data); + dhd_os_wake_unlock(&dhd->pub); + return ret; + } #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */ - if (cmd != SIOCDEVPRIVATE) + if (cmd != SIOCDEVPRIVATE) { + dhd_os_wake_unlock(&dhd->pub); return -EOPNOTSUPP; + } memset(&ioc, 0, sizeof(ioc)); @@ -1779,6 +1796,8 @@ done: if (buf) MFREE(dhd->pub.osh, buf, buflen); + dhd_os_wake_unlock(&dhd->pub); + return OSL_ERROR(bcmerror); } diff --git a/drivers/net/wireless/bcm4329/wl_iw.c b/drivers/net/wireless/bcm4329/wl_iw.c index 98133bbf4b6a..03385bb5f56b 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.c +++ b/drivers/net/wireless/bcm4329/wl_iw.c @@ -308,6 +308,8 @@ dev_wlc_ioctl( return ret; } + net_os_wake_lock(dev); + WL_TRACE(("%s, PID:%x: send Local IOCTL -> dhd: cmd:0x%x, buf:%p, len:%d ,\n", __FUNCTION__, current->pid, cmd, arg, len)); @@ -323,6 +325,7 @@ dev_wlc_ioctl( ret = dev_open(dev); if (ret) { WL_ERROR(("%s: Error dev_open: %d\n", __func__, ret)); + net_os_wake_unlock(dev); return ret; } @@ -338,6 +341,9 @@ dev_wlc_ioctl( else { WL_TRACE(("%s: call after driver stop\n", __FUNCTION__)); } + + net_os_wake_unlock(dev); + return ret; } @@ -941,6 +947,7 @@ wl_iw_send_priv_event( strcpy(extra, flag); wrqu.data.length = strlen(extra); wireless_send_event(dev, cmd, &wrqu, extra); + net_os_wake_lock_timeout_enable(dev); WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra)); return 0; @@ -1031,8 +1038,6 @@ wl_iw_control_wl_off( dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); wl_iw_send_priv_event(dev, "STOP"); - - net_os_wake_lock_timeout_enable(dev); } mutex_unlock(&wl_start_lock); @@ -1064,8 +1069,6 @@ wl_iw_control_wl_on( wl_iw_iscan_set_scan_broadcast_prep(dev, 0); #endif - net_os_wake_lock_timeout_enable(dev); - WL_TRACE(("Exited %s \n", __FUNCTION__)); return ret; @@ -2264,13 +2267,15 @@ _iscan_sysioc_thread(void *data) status = WL_SCAN_RESULTS_PARTIAL; while (down_interruptible(&iscan->sysioc_sem) == 0) { + net_os_wake_lock(iscan->dev); + #if defined(SOFTAP) if (ap_cfg_running) { WL_TRACE(("%s skipping SCAN ops in AP mode !!!\n", __FUNCTION__)); + net_os_wake_unlock(iscan->dev); continue; } #endif - net_os_wake_lock(iscan->dev); if (iscan->timer_on) { iscan->timer_on = 0; @@ -5134,7 +5139,7 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap) return -1; } - net_os_wake_lock(dev); + net_os_wake_lock(dev); WL_SOFTAP(("wl_iw: set ap profile:\n")); WL_SOFTAP((" ssid = '%s'\n", ap->ssid)); @@ -5269,9 +5274,9 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap) fail: WL_SOFTAP(("%s exit with %d\n", __FUNCTION__, res)); - net_os_wake_unlock(dev); + net_os_wake_unlock(dev); - return res; + return res; } @@ -5555,10 +5560,10 @@ static int iwpriv_softap_stop(struct net_device *dev, return res; } - net_os_wake_lock(dev); + net_os_wake_lock(dev); if ((ap_cfg_running == TRUE)) { - wl_iw_softap_deassoc_stations(ap_net_dev); + wl_iw_softap_deassoc_stations(ap_net_dev); if ((res = dev_iw_write_cfg1_bss_var(dev, 2)) < 0) WL_ERROR(("%s failed to del BSS err = %d", __FUNCTION__, res)); @@ -5573,9 +5578,9 @@ static int iwpriv_softap_stop(struct net_device *dev, WL_SOFTAP(("%s Done with %d\n", __FUNCTION__, res)); - net_os_wake_unlock(dev); + net_os_wake_unlock(dev); - return res; + return res; } @@ -5685,7 +5690,7 @@ iwpriv_en_ap_bss( return -1; } - net_os_wake_lock(dev); + net_os_wake_lock(dev); WL_TRACE(("%s: rcvd IWPRIV IOCTL: for dev:%s\n", __FUNCTION__, dev->name)); @@ -5701,7 +5706,7 @@ iwpriv_en_ap_bss( WL_SOFTAP(("%s done with res %d \n", __FUNCTION__, res)); - net_os_wake_unlock(dev); + net_os_wake_unlock(dev); return res; } @@ -6210,11 +6215,14 @@ int wl_iw_ioctl( char *extra = NULL; int token_size = 1, max_tokens = 0, ret = 0; + net_os_wake_lock(dev); + WL_TRACE(("%s: cmd:%x alled via dhd->do_ioctl()entry point\n", __FUNCTION__, cmd)); if (cmd < SIOCIWFIRST || IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) || !(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)])) { WL_ERROR(("%s: error in cmd=%x : not supported\n", __FUNCTION__, cmd)); + net_os_wake_unlock(dev); return -EOPNOTSUPP; } @@ -6279,14 +6287,18 @@ int wl_iw_ioctl( if (wrq->u.data.length > max_tokens) { WL_ERROR(("%s: error in cmd=%x wrq->u.data.length=%d > max_tokens=%d\n", \ __FUNCTION__, cmd, wrq->u.data.length, max_tokens)); - return -E2BIG; + ret = -E2BIG; + goto wl_iw_ioctl_done; + } + if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL))) { + ret = -ENOMEM; + goto wl_iw_ioctl_done; } - if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL))) - return -ENOMEM; if (copy_from_user(extra, wrq->u.data.pointer, wrq->u.data.length * token_size)) { kfree(extra); - return -EFAULT; + ret = -EFAULT; + goto wl_iw_ioctl_done; } } @@ -6298,12 +6310,17 @@ int wl_iw_ioctl( if (extra) { if (copy_to_user(wrq->u.data.pointer, extra, wrq->u.data.length * token_size)) { kfree(extra); - return -EFAULT; + ret = -EFAULT; + goto wl_iw_ioctl_done; } kfree(extra); } +wl_iw_ioctl_done: + + net_os_wake_unlock(dev); + return ret; } @@ -6429,7 +6446,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) return; } - net_os_wake_lock(dev); + net_os_wake_lock(dev); WL_TRACE(("%s: dev=%s event=%d \n", __FUNCTION__, dev->name, event_type)); @@ -6516,7 +6533,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); bzero(&extra, ETHER_ADDR_LEN); - net_os_wake_lock_timeout_enable(dev); } else { memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN); @@ -6535,6 +6551,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) WL_TRACE(("Link UP\n")); } + net_os_wake_lock_timeout_enable(dev); wrqu.addr.sa_family = ARPHRD_ETHER; break; case WLC_E_ACTION_FRAME: @@ -6652,8 +6669,8 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) } #endif wl_iw_event_end: - net_os_wake_unlock(dev); -#endif + net_os_wake_unlock(dev); +#endif } int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats) @@ -6821,7 +6838,7 @@ _bt_dhcp_sysioc_thread(void *data) g_bt->bt_state = BT_DHCP_IDLE; g_bt->timer_on = 0; break; - } + } net_os_wake_unlock(g_bt->dev); } -- 2.34.1