mac80211: merge a LED related locking fix
[openwrt.git] / package / mac80211 / patches / 300-pending_work.patch
1 --- a/net/mac80211/agg-rx.c
2 +++ b/net/mac80211/agg-rx.c
3 @@ -187,6 +187,8 @@ static void ieee80211_send_addba_resp(st
4                 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
5         else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
6                 memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
7 +       else if (sdata->vif.type == NL80211_IFTYPE_WDS)
8 +               memcpy(mgmt->bssid, da, ETH_ALEN);
9  
10         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
11                                           IEEE80211_STYPE_ACTION);
12 --- a/net/mac80211/agg-tx.c
13 +++ b/net/mac80211/agg-tx.c
14 @@ -81,7 +81,8 @@ static void ieee80211_send_addba_request
15         memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
16         if (sdata->vif.type == NL80211_IFTYPE_AP ||
17             sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
18 -           sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
19 +           sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
20 +           sdata->vif.type == NL80211_IFTYPE_WDS)
21                 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
22         else if (sdata->vif.type == NL80211_IFTYPE_STATION)
23                 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
24 @@ -471,6 +472,7 @@ int ieee80211_start_tx_ba_session(struct
25             sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
26             sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
27             sdata->vif.type != NL80211_IFTYPE_AP &&
28 +           sdata->vif.type != NL80211_IFTYPE_WDS &&
29             sdata->vif.type != NL80211_IFTYPE_ADHOC)
30                 return -EINVAL;
31  
32 --- a/net/mac80211/debugfs_sta.c
33 +++ b/net/mac80211/debugfs_sta.c
34 @@ -63,11 +63,11 @@ static ssize_t sta_flags_read(struct fil
35         test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : ""
36  
37         int res = scnprintf(buf, sizeof(buf),
38 -                           "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
39 +                           "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
40                             TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
41                             TEST(PS_DRIVER), TEST(AUTHORIZED),
42                             TEST(SHORT_PREAMBLE),
43 -                           TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT),
44 +                           TEST(WME), TEST(CLEAR_PS_FILT),
45                             TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
46                             TEST(UAPSD), TEST(SP), TEST(TDLS_PEER),
47                             TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT),
48 --- a/net/mac80211/iface.c
49 +++ b/net/mac80211/iface.c
50 @@ -178,7 +178,6 @@ static int ieee80211_do_open(struct net_
51  {
52         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
53         struct ieee80211_local *local = sdata->local;
54 -       struct sta_info *sta;
55         u32 changed = 0;
56         int res;
57         u32 hw_reconf_flags = 0;
58 @@ -309,28 +308,6 @@ static int ieee80211_do_open(struct net_
59  
60         set_bit(SDATA_STATE_RUNNING, &sdata->state);
61  
62 -       if (sdata->vif.type == NL80211_IFTYPE_WDS) {
63 -               /* Create STA entry for the WDS peer */
64 -               sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
65 -                                    GFP_KERNEL);
66 -               if (!sta) {
67 -                       res = -ENOMEM;
68 -                       goto err_del_interface;
69 -               }
70 -
71 -               sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
72 -               sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
73 -               sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
74 -
75 -               res = sta_info_insert(sta);
76 -               if (res) {
77 -                       /* STA has been freed */
78 -                       goto err_del_interface;
79 -               }
80 -
81 -               rate_control_rate_init(sta);
82 -       }
83 -
84         /*
85          * set_multicast_list will be invoked by the networking core
86          * which will check whether any increments here were done in
87 @@ -357,8 +334,7 @@ static int ieee80211_do_open(struct net_
88         netif_tx_start_all_queues(dev);
89  
90         return 0;
91 - err_del_interface:
92 -       drv_remove_interface(local, sdata);
93 +
94   err_stop:
95         if (!local->open_count)
96                 drv_stop(local);
97 @@ -720,6 +696,70 @@ static void ieee80211_if_setup(struct ne
98         dev->destructor = free_netdev;
99  }
100  
101 +static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
102 +                                        struct sk_buff *skb)
103 +{
104 +       struct ieee80211_local *local = sdata->local;
105 +       struct ieee80211_rx_status *rx_status;
106 +       struct ieee802_11_elems elems;
107 +       struct ieee80211_mgmt *mgmt;
108 +       struct sta_info *sta;
109 +       size_t baselen;
110 +       u32 rates = 0;
111 +       u16 stype;
112 +       bool new = false;
113 +       enum ieee80211_band band = local->hw.conf.channel->band;
114 +       struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
115 +
116 +       rx_status = IEEE80211_SKB_RXCB(skb);
117 +       mgmt = (struct ieee80211_mgmt *) skb->data;
118 +       stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
119 +
120 +       if (stype != IEEE80211_STYPE_BEACON)
121 +               return;
122 +
123 +       baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
124 +       if (baselen > skb->len)
125 +               return;
126 +
127 +       ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
128 +                              skb->len - baselen, &elems);
129 +
130 +       rates = ieee80211_sta_get_rates(local, &elems, band);
131 +
132 +       rcu_read_lock();
133 +
134 +       sta = sta_info_get(sdata, sdata->u.wds.remote_addr);
135 +
136 +       if (!sta) {
137 +               rcu_read_unlock();
138 +               sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
139 +                                    GFP_KERNEL);
140 +               if (!sta)
141 +                       return;
142 +
143 +               new = true;
144 +       }
145 +
146 +       sta->last_rx = jiffies;
147 +       sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
148 +
149 +       if (elems.ht_cap_elem)
150 +               ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
151 +                               elems.ht_cap_elem, &sta->sta.ht_cap);
152 +
153 +       if (elems.wmm_param)
154 +               set_sta_flag(sta, WLAN_STA_WME);
155 +
156 +       if (new) {
157 +               set_sta_flag(sta, WLAN_STA_AUTHORIZED);
158 +               rate_control_rate_init(sta);
159 +               sta_info_insert_rcu(sta);
160 +       }
161 +
162 +       rcu_read_unlock();
163 +}
164 +
165  static void ieee80211_iface_work(struct work_struct *work)
166  {
167         struct ieee80211_sub_if_data *sdata =
168 @@ -824,6 +864,9 @@ static void ieee80211_iface_work(struct 
169                                 break;
170                         ieee80211_mesh_rx_queued_mgmt(sdata, skb);
171                         break;
172 +               case NL80211_IFTYPE_WDS:
173 +                       ieee80211_wds_rx_queued_mgmt(sdata, skb);
174 +                       break;
175                 default:
176                         WARN(1, "frame for unexpected interface type");
177                         break;
178 --- a/net/mac80211/rx.c
179 +++ b/net/mac80211/rx.c
180 @@ -2281,6 +2281,7 @@ ieee80211_rx_h_action(struct ieee80211_r
181                     sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
182                     sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
183                     sdata->vif.type != NL80211_IFTYPE_AP &&
184 +                   sdata->vif.type != NL80211_IFTYPE_WDS &&
185                     sdata->vif.type != NL80211_IFTYPE_ADHOC)
186                         break;
187  
188 @@ -2491,14 +2492,15 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
189  
190         if (!ieee80211_vif_is_mesh(&sdata->vif) &&
191             sdata->vif.type != NL80211_IFTYPE_ADHOC &&
192 -           sdata->vif.type != NL80211_IFTYPE_STATION)
193 +           sdata->vif.type != NL80211_IFTYPE_STATION &&
194 +           sdata->vif.type != NL80211_IFTYPE_WDS)
195                 return RX_DROP_MONITOR;
196  
197         switch (stype) {
198         case cpu_to_le16(IEEE80211_STYPE_AUTH):
199         case cpu_to_le16(IEEE80211_STYPE_BEACON):
200         case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
201 -               /* process for all: mesh, mlme, ibss */
202 +               /* process for all: mesh, mlme, ibss, wds */
203                 break;
204         case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
205         case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
206 @@ -2852,10 +2854,16 @@ static int prepare_for_handlers(struct i
207                 }
208                 break;
209         case NL80211_IFTYPE_WDS:
210 -               if (bssid || !ieee80211_is_data(hdr->frame_control))
211 -                       return 0;
212                 if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2))
213                         return 0;
214 +
215 +               if (ieee80211_is_data(hdr->frame_control) ||
216 +                   ieee80211_is_action(hdr->frame_control)) {
217 +                       if (compare_ether_addr(sdata->vif.addr, hdr->addr1))
218 +                               return 0;
219 +               } else if (!ieee80211_is_beacon(hdr->frame_control))
220 +                       return 0;
221 +
222                 break;
223         default:
224                 /* should never get here */
225 --- a/net/mac80211/sta_info.c
226 +++ b/net/mac80211/sta_info.c
227 @@ -1379,8 +1379,10 @@ int sta_info_move_state(struct sta_info 
228                 return -EINVAL;
229         }
230  
231 +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
232         printk(KERN_DEBUG "%s: moving STA %pM to state %d\n",
233                 sta->sdata->name, sta->sta.addr, new_state);
234 +#endif
235  
236         /*
237          * notify the driver before the actual changes so it can
238 --- a/net/mac80211/sta_info.h
239 +++ b/net/mac80211/sta_info.h
240 @@ -31,7 +31,6 @@
241   * @WLAN_STA_SHORT_PREAMBLE: Station is capable of receiving short-preamble
242   *     frames.
243   * @WLAN_STA_WME: Station is a QoS-STA.
244 - * @WLAN_STA_WDS: Station is one of our WDS peers.
245   * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
246   *     IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
247   *     frame to this station is transmitted.
248 @@ -62,7 +61,6 @@ enum ieee80211_sta_info_flags {
249         WLAN_STA_AUTHORIZED,
250         WLAN_STA_SHORT_PREAMBLE,
251         WLAN_STA_WME,
252 -       WLAN_STA_WDS,
253         WLAN_STA_CLEAR_PS_FILT,
254         WLAN_STA_MFP,
255         WLAN_STA_BLOCK_BA,
256 --- a/net/mac80211/rate.h
257 +++ b/net/mac80211/rate.h
258 @@ -37,7 +37,7 @@ static inline void rate_control_tx_statu
259         struct ieee80211_sta *ista = &sta->sta;
260         void *priv_sta = sta->rate_ctrl_priv;
261  
262 -       if (!ref)
263 +       if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
264                 return;
265  
266         ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb);
267 --- a/net/mac80211/main.c
268 +++ b/net/mac80211/main.c
269 @@ -915,6 +915,8 @@ int ieee80211_register_hw(struct ieee802
270                 wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
271                             result);
272  
273 +       ieee80211_led_init(local);
274 +
275         rtnl_lock();
276  
277         result = ieee80211_init_rate_ctrl_alg(local,
278 @@ -936,8 +938,6 @@ int ieee80211_register_hw(struct ieee802
279  
280         rtnl_unlock();
281  
282 -       ieee80211_led_init(local);
283 -
284         local->network_latency_notifier.notifier_call =
285                 ieee80211_max_network_latency;
286         result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,