diff options
Diffstat (limited to 'drivers/net/wireless/bcmdhd/dhd_linux.c')
-rw-r--r-- | drivers/net/wireless/bcmdhd/dhd_linux.c | 50 |
1 files changed, 30 insertions, 20 deletions
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 5d35f78cf2a..03ba34a2c82 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -443,11 +443,9 @@ static void dhd_htsf_addrxts(dhd_pub_t *dhdp, void *pktbuf); static void dhd_dump_htsfhisto(histo_t *his, char *s); #endif /* WLMEDIA_HTSF */ -extern s32 wl_cfg80211_ifdel_ops(struct net_device *net); - /* Monitor interface */ -extern int dhd_monitor_init(void *dhd_pub); -extern int dhd_monitor_uninit(void); +int dhd_monitor_init(void *dhd_pub); +int dhd_monitor_uninit(void); #if defined(CONFIG_WIRELESS_EXT) @@ -673,7 +671,7 @@ dhd_timeout_expired(dhd_timeout_t *tmo) return 0; } -static int +int dhd_net2idx(dhd_info_t *dhd, struct net_device *net) { int i = 0; @@ -971,7 +969,8 @@ dhd_op_if(dhd_if_t *ifp) memcpy(netdev_priv(ifp->net), &dhd, sizeof(dhd)); #ifdef WL_CFG80211 if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) - if (!wl_cfg80211_notify_ifadd(ifp->net, ifp->idx, dhd_net_attach)) { + if (!wl_cfg80211_notify_ifadd(ifp->net, ifp->idx, ifp->bssidx, + dhd_net_attach)) { ifp->state = 0; return; } @@ -1023,10 +1022,10 @@ dhd_op_if(dhd_if_t *ifp) free_netdev(ifp->net); } dhd->iflist[ifp->idx] = NULL; - MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); #ifdef WL_CFG80211 - if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) + if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { wl_cfg80211_notify_ifdel(ifp->net); + } #endif #ifdef SOFTAP flags = dhd_os_spin_lock(&dhd->pub); @@ -1034,6 +1033,7 @@ dhd_op_if(dhd_if_t *ifp) ap_net_dev = NULL; /* NULL SOFTAP global wl0.1 as well */ dhd_os_spin_unlock(&dhd->pub, flags); #endif /* SOFTAP */ + MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); } } @@ -1385,7 +1385,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) struct sk_buff *skb; uchar *eth; uint len; - void *data, *pnext, *save_pktbuf; + void *data, *pnext = NULL, *save_pktbuf; int i; dhd_if_t *ifp; wl_event_msg_t event; @@ -1398,6 +1398,16 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) struct ether_header *eh; struct dot11_llc_snap_header *lsh; + ifp = dhd->iflist[ifidx]; + + /* Dropping packets before registering net device to avoid kernel panic */ + if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) { + DHD_ERROR(("%s: net device is NOT registered yet. drop packet\n", + __FUNCTION__)); + PKTFREE(dhdp->osh, pktbuf, TRUE); + continue; + } + pnext = PKTNEXT(dhdp->osh, pktbuf); PKTSETNEXT(wl->sh.osh, pktbuf, NULL); @@ -1487,14 +1497,6 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) dhdp->dstats.rx_bytes += skb->len; dhdp->rx_packets++; /* Local count */ - /* Dropping packets before registering net device to avoid kernel panic */ - if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) { - DHD_ERROR(("%s: net device is NOT registered yet. drop [%s] packet\n", - __FUNCTION__, (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) ? "event" : "data")); - PKTFREE(dhdp->osh, pktbuf, TRUE); - continue; - } - if (in_interrupt()) { netif_rx(skb); } else { @@ -2355,6 +2357,7 @@ dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name, if (handle == NULL) { ifp->state = WLC_E_IF_ADD; ifp->idx = ifidx; + ifp->bssidx = bssidx; ASSERT(&dhd->thr_sysioc_ctl.thr_pid >= 0); up(&dhd->thr_sysioc_ctl.sema); } else @@ -3057,6 +3060,7 @@ void dhd_detach(dhd_pub_t *dhdp) { dhd_info_t *dhd; unsigned long flags; + int timer_valid = FALSE; if (!dhdp) return; @@ -3118,17 +3122,23 @@ void dhd_detach(dhd_pub_t *dhdp) if (ifp->net->netdev_ops == &dhd_ops_pri) #endif { - unregister_netdev(ifp->net); + if (ifp->net) { + unregister_netdev(ifp->net); + free_netdev(ifp->net); + ifp->net = NULL; + } MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); - + dhd->iflist[0] = NULL; } } /* Clear the watchdog timer */ flags = dhd_os_spin_lock(&dhd->pub); + timer_valid = dhd->wd_timer_valid; dhd->wd_timer_valid = FALSE; dhd_os_spin_unlock(&dhd->pub, flags); - del_timer_sync(&dhd->timer); + if (timer_valid) + del_timer_sync(&dhd->timer); if (dhd->dhd_state & DHD_ATTACH_STATE_THREADS_CREATED) { #ifdef DHDTHREAD |