| --- a/driver/wl_linux.c |
| +++ b/driver/wl_linux.c |
| @@ -354,6 +354,7 @@ static int wl_read_proc(char *buffer, ch |
| static int wl_dump(wl_info_t *wl, struct bcmstrbuf *b); |
| #endif /* BCMDBG */ |
| struct wl_if *wl_alloc_if(wl_info_t *wl, int iftype, uint unit, struct wlc_if* wlc_if); |
| +static void wl_link_if(wl_info_t *wl, wl_if_t *wlif); |
| static void wl_free_if(wl_info_t *wl, wl_if_t *wlif); |
| |
| |
| @@ -566,6 +567,9 @@ wl_attach(uint16 vendor, uint16 device, |
| wl->dev = dev; |
| wl_if_setup(dev); |
| |
| + /* add the interface to the interface linked list */ |
| + wl_link_if(wl, wlif); |
| + |
| /* map chip registers (47xx: and sprom) */ |
| dev->base_addr = regs; |
| |
| @@ -1106,10 +1110,14 @@ wl_free(wl_info_t *wl) |
| free_irq(wl->dev->irq, wl); |
| } |
| |
| - if (wl->dev) { |
| - wl_free_if(wl, WL_DEV_IF(wl->dev)); |
| - wl->dev = NULL; |
| + /* free all interfaces */ |
| + while (wl->if_list) { |
| + if ((wl->if_list->dev != wl->dev) || wl->if_list->next == NULL) |
| + wl_free_if(wl, wl->if_list); |
| + else |
| + wl_free_if(wl, wl->if_list->next); |
| } |
| + wl->dev = NULL; |
| |
| #ifdef TOE |
| wl_toe_detach(wl->toei); |
| @@ -1355,10 +1363,12 @@ wl_txflowcontrol(wl_info_t *wl, bool sta |
| |
| ASSERT(prio == ALLPRIO); |
| for (wlif = wl->if_list; wlif != NULL; wlif = wlif->next) { |
| - if (state == ON) |
| - netif_stop_queue(wlif->dev); |
| - else |
| - netif_wake_queue(wlif->dev); |
| + if (wlif->dev_registed) { |
| + if (state == ON) |
| + netif_stop_queue(wlif->dev); |
| + else |
| + netif_wake_queue(wlif->dev); |
| + } |
| } |
| } |
| |
| @@ -1398,7 +1408,6 @@ wl_alloc_if(wl_info_t *wl, int iftype, u |
| { |
| struct net_device *dev; |
| wl_if_t *wlif; |
| - wl_if_t *p; |
| |
| dev = alloc_etherdev(sizeof(wl_if_t)); |
| wlif = netdev_priv(dev); |
| @@ -1411,9 +1420,13 @@ wl_alloc_if(wl_info_t *wl, int iftype, u |
| wlif->wlcif = wlcif; |
| wlif->subunit = subunit; |
| |
| - /* match current flow control state */ |
| - if (iftype != WL_IFTYPE_MON && wl->dev && netif_queue_stopped(wl->dev)) |
| - netif_stop_queue(dev); |
| + return wlif; |
| +} |
| + |
| +static void |
| +wl_link_if(wl_info_t *wl, wl_if_t *wlif) |
| +{ |
| + wl_if_t *p; |
| |
| /* add the interface to the interface linked list */ |
| if (wl->if_list == NULL) |
| @@ -1424,7 +1437,6 @@ wl_alloc_if(wl_info_t *wl, int iftype, u |
| p = p->next; |
| p->next = wlif; |
| } |
| - return wlif; |
| } |
| |
| static void |
| @@ -1504,6 +1516,9 @@ _wl_add_if(wl_task_t *task) |
| wl_info_t *wl = wlif->wl; |
| struct net_device *dev = wlif->dev; |
| |
| + /* add the interface to the interface linked list */ |
| + wl_link_if(wl, wlif); |
| + |
| if (wlif->type == WL_IFTYPE_WDS) |
| dev->netdev_ops = &wl_wds_ops; |
| |
| @@ -1516,6 +1531,14 @@ _wl_add_if(wl_task_t *task) |
| } |
| wlif->dev_registed = TRUE; |
| |
| + /* match current flow control state */ |
| + if (wl->dev) { |
| + if (netif_queue_stopped(wl->dev)) |
| + netif_stop_queue(dev); |
| + else |
| + netif_wake_queue(dev); |
| + } |
| + |
| done: |
| MFREE(wl->osh, task, sizeof(wl_task_t)); |
| atomic_dec(&wl->callbacks); |
| @@ -1545,6 +1568,8 @@ wl_add_if(wl_info_t *wl, struct wlc_if* |
| return NULL; |
| } |
| |
| + wl_if_setup(wlif->dev); |
| + |
| sprintf(wlif->dev->name, "%s%d.%d", devname, wl->pub->unit, wlif->subunit); |
| if (remote) |
| bcopy(remote, &wlif->remote, ETHER_ADDR_LEN); |
| @@ -2778,6 +2803,9 @@ wl_add_monitor(wl_task_t *task) |
| dev = wlif->dev; |
| wl->monitor = dev; |
| |
| + /* add the interface to the interface linked list */ |
| + wl_link_if(wl, wlif); |
| + |
| /* override some fields */ |
| sprintf(dev->name, "prism%d", wl->pub->unit); |
| bcopy(wl->dev->dev_addr, dev->dev_addr, ETHER_ADDR_LEN); |