b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | --- a/driver/wl_linux.c |
| 2 | +++ b/driver/wl_linux.c |
| 3 | @@ -354,6 +354,7 @@ static int wl_read_proc(char *buffer, ch |
| 4 | static int wl_dump(wl_info_t *wl, struct bcmstrbuf *b); |
| 5 | #endif /* BCMDBG */ |
| 6 | struct wl_if *wl_alloc_if(wl_info_t *wl, int iftype, uint unit, struct wlc_if* wlc_if); |
| 7 | +static void wl_link_if(wl_info_t *wl, wl_if_t *wlif); |
| 8 | static void wl_free_if(wl_info_t *wl, wl_if_t *wlif); |
| 9 | |
| 10 | |
| 11 | @@ -566,6 +567,9 @@ wl_attach(uint16 vendor, uint16 device, |
| 12 | wl->dev = dev; |
| 13 | wl_if_setup(dev); |
| 14 | |
| 15 | + /* add the interface to the interface linked list */ |
| 16 | + wl_link_if(wl, wlif); |
| 17 | + |
| 18 | /* map chip registers (47xx: and sprom) */ |
| 19 | dev->base_addr = regs; |
| 20 | |
| 21 | @@ -1106,10 +1110,14 @@ wl_free(wl_info_t *wl) |
| 22 | free_irq(wl->dev->irq, wl); |
| 23 | } |
| 24 | |
| 25 | - if (wl->dev) { |
| 26 | - wl_free_if(wl, WL_DEV_IF(wl->dev)); |
| 27 | - wl->dev = NULL; |
| 28 | + /* free all interfaces */ |
| 29 | + while (wl->if_list) { |
| 30 | + if ((wl->if_list->dev != wl->dev) || wl->if_list->next == NULL) |
| 31 | + wl_free_if(wl, wl->if_list); |
| 32 | + else |
| 33 | + wl_free_if(wl, wl->if_list->next); |
| 34 | } |
| 35 | + wl->dev = NULL; |
| 36 | |
| 37 | #ifdef TOE |
| 38 | wl_toe_detach(wl->toei); |
| 39 | @@ -1355,10 +1363,12 @@ wl_txflowcontrol(wl_info_t *wl, bool sta |
| 40 | |
| 41 | ASSERT(prio == ALLPRIO); |
| 42 | for (wlif = wl->if_list; wlif != NULL; wlif = wlif->next) { |
| 43 | - if (state == ON) |
| 44 | - netif_stop_queue(wlif->dev); |
| 45 | - else |
| 46 | - netif_wake_queue(wlif->dev); |
| 47 | + if (wlif->dev_registed) { |
| 48 | + if (state == ON) |
| 49 | + netif_stop_queue(wlif->dev); |
| 50 | + else |
| 51 | + netif_wake_queue(wlif->dev); |
| 52 | + } |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | @@ -1398,7 +1408,6 @@ wl_alloc_if(wl_info_t *wl, int iftype, u |
| 57 | { |
| 58 | struct net_device *dev; |
| 59 | wl_if_t *wlif; |
| 60 | - wl_if_t *p; |
| 61 | |
| 62 | dev = alloc_etherdev(sizeof(wl_if_t)); |
| 63 | wlif = netdev_priv(dev); |
| 64 | @@ -1411,9 +1420,13 @@ wl_alloc_if(wl_info_t *wl, int iftype, u |
| 65 | wlif->wlcif = wlcif; |
| 66 | wlif->subunit = subunit; |
| 67 | |
| 68 | - /* match current flow control state */ |
| 69 | - if (iftype != WL_IFTYPE_MON && wl->dev && netif_queue_stopped(wl->dev)) |
| 70 | - netif_stop_queue(dev); |
| 71 | + return wlif; |
| 72 | +} |
| 73 | + |
| 74 | +static void |
| 75 | +wl_link_if(wl_info_t *wl, wl_if_t *wlif) |
| 76 | +{ |
| 77 | + wl_if_t *p; |
| 78 | |
| 79 | /* add the interface to the interface linked list */ |
| 80 | if (wl->if_list == NULL) |
| 81 | @@ -1424,7 +1437,6 @@ wl_alloc_if(wl_info_t *wl, int iftype, u |
| 82 | p = p->next; |
| 83 | p->next = wlif; |
| 84 | } |
| 85 | - return wlif; |
| 86 | } |
| 87 | |
| 88 | static void |
| 89 | @@ -1504,6 +1516,9 @@ _wl_add_if(wl_task_t *task) |
| 90 | wl_info_t *wl = wlif->wl; |
| 91 | struct net_device *dev = wlif->dev; |
| 92 | |
| 93 | + /* add the interface to the interface linked list */ |
| 94 | + wl_link_if(wl, wlif); |
| 95 | + |
| 96 | if (wlif->type == WL_IFTYPE_WDS) |
| 97 | dev->netdev_ops = &wl_wds_ops; |
| 98 | |
| 99 | @@ -1516,6 +1531,14 @@ _wl_add_if(wl_task_t *task) |
| 100 | } |
| 101 | wlif->dev_registed = TRUE; |
| 102 | |
| 103 | + /* match current flow control state */ |
| 104 | + if (wl->dev) { |
| 105 | + if (netif_queue_stopped(wl->dev)) |
| 106 | + netif_stop_queue(dev); |
| 107 | + else |
| 108 | + netif_wake_queue(dev); |
| 109 | + } |
| 110 | + |
| 111 | done: |
| 112 | MFREE(wl->osh, task, sizeof(wl_task_t)); |
| 113 | atomic_dec(&wl->callbacks); |
| 114 | @@ -1545,6 +1568,8 @@ wl_add_if(wl_info_t *wl, struct wlc_if* |
| 115 | return NULL; |
| 116 | } |
| 117 | |
| 118 | + wl_if_setup(wlif->dev); |
| 119 | + |
| 120 | sprintf(wlif->dev->name, "%s%d.%d", devname, wl->pub->unit, wlif->subunit); |
| 121 | if (remote) |
| 122 | bcopy(remote, &wlif->remote, ETHER_ADDR_LEN); |
| 123 | @@ -2778,6 +2803,9 @@ wl_add_monitor(wl_task_t *task) |
| 124 | dev = wlif->dev; |
| 125 | wl->monitor = dev; |
| 126 | |
| 127 | + /* add the interface to the interface linked list */ |
| 128 | + wl_link_if(wl, wlif); |
| 129 | + |
| 130 | /* override some fields */ |
| 131 | sprintf(dev->name, "prism%d", wl->pub->unit); |
| 132 | bcopy(wl->dev->dev_addr, dev->dev_addr, ETHER_ADDR_LEN); |