ath9k: prevent writes to const data on AR9160
[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,
287 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
288 +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
289 @@ -489,8 +489,6 @@ static int ar5008_hw_rf_alloc_ext_banks(
290         ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows);
291         ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows);
292         ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows);
293 -       ATH_ALLOC_BANK(ah->addac5416_21,
294 -                      ah->iniAddac.ia_rows * ah->iniAddac.ia_columns);
295         ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows);
296  
297         return 0;
298 @@ -519,7 +517,6 @@ static void ar5008_hw_rf_free_ext_banks(
299         ATH_FREE_BANK(ah->analogBank6Data);
300         ATH_FREE_BANK(ah->analogBank6TPCData);
301         ATH_FREE_BANK(ah->analogBank7Data);
302 -       ATH_FREE_BANK(ah->addac5416_21);
303         ATH_FREE_BANK(ah->bank6Temp);
304  
305  #undef ATH_FREE_BANK
306 @@ -805,27 +802,7 @@ static int ar5008_hw_process_ini(struct 
307         if (ah->eep_ops->set_addac)
308                 ah->eep_ops->set_addac(ah, chan);
309  
310 -       if (AR_SREV_5416_22_OR_LATER(ah)) {
311 -               REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
312 -       } else {
313 -               struct ar5416IniArray temp;
314 -               u32 addacSize =
315 -                       sizeof(u32) * ah->iniAddac.ia_rows *
316 -                       ah->iniAddac.ia_columns;
317 -
318 -               /* For AR5416 2.0/2.1 */
319 -               memcpy(ah->addac5416_21,
320 -                      ah->iniAddac.ia_array, addacSize);
321 -
322 -               /* override CLKDRV value at [row, column] = [31, 1] */
323 -               (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0;
324 -
325 -               temp.ia_array = ah->addac5416_21;
326 -               temp.ia_columns = ah->iniAddac.ia_columns;
327 -               temp.ia_rows = ah->iniAddac.ia_rows;
328 -               REG_WRITE_ARRAY(&temp, 1, regWrites);
329 -       }
330 -
331 +       REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
332         REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
333  
334         ENABLE_REGWRITE_BUFFER(ah);
335 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
336 +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
337 @@ -180,6 +180,25 @@ static void ar9002_hw_init_mode_regs(str
338                 INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
339                                ARRAY_SIZE(ar5416Addac), 2);
340         }
341 +
342 +       /* iniAddac needs to be modified for these chips */
343 +       if (AR_SREV_9160(ah) || !AR_SREV_5416_22_OR_LATER(ah)) {
344 +               struct ar5416IniArray *addac = &ah->iniAddac;
345 +               u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns;
346 +               u32 *data;
347 +
348 +               data = kmalloc(size, GFP_KERNEL);
349 +               if (!data)
350 +                       return;
351 +
352 +               memcpy(data, addac->ia_array, size);
353 +               addac->ia_array = data;
354 +
355 +               if (!AR_SREV_5416_22_OR_LATER(ah)) {
356 +                       /* override CLKDRV value */
357 +                       INI_RA(addac, 31,1) = 0;
358 +               }
359 +       }
360  }
361  
362  /* Support for Japan ch.14 (2484) spread */
363 --- a/drivers/net/wireless/ath/ath9k/hw.h
364 +++ b/drivers/net/wireless/ath/ath9k/hw.h
365 @@ -940,7 +940,6 @@ struct ath_hw {
366         u32 *analogBank6Data;
367         u32 *analogBank6TPCData;
368         u32 *analogBank7Data;
369 -       u32 *addac5416_21;
370         u32 *bank6Temp;
371  
372         u8 txpower_limit;