create branch for barrier breaker (from trunk r41863)
[14.07/openwrt.git] / package / kernel / broadcom-wl / patches / 008-fix_virtual_interfaces.patch
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);