aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-06-11 14:34:06 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-11 14:34:06 -0400
commit14599f1e341ee219abdd15f4eee5872d6f2d29f1 (patch)
tree3875181429010e58416ab34e6c06ef42de52e756 /net
parentd8d1f30b95a635dbd610dcc5eb641aca8f4768cf (diff)
parent832c10fd733893f86c63bde1c65b005d5a2fe346 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts: drivers/net/wireless/wl12xx/wl1271.h drivers/net/wireless/wl12xx/wl1271_cmd.h
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/Kconfig7
-rw-r--r--net/mac80211/Makefile4
-rw-r--r--net/mac80211/agg-tx.c7
-rw-r--r--net/mac80211/cfg.c22
-rw-r--r--net/mac80211/debugfs.c154
-rw-r--r--net/mac80211/debugfs_sta.c48
-rw-r--r--net/mac80211/driver-ops.h25
-rw-r--r--net/mac80211/driver-trace.h35
-rw-r--r--net/mac80211/ibss.c14
-rw-r--r--net/mac80211/ieee80211_i.h7
-rw-r--r--net/mac80211/iface.c14
-rw-r--r--net/mac80211/key.c288
-rw-r--r--net/mac80211/key.h22
-rw-r--r--net/mac80211/main.c81
-rw-r--r--net/mac80211/mlme.c75
-rw-r--r--net/mac80211/rate.h13
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c824
-rw-r--r--net/mac80211/rc80211_minstrel_ht.h128
-rw-r--r--net/mac80211/rc80211_minstrel_ht_debugfs.c120
-rw-r--r--net/mac80211/rx.c41
-rw-r--r--net/mac80211/sta_info.c8
-rw-r--r--net/mac80211/sta_info.h44
-rw-r--r--net/mac80211/status.c2
-rw-r--r--net/mac80211/work.c2
-rw-r--r--net/wireless/chan.c5
-rw-r--r--net/wireless/core.h1
-rw-r--r--net/wireless/mlme.c3
-rw-r--r--net/wireless/nl80211.c3
28 files changed, 1520 insertions, 477 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 8a91f6c0bb18..83eec7a8bd1f 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -33,6 +33,13 @@ config MAC80211_RC_MINSTREL
33 ---help--- 33 ---help---
34 This option enables the 'minstrel' TX rate control algorithm 34 This option enables the 'minstrel' TX rate control algorithm
35 35
36config MAC80211_RC_MINSTREL_HT
37 bool "Minstrel 802.11n support" if EMBEDDED
38 depends on MAC80211_RC_MINSTREL
39 default y
40 ---help---
41 This option enables the 'minstrel_ht' TX rate control algorithm
42
36choice 43choice
37 prompt "Default rate control algorithm" 44 prompt "Default rate control algorithm"
38 depends on MAC80211_HAS_RC 45 depends on MAC80211_HAS_RC
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 84b48ba8a77e..fdb54e61d637 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -51,7 +51,11 @@ rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o
51rc80211_minstrel-y := rc80211_minstrel.o 51rc80211_minstrel-y := rc80211_minstrel.o
52rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o 52rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o
53 53
54rc80211_minstrel_ht-y := rc80211_minstrel_ht.o
55rc80211_minstrel_ht-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_ht_debugfs.o
56
54mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc80211_pid-y) 57mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc80211_pid-y)
55mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y) 58mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
59mac80211-$(CONFIG_MAC80211_RC_MINSTREL_HT) += $(rc80211_minstrel_ht-y)
56 60
57ccflags-y += -D__CHECK_ENDIAN__ 61ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 98258b7341e3..d1b6664a2532 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -540,14 +540,13 @@ int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
540 return ret; 540 return ret;
541} 541}
542 542
543int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, 543int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
544 enum ieee80211_back_parties initiator)
545{ 544{
546 struct sta_info *sta = container_of(pubsta, struct sta_info, sta); 545 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
547 struct ieee80211_sub_if_data *sdata = sta->sdata; 546 struct ieee80211_sub_if_data *sdata = sta->sdata;
548 struct ieee80211_local *local = sdata->local; 547 struct ieee80211_local *local = sdata->local;
549 548
550 trace_api_stop_tx_ba_session(pubsta, tid, initiator); 549 trace_api_stop_tx_ba_session(pubsta, tid);
551 550
552 if (!local->ops->ampdu_action) 551 if (!local->ops->ampdu_action)
553 return -EINVAL; 552 return -EINVAL;
@@ -555,7 +554,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
555 if (tid >= STA_TID_NUM) 554 if (tid >= STA_TID_NUM)
556 return -EINVAL; 555 return -EINVAL;
557 556
558 return __ieee80211_stop_tx_ba_session(sta, tid, initiator); 557 return __ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR);
559} 558}
560EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); 559EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
561 560
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a2ed0f7b5568..1f76d048388b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -120,6 +120,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
120 struct ieee80211_key *key; 120 struct ieee80211_key *key;
121 int err; 121 int err;
122 122
123 if (!netif_running(dev))
124 return -ENETDOWN;
125
123 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 126 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
124 127
125 switch (params->cipher) { 128 switch (params->cipher) {
@@ -145,7 +148,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
145 if (!key) 148 if (!key)
146 return -ENOMEM; 149 return -ENOMEM;
147 150
148 rcu_read_lock(); 151 mutex_lock(&sdata->local->sta_mtx);
149 152
150 if (mac_addr) { 153 if (mac_addr) {
151 sta = sta_info_get_bss(sdata, mac_addr); 154 sta = sta_info_get_bss(sdata, mac_addr);
@@ -160,7 +163,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
160 163
161 err = 0; 164 err = 0;
162 out_unlock: 165 out_unlock:
163 rcu_read_unlock(); 166 mutex_unlock(&sdata->local->sta_mtx);
164 167
165 return err; 168 return err;
166} 169}
@@ -174,7 +177,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
174 177
175 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 178 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
176 179
177 rcu_read_lock(); 180 mutex_lock(&sdata->local->sta_mtx);
178 181
179 if (mac_addr) { 182 if (mac_addr) {
180 ret = -ENOENT; 183 ret = -ENOENT;
@@ -202,7 +205,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
202 205
203 ret = 0; 206 ret = 0;
204 out_unlock: 207 out_unlock:
205 rcu_read_unlock(); 208 mutex_unlock(&sdata->local->sta_mtx);
206 209
207 return ret; 210 return ret;
208} 211}
@@ -305,15 +308,10 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
305 struct net_device *dev, 308 struct net_device *dev,
306 u8 key_idx) 309 u8 key_idx)
307{ 310{
308 struct ieee80211_sub_if_data *sdata; 311 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
309
310 rcu_read_lock();
311 312
312 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
313 ieee80211_set_default_key(sdata, key_idx); 313 ieee80211_set_default_key(sdata, key_idx);
314 314
315 rcu_read_unlock();
316
317 return 0; 315 return 0;
318} 316}
319 317
@@ -1554,10 +1552,12 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
1554static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, 1552static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev,
1555 struct ieee80211_channel *chan, 1553 struct ieee80211_channel *chan,
1556 enum nl80211_channel_type channel_type, 1554 enum nl80211_channel_type channel_type,
1555 bool channel_type_valid,
1557 const u8 *buf, size_t len, u64 *cookie) 1556 const u8 *buf, size_t len, u64 *cookie)
1558{ 1557{
1559 return ieee80211_mgd_action(IEEE80211_DEV_TO_SUB_IF(dev), chan, 1558 return ieee80211_mgd_action(IEEE80211_DEV_TO_SUB_IF(dev), chan,
1560 channel_type, buf, len, cookie); 1559 channel_type, channel_type_valid,
1560 buf, len, cookie);
1561} 1561}
1562 1562
1563struct cfg80211_ops mac80211_config_ops = { 1563struct cfg80211_ops mac80211_config_ops = {
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 637929b65ccc..a694c593ff6a 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -307,9 +307,6 @@ static const struct file_operations queues_ops = {
307 307
308/* statistics stuff */ 308/* statistics stuff */
309 309
310#define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \
311 DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value)
312
313static ssize_t format_devstat_counter(struct ieee80211_local *local, 310static ssize_t format_devstat_counter(struct ieee80211_local *local,
314 char __user *userbuf, 311 char __user *userbuf,
315 size_t count, loff_t *ppos, 312 size_t count, loff_t *ppos,
@@ -351,75 +348,16 @@ static const struct file_operations stats_ ##name## _ops = { \
351 .open = mac80211_open_file_generic, \ 348 .open = mac80211_open_file_generic, \
352}; 349};
353 350
354#define DEBUGFS_STATS_ADD(name) \ 351#define DEBUGFS_STATS_ADD(name, field) \
352 debugfs_create_u32(#name, 0400, statsd, (u32 *) &field);
353#define DEBUGFS_DEVSTATS_ADD(name) \
355 debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops); 354 debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops);
356 355
357DEBUGFS_STATS_FILE(transmitted_fragment_count, 20, "%u",
358 local->dot11TransmittedFragmentCount);
359DEBUGFS_STATS_FILE(multicast_transmitted_frame_count, 20, "%u",
360 local->dot11MulticastTransmittedFrameCount);
361DEBUGFS_STATS_FILE(failed_count, 20, "%u",
362 local->dot11FailedCount);
363DEBUGFS_STATS_FILE(retry_count, 20, "%u",
364 local->dot11RetryCount);
365DEBUGFS_STATS_FILE(multiple_retry_count, 20, "%u",
366 local->dot11MultipleRetryCount);
367DEBUGFS_STATS_FILE(frame_duplicate_count, 20, "%u",
368 local->dot11FrameDuplicateCount);
369DEBUGFS_STATS_FILE(received_fragment_count, 20, "%u",
370 local->dot11ReceivedFragmentCount);
371DEBUGFS_STATS_FILE(multicast_received_frame_count, 20, "%u",
372 local->dot11MulticastReceivedFrameCount);
373DEBUGFS_STATS_FILE(transmitted_frame_count, 20, "%u",
374 local->dot11TransmittedFrameCount);
375#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
376DEBUGFS_STATS_FILE(tx_handlers_drop, 20, "%u",
377 local->tx_handlers_drop);
378DEBUGFS_STATS_FILE(tx_handlers_queued, 20, "%u",
379 local->tx_handlers_queued);
380DEBUGFS_STATS_FILE(tx_handlers_drop_unencrypted, 20, "%u",
381 local->tx_handlers_drop_unencrypted);
382DEBUGFS_STATS_FILE(tx_handlers_drop_fragment, 20, "%u",
383 local->tx_handlers_drop_fragment);
384DEBUGFS_STATS_FILE(tx_handlers_drop_wep, 20, "%u",
385 local->tx_handlers_drop_wep);
386DEBUGFS_STATS_FILE(tx_handlers_drop_not_assoc, 20, "%u",
387 local->tx_handlers_drop_not_assoc);
388DEBUGFS_STATS_FILE(tx_handlers_drop_unauth_port, 20, "%u",
389 local->tx_handlers_drop_unauth_port);
390DEBUGFS_STATS_FILE(rx_handlers_drop, 20, "%u",
391 local->rx_handlers_drop);
392DEBUGFS_STATS_FILE(rx_handlers_queued, 20, "%u",
393 local->rx_handlers_queued);
394DEBUGFS_STATS_FILE(rx_handlers_drop_nullfunc, 20, "%u",
395 local->rx_handlers_drop_nullfunc);
396DEBUGFS_STATS_FILE(rx_handlers_drop_defrag, 20, "%u",
397 local->rx_handlers_drop_defrag);
398DEBUGFS_STATS_FILE(rx_handlers_drop_short, 20, "%u",
399 local->rx_handlers_drop_short);
400DEBUGFS_STATS_FILE(rx_handlers_drop_passive_scan, 20, "%u",
401 local->rx_handlers_drop_passive_scan);
402DEBUGFS_STATS_FILE(tx_expand_skb_head, 20, "%u",
403 local->tx_expand_skb_head);
404DEBUGFS_STATS_FILE(tx_expand_skb_head_cloned, 20, "%u",
405 local->tx_expand_skb_head_cloned);
406DEBUGFS_STATS_FILE(rx_expand_skb_head, 20, "%u",
407 local->rx_expand_skb_head);
408DEBUGFS_STATS_FILE(rx_expand_skb_head2, 20, "%u",
409 local->rx_expand_skb_head2);
410DEBUGFS_STATS_FILE(rx_handlers_fragments, 20, "%u",
411 local->rx_handlers_fragments);
412DEBUGFS_STATS_FILE(tx_status_drop, 20, "%u",
413 local->tx_status_drop);
414
415#endif
416
417DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount); 356DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
418DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount); 357DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount);
419DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount); 358DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount);
420DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount); 359DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount);
421 360
422
423void debugfs_hw_add(struct ieee80211_local *local) 361void debugfs_hw_add(struct ieee80211_local *local)
424{ 362{
425 struct dentry *phyd = local->hw.wiphy->debugfsdir; 363 struct dentry *phyd = local->hw.wiphy->debugfsdir;
@@ -448,38 +386,60 @@ void debugfs_hw_add(struct ieee80211_local *local)
448 if (!statsd) 386 if (!statsd)
449 return; 387 return;
450 388
451 DEBUGFS_STATS_ADD(transmitted_fragment_count); 389 DEBUGFS_STATS_ADD(transmitted_fragment_count,
452 DEBUGFS_STATS_ADD(multicast_transmitted_frame_count); 390 local->dot11TransmittedFragmentCount);
453 DEBUGFS_STATS_ADD(failed_count); 391 DEBUGFS_STATS_ADD(multicast_transmitted_frame_count,
454 DEBUGFS_STATS_ADD(retry_count); 392 local->dot11MulticastTransmittedFrameCount);
455 DEBUGFS_STATS_ADD(multiple_retry_count); 393 DEBUGFS_STATS_ADD(failed_count, local->dot11FailedCount);
456 DEBUGFS_STATS_ADD(frame_duplicate_count); 394 DEBUGFS_STATS_ADD(retry_count, local->dot11RetryCount);
457 DEBUGFS_STATS_ADD(received_fragment_count); 395 DEBUGFS_STATS_ADD(multiple_retry_count,
458 DEBUGFS_STATS_ADD(multicast_received_frame_count); 396 local->dot11MultipleRetryCount);
459 DEBUGFS_STATS_ADD(transmitted_frame_count); 397 DEBUGFS_STATS_ADD(frame_duplicate_count,
398 local->dot11FrameDuplicateCount);
399 DEBUGFS_STATS_ADD(received_fragment_count,
400 local->dot11ReceivedFragmentCount);
401 DEBUGFS_STATS_ADD(multicast_received_frame_count,
402 local->dot11MulticastReceivedFrameCount);
403 DEBUGFS_STATS_ADD(transmitted_frame_count,
404 local->dot11TransmittedFrameCount);
460#ifdef CONFIG_MAC80211_DEBUG_COUNTERS 405#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
461 DEBUGFS_STATS_ADD(tx_handlers_drop); 406 DEBUGFS_STATS_ADD(tx_handlers_drop, local->tx_handlers_drop);
462 DEBUGFS_STATS_ADD(tx_handlers_queued); 407 DEBUGFS_STATS_ADD(tx_handlers_queued, local->tx_handlers_queued);
463 DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted); 408 DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted,
464 DEBUGFS_STATS_ADD(tx_handlers_drop_fragment); 409 local->tx_handlers_drop_unencrypted);
465 DEBUGFS_STATS_ADD(tx_handlers_drop_wep); 410 DEBUGFS_STATS_ADD(tx_handlers_drop_fragment,
466 DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc); 411 local->tx_handlers_drop_fragment);
467 DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port); 412 DEBUGFS_STATS_ADD(tx_handlers_drop_wep,
468 DEBUGFS_STATS_ADD(rx_handlers_drop); 413 local->tx_handlers_drop_wep);
469 DEBUGFS_STATS_ADD(rx_handlers_queued); 414 DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc,
470 DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc); 415 local->tx_handlers_drop_not_assoc);
471 DEBUGFS_STATS_ADD(rx_handlers_drop_defrag); 416 DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port,
472 DEBUGFS_STATS_ADD(rx_handlers_drop_short); 417 local->tx_handlers_drop_unauth_port);
473 DEBUGFS_STATS_ADD(rx_handlers_drop_passive_scan); 418 DEBUGFS_STATS_ADD(rx_handlers_drop, local->rx_handlers_drop);
474 DEBUGFS_STATS_ADD(tx_expand_skb_head); 419 DEBUGFS_STATS_ADD(rx_handlers_queued, local->rx_handlers_queued);
475 DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned); 420 DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc,
476 DEBUGFS_STATS_ADD(rx_expand_skb_head); 421 local->rx_handlers_drop_nullfunc);
477 DEBUGFS_STATS_ADD(rx_expand_skb_head2); 422 DEBUGFS_STATS_ADD(rx_handlers_drop_defrag,
478 DEBUGFS_STATS_ADD(rx_handlers_fragments); 423 local->rx_handlers_drop_defrag);
479 DEBUGFS_STATS_ADD(tx_status_drop); 424 DEBUGFS_STATS_ADD(rx_handlers_drop_short,
425 local->rx_handlers_drop_short);
426 DEBUGFS_STATS_ADD(rx_handlers_drop_passive_scan,
427 local->rx_handlers_drop_passive_scan);
428 DEBUGFS_STATS_ADD(tx_expand_skb_head,
429 local->tx_expand_skb_head);
430 DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned,
431 local->tx_expand_skb_head_cloned);
432 DEBUGFS_STATS_ADD(rx_expand_skb_head,
433 local->rx_expand_skb_head);
434 DEBUGFS_STATS_ADD(rx_expand_skb_head2,
435 local->rx_expand_skb_head2);
436 DEBUGFS_STATS_ADD(rx_handlers_fragments,
437 local->rx_handlers_fragments);
438 DEBUGFS_STATS_ADD(tx_status_drop,
439 local->tx_status_drop);
480#endif 440#endif
481 DEBUGFS_STATS_ADD(dot11ACKFailureCount); 441 DEBUGFS_DEVSTATS_ADD(dot11ACKFailureCount);
482 DEBUGFS_STATS_ADD(dot11RTSFailureCount); 442 DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount);
483 DEBUGFS_STATS_ADD(dot11FCSErrorCount); 443 DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount);
484 DEBUGFS_STATS_ADD(dot11RTSSuccessCount); 444 DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount);
485} 445}
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index e763f1529ddb..576e024715e3 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -30,7 +30,6 @@ static ssize_t sta_ ##name## _read(struct file *file, \
30} 30}
31#define STA_READ_D(name, field) STA_READ(name, 20, field, "%d\n") 31#define STA_READ_D(name, field) STA_READ(name, 20, field, "%d\n")
32#define STA_READ_U(name, field) STA_READ(name, 20, field, "%u\n") 32#define STA_READ_U(name, field) STA_READ(name, 20, field, "%u\n")
33#define STA_READ_LU(name, field) STA_READ(name, 20, field, "%lu\n")
34#define STA_READ_S(name, field) STA_READ(name, 20, field, "%s\n") 33#define STA_READ_S(name, field) STA_READ(name, 20, field, "%s\n")
35 34
36#define STA_OPS(name) \ 35#define STA_OPS(name) \
@@ -52,19 +51,7 @@ static const struct file_operations sta_ ##name## _ops = { \
52 51
53STA_FILE(aid, sta.aid, D); 52STA_FILE(aid, sta.aid, D);
54STA_FILE(dev, sdata->name, S); 53STA_FILE(dev, sdata->name, S);
55STA_FILE(rx_packets, rx_packets, LU);
56STA_FILE(tx_packets, tx_packets, LU);
57STA_FILE(rx_bytes, rx_bytes, LU);
58STA_FILE(tx_bytes, tx_bytes, LU);
59STA_FILE(rx_duplicates, num_duplicates, LU);
60STA_FILE(rx_fragments, rx_fragments, LU);
61STA_FILE(rx_dropped, rx_dropped, LU);
62STA_FILE(tx_fragments, tx_fragments, LU);
63STA_FILE(tx_filtered, tx_filtered_count, LU);
64STA_FILE(tx_retry_failed, tx_retry_failed, LU);
65STA_FILE(tx_retry_count, tx_retry_count, LU);
66STA_FILE(last_signal, last_signal, D); 54STA_FILE(last_signal, last_signal, D);
67STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU);
68 55
69static ssize_t sta_flags_read(struct file *file, char __user *userbuf, 56static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
70 size_t count, loff_t *ppos) 57 size_t count, loff_t *ppos)
@@ -210,8 +197,7 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu
210 if (start) 197 if (start)
211 ret = ieee80211_start_tx_ba_session(&sta->sta, tid); 198 ret = ieee80211_start_tx_ba_session(&sta->sta, tid);
212 else 199 else
213 ret = ieee80211_stop_tx_ba_session(&sta->sta, tid, 200 ret = ieee80211_stop_tx_ba_session(&sta->sta, tid);
214 WLAN_BACK_RECIPIENT);
215 } else { 201 } else {
216 __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, 3); 202 __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, 3);
217 ret = 0; 203 ret = 0;
@@ -307,6 +293,13 @@ STA_OPS(ht_capa);
307 debugfs_create_file(#name, 0400, \ 293 debugfs_create_file(#name, 0400, \
308 sta->debugfs.dir, sta, &sta_ ##name## _ops); 294 sta->debugfs.dir, sta, &sta_ ##name## _ops);
309 295
296#define DEBUGFS_ADD_COUNTER(name, field) \
297 if (sizeof(sta->field) == sizeof(u32)) \
298 debugfs_create_u32(#name, 0400, sta->debugfs.dir, \
299 (u32 *) &sta->field); \
300 else \
301 debugfs_create_u64(#name, 0400, sta->debugfs.dir, \
302 (u64 *) &sta->field);
310 303
311void ieee80211_sta_debugfs_add(struct sta_info *sta) 304void ieee80211_sta_debugfs_add(struct sta_info *sta)
312{ 305{
@@ -339,20 +332,21 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
339 DEBUGFS_ADD(last_seq_ctrl); 332 DEBUGFS_ADD(last_seq_ctrl);
340 DEBUGFS_ADD(agg_status); 333 DEBUGFS_ADD(agg_status);
341 DEBUGFS_ADD(dev); 334 DEBUGFS_ADD(dev);
342 DEBUGFS_ADD(rx_packets);
343 DEBUGFS_ADD(tx_packets);
344 DEBUGFS_ADD(rx_bytes);
345 DEBUGFS_ADD(tx_bytes);
346 DEBUGFS_ADD(rx_duplicates);
347 DEBUGFS_ADD(rx_fragments);
348 DEBUGFS_ADD(rx_dropped);
349 DEBUGFS_ADD(tx_fragments);
350 DEBUGFS_ADD(tx_filtered);
351 DEBUGFS_ADD(tx_retry_failed);
352 DEBUGFS_ADD(tx_retry_count);
353 DEBUGFS_ADD(last_signal); 335 DEBUGFS_ADD(last_signal);
354 DEBUGFS_ADD(wep_weak_iv_count);
355 DEBUGFS_ADD(ht_capa); 336 DEBUGFS_ADD(ht_capa);
337
338 DEBUGFS_ADD_COUNTER(rx_packets, rx_packets);
339 DEBUGFS_ADD_COUNTER(tx_packets, tx_packets);
340 DEBUGFS_ADD_COUNTER(rx_bytes, rx_bytes);
341 DEBUGFS_ADD_COUNTER(tx_bytes, tx_bytes);
342 DEBUGFS_ADD_COUNTER(rx_duplicates, num_duplicates);
343 DEBUGFS_ADD_COUNTER(rx_fragments, rx_fragments);
344 DEBUGFS_ADD_COUNTER(rx_dropped, rx_dropped);
345 DEBUGFS_ADD_COUNTER(tx_fragments, tx_fragments);
346 DEBUGFS_ADD_COUNTER(tx_filtered, tx_filtered_count);
347 DEBUGFS_ADD_COUNTER(tx_retry_failed, tx_retry_failed);
348 DEBUGFS_ADD_COUNTER(tx_retry_count, tx_retry_count);
349 DEBUGFS_ADD_COUNTER(wep_weak_iv_count, wep_weak_iv_count);
356} 350}
357 351
358void ieee80211_sta_debugfs_remove(struct sta_info *sta) 352void ieee80211_sta_debugfs_remove(struct sta_info *sta)
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 4f2271316650..7d18a3245e3d 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -83,6 +83,23 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
83 trace_drv_bss_info_changed(local, sdata, info, changed); 83 trace_drv_bss_info_changed(local, sdata, info, changed);
84} 84}
85 85
86struct in_ifaddr;
87static inline int drv_configure_arp_filter(struct ieee80211_local *local,
88 struct ieee80211_vif *vif,
89 struct in_ifaddr *ifa_list)
90{
91 int ret = 0;
92
93 might_sleep();
94
95 if (local->ops->configure_arp_filter)
96 ret = local->ops->configure_arp_filter(&local->hw, vif,
97 ifa_list);
98
99 trace_drv_configure_arp_filter(local, vif_to_sdata(vif), ifa_list, ret);
100 return ret;
101}
102
86static inline u64 drv_prepare_multicast(struct ieee80211_local *local, 103static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
87 struct netdev_hw_addr_list *mc_list) 104 struct netdev_hw_addr_list *mc_list)
88{ 105{
@@ -252,9 +269,6 @@ static inline int drv_sta_add(struct ieee80211_local *local,
252 269
253 if (local->ops->sta_add) 270 if (local->ops->sta_add)
254 ret = local->ops->sta_add(&local->hw, &sdata->vif, sta); 271 ret = local->ops->sta_add(&local->hw, &sdata->vif, sta);
255 else if (local->ops->sta_notify)
256 local->ops->sta_notify(&local->hw, &sdata->vif,
257 STA_NOTIFY_ADD, sta);
258 272
259 trace_drv_sta_add(local, sdata, sta, ret); 273 trace_drv_sta_add(local, sdata, sta, ret);
260 274
@@ -269,9 +283,6 @@ static inline void drv_sta_remove(struct ieee80211_local *local,
269 283
270 if (local->ops->sta_remove) 284 if (local->ops->sta_remove)
271 local->ops->sta_remove(&local->hw, &sdata->vif, sta); 285 local->ops->sta_remove(&local->hw, &sdata->vif, sta);
272 else if (local->ops->sta_notify)
273 local->ops->sta_notify(&local->hw, &sdata->vif,
274 STA_NOTIFY_REMOVE, sta);
275 286
276 trace_drv_sta_remove(local, sdata, sta); 287 trace_drv_sta_remove(local, sdata, sta);
277} 288}
@@ -349,7 +360,7 @@ static inline int drv_get_survey(struct ieee80211_local *local, int idx,
349 struct survey_info *survey) 360 struct survey_info *survey)
350{ 361{
351 int ret = -EOPNOTSUPP; 362 int ret = -EOPNOTSUPP;
352 if (local->ops->conf_tx) 363 if (local->ops->get_survey)
353 ret = local->ops->get_survey(&local->hw, idx, survey); 364 ret = local->ops->get_survey(&local->hw, idx, survey);
354 /* trace_drv_get_survey(local, idx, survey, ret); */ 365 /* trace_drv_get_survey(local, idx, survey, ret); */
355 return ret; 366 return ret;
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 6a9b2342a9c2..6b90630151ab 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -219,6 +219,31 @@ TRACE_EVENT(drv_bss_info_changed,
219 ) 219 )
220); 220);
221 221
222TRACE_EVENT(drv_configure_arp_filter,
223 TP_PROTO(struct ieee80211_local *local,
224 struct ieee80211_sub_if_data *sdata,
225 struct in_ifaddr *ifa_list, int ret),
226
227 TP_ARGS(local, sdata, ifa_list, ret),
228
229 TP_STRUCT__entry(
230 LOCAL_ENTRY
231 VIF_ENTRY
232 __field(int, ret)
233 ),
234
235 TP_fast_assign(
236 LOCAL_ASSIGN;
237 VIF_ASSIGN;
238 __entry->ret = ret;
239 ),
240
241 TP_printk(
242 VIF_PR_FMT LOCAL_PR_FMT " ret:%d",
243 VIF_PR_ARG, LOCAL_PR_ARG, __entry->ret
244 )
245);
246
222TRACE_EVENT(drv_prepare_multicast, 247TRACE_EVENT(drv_prepare_multicast,
223 TP_PROTO(struct ieee80211_local *local, int mc_count, u64 ret), 248 TP_PROTO(struct ieee80211_local *local, int mc_count, u64 ret),
224 249
@@ -851,25 +876,23 @@ TRACE_EVENT(api_start_tx_ba_cb,
851); 876);
852 877
853TRACE_EVENT(api_stop_tx_ba_session, 878TRACE_EVENT(api_stop_tx_ba_session,
854 TP_PROTO(struct ieee80211_sta *sta, u16 tid, u16 initiator), 879 TP_PROTO(struct ieee80211_sta *sta, u16 tid),
855 880
856 TP_ARGS(sta, tid, initiator), 881 TP_ARGS(sta, tid),
857 882
858 TP_STRUCT__entry( 883 TP_STRUCT__entry(
859 STA_ENTRY 884 STA_ENTRY
860 __field(u16, tid) 885 __field(u16, tid)
861 __field(u16, initiator)
862 ), 886 ),
863 887
864 TP_fast_assign( 888 TP_fast_assign(
865 STA_ASSIGN; 889 STA_ASSIGN;
866 __entry->tid = tid; 890 __entry->tid = tid;
867 __entry->initiator = initiator;
868 ), 891 ),
869 892
870 TP_printk( 893 TP_printk(
871 STA_PR_FMT " tid:%d initiator:%d", 894 STA_PR_FMT " tid:%d",
872 STA_PR_ARG, __entry->tid, __entry->initiator 895 STA_PR_ARG, __entry->tid
873 ) 896 )
874); 897);
875 898
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index b2cc1fda6cfd..d7a96ced2c83 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -798,6 +798,15 @@ static void ieee80211_ibss_work(struct work_struct *work)
798 } 798 }
799} 799}
800 800
801static void ieee80211_queue_ibss_work(struct ieee80211_sub_if_data *sdata)
802{
803 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
804 struct ieee80211_local *local = sdata->local;
805
806 set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
807 ieee80211_queue_work(&local->hw, &ifibss->work);
808}
809
801static void ieee80211_ibss_timer(unsigned long data) 810static void ieee80211_ibss_timer(unsigned long data)
802{ 811{
803 struct ieee80211_sub_if_data *sdata = 812 struct ieee80211_sub_if_data *sdata =
@@ -810,8 +819,7 @@ static void ieee80211_ibss_timer(unsigned long data)
810 return; 819 return;
811 } 820 }
812 821
813 set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request); 822 ieee80211_queue_ibss_work(sdata);
814 ieee80211_queue_work(&local->hw, &ifibss->work);
815} 823}
816 824
817#ifdef CONFIG_PM 825#ifdef CONFIG_PM
@@ -859,7 +867,7 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
859 if (!sdata->u.ibss.ssid_len) 867 if (!sdata->u.ibss.ssid_len)
860 continue; 868 continue;
861 sdata->u.ibss.last_scan_completed = jiffies; 869 sdata->u.ibss.last_scan_completed = jiffies;
862 mod_timer(&sdata->u.ibss.timer, 0); 870 ieee80211_queue_ibss_work(sdata);
863 } 871 }
864 mutex_unlock(&local->iflist_mtx); 872 mutex_unlock(&local->iflist_mtx);
865} 873}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ec3e5c3e27bd..1e779e833473 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -746,10 +746,10 @@ struct ieee80211_local {
746 struct mutex iflist_mtx; 746 struct mutex iflist_mtx;
747 747
748 /* 748 /*
749 * Key lock, protects sdata's key_list and sta_info's 749 * Key mutex, protects sdata's key_list and sta_info's
750 * key pointers (write access, they're RCU.) 750 * key pointers (write access, they're RCU.)
751 */ 751 */
752 spinlock_t key_lock; 752 struct mutex key_mtx;
753 753
754 754
755 /* Scanning and BSS list */ 755 /* Scanning and BSS list */
@@ -851,6 +851,7 @@ struct ieee80211_local {
851 struct work_struct dynamic_ps_disable_work; 851 struct work_struct dynamic_ps_disable_work;
852 struct timer_list dynamic_ps_timer; 852 struct timer_list dynamic_ps_timer;
853 struct notifier_block network_latency_notifier; 853 struct notifier_block network_latency_notifier;
854 struct notifier_block ifa_notifier;
854 855
855 int user_power_level; /* in dBm */ 856 int user_power_level; /* in dBm */
856 int power_constr_level; /* in dBm */ 857 int power_constr_level; /* in dBm */
@@ -988,6 +989,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
988int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, 989int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata,
989 struct ieee80211_channel *chan, 990 struct ieee80211_channel *chan,
990 enum nl80211_channel_type channel_type, 991 enum nl80211_channel_type channel_type,
992 bool channel_type_valid,
991 const u8 *buf, size_t len, u64 *cookie); 993 const u8 *buf, size_t len, u64 *cookie);
992ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, 994ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
993 struct sk_buff *skb); 995 struct sk_buff *skb);
@@ -996,6 +998,7 @@ void ieee80211_send_pspoll(struct ieee80211_local *local,
996void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); 998void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency);
997int ieee80211_max_network_latency(struct notifier_block *nb, 999int ieee80211_max_network_latency(struct notifier_block *nb,
998 unsigned long data, void *dummy); 1000 unsigned long data, void *dummy);
1001int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata);
999void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, 1002void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1000 struct ieee80211_channel_sw_ie *sw_elem, 1003 struct ieee80211_channel_sw_ie *sw_elem,
1001 struct ieee80211_bss *bss, 1004 struct ieee80211_bss *bss,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 50deb017fd6e..1afa9ec81fe8 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -268,7 +268,6 @@ static int ieee80211_open(struct net_device *dev)
268 268
269 changed |= ieee80211_reset_erp_info(sdata); 269 changed |= ieee80211_reset_erp_info(sdata);
270 ieee80211_bss_info_change_notify(sdata, changed); 270 ieee80211_bss_info_change_notify(sdata, changed);
271 ieee80211_enable_keys(sdata);
272 271
273 if (sdata->vif.type == NL80211_IFTYPE_STATION) 272 if (sdata->vif.type == NL80211_IFTYPE_STATION)
274 netif_carrier_off(dev); 273 netif_carrier_off(dev);
@@ -321,15 +320,6 @@ static int ieee80211_open(struct net_device *dev)
321 320
322 ieee80211_recalc_ps(local, -1); 321 ieee80211_recalc_ps(local, -1);
323 322
324 /*
325 * ieee80211_sta_work is disabled while network interface
326 * is down. Therefore, some configuration changes may not
327 * yet be effective. Trigger execution of ieee80211_sta_work
328 * to fix this.
329 */
330 if (sdata->vif.type == NL80211_IFTYPE_STATION)
331 ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
332
333 netif_tx_start_all_queues(dev); 323 netif_tx_start_all_queues(dev);
334 324
335 return 0; 325 return 0;
@@ -531,8 +521,8 @@ static int ieee80211_stop(struct net_device *dev)
531 BSS_CHANGED_BEACON_ENABLED); 521 BSS_CHANGED_BEACON_ENABLED);
532 } 522 }
533 523
534 /* disable all keys for as long as this netdev is down */ 524 /* free all remaining keys, there shouldn't be any */
535 ieee80211_disable_keys(sdata); 525 ieee80211_free_keys(sdata);
536 drv_remove_interface(local, &sdata->vif); 526 drv_remove_interface(local, &sdata->vif);
537 } 527 }
538 528
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index e8f6e3b252d8..d0d9001a4a6a 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -36,80 +36,20 @@
36 * There is currently no way of knowing this except by looking into 36 * There is currently no way of knowing this except by looking into
37 * debugfs. 37 * debugfs.
38 * 38 *
39 * All key operations are protected internally so you can call them at 39 * All key operations are protected internally.
40 * any time.
41 * 40 *
42 * Within mac80211, key references are, just as STA structure references, 41 * Within mac80211, key references are, just as STA structure references,
43 * protected by RCU. Note, however, that some things are unprotected, 42 * protected by RCU. Note, however, that some things are unprotected,
44 * namely the key->sta dereferences within the hardware acceleration 43 * namely the key->sta dereferences within the hardware acceleration
45 * functions. This means that sta_info_destroy() must flush the key todo 44 * functions. This means that sta_info_destroy() must remove the key
46 * list. 45 * which waits for an RCU grace period.
47 *
48 * All the direct key list manipulation functions must not sleep because
49 * they can operate on STA info structs that are protected by RCU.
50 */ 46 */
51 47
52static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 48static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
53 49
54/* key mutex: used to synchronise todo runners */ 50static void assert_key_lock(struct ieee80211_local *local)
55static DEFINE_MUTEX(key_mutex);
56static DEFINE_SPINLOCK(todo_lock);
57static LIST_HEAD(todo_list);
58
59static void key_todo(struct work_struct *work)
60{ 51{
61 ieee80211_key_todo(); 52 WARN_ON(!mutex_is_locked(&local->key_mtx));
62}
63
64static DECLARE_WORK(todo_work, key_todo);
65
66/**
67 * add_todo - add todo item for a key
68 *
69 * @key: key to add to do item for
70 * @flag: todo flag(s)
71 *
72 * Must be called with IRQs or softirqs disabled.
73 */
74static void add_todo(struct ieee80211_key *key, u32 flag)
75{
76 if (!key)
77 return;
78
79 spin_lock(&todo_lock);
80 key->flags |= flag;
81 /*
82 * Remove again if already on the list so that we move it to the end.
83 */
84 if (!list_empty(&key->todo))
85 list_del(&key->todo);
86 list_add_tail(&key->todo, &todo_list);
87 schedule_work(&todo_work);
88 spin_unlock(&todo_lock);
89}
90
91/**
92 * ieee80211_key_lock - lock the mac80211 key operation lock
93 *
94 * This locks the (global) mac80211 key operation lock, all
95 * key operations must be done under this lock.
96 */
97static void ieee80211_key_lock(void)
98{
99 mutex_lock(&key_mutex);
100}
101
102/**
103 * ieee80211_key_unlock - unlock the mac80211 key operation lock
104 */
105static void ieee80211_key_unlock(void)
106{
107 mutex_unlock(&key_mutex);
108}
109
110static void assert_key_lock(void)
111{
112 WARN_ON(!mutex_is_locked(&key_mutex));
113} 53}
114 54
115static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) 55static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
@@ -126,12 +66,13 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
126 struct ieee80211_sta *sta; 66 struct ieee80211_sta *sta;
127 int ret; 67 int ret;
128 68
129 assert_key_lock();
130 might_sleep(); 69 might_sleep();
131 70
132 if (!key->local->ops->set_key) 71 if (!key->local->ops->set_key)
133 return; 72 return;
134 73
74 assert_key_lock(key->local);
75
135 sta = get_sta_for_key(key); 76 sta = get_sta_for_key(key);
136 77
137 sdata = key->sdata; 78 sdata = key->sdata;
@@ -142,11 +83,8 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
142 83
143 ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); 84 ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf);
144 85
145 if (!ret) { 86 if (!ret)
146 spin_lock_bh(&todo_lock);
147 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; 87 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
148 spin_unlock_bh(&todo_lock);
149 }
150 88
151 if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) 89 if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
152 printk(KERN_ERR "mac80211-%s: failed to set key " 90 printk(KERN_ERR "mac80211-%s: failed to set key "
@@ -161,18 +99,15 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
161 struct ieee80211_sta *sta; 99 struct ieee80211_sta *sta;
162 int ret; 100 int ret;
163 101
164 assert_key_lock();
165 might_sleep(); 102 might_sleep();
166 103
167 if (!key || !key->local->ops->set_key) 104 if (!key || !key->local->ops->set_key)
168 return; 105 return;
169 106
170 spin_lock_bh(&todo_lock); 107 assert_key_lock(key->local);
171 if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { 108
172 spin_unlock_bh(&todo_lock); 109 if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
173 return; 110 return;
174 }
175 spin_unlock_bh(&todo_lock);
176 111
177 sta = get_sta_for_key(key); 112 sta = get_sta_for_key(key);
178 sdata = key->sdata; 113 sdata = key->sdata;
@@ -191,9 +126,7 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
191 wiphy_name(key->local->hw.wiphy), 126 wiphy_name(key->local->hw.wiphy),
192 key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); 127 key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
193 128
194 spin_lock_bh(&todo_lock);
195 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; 129 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
196 spin_unlock_bh(&todo_lock);
197} 130}
198 131
199static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, 132static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
@@ -201,22 +134,24 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
201{ 134{
202 struct ieee80211_key *key = NULL; 135 struct ieee80211_key *key = NULL;
203 136
137 assert_key_lock(sdata->local);
138
204 if (idx >= 0 && idx < NUM_DEFAULT_KEYS) 139 if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
205 key = sdata->keys[idx]; 140 key = sdata->keys[idx];
206 141
207 rcu_assign_pointer(sdata->default_key, key); 142 rcu_assign_pointer(sdata->default_key, key);
208 143
209 if (key) 144 if (key) {
210 add_todo(key, KEY_FLAG_TODO_DEFKEY); 145 ieee80211_debugfs_key_remove_default(key->sdata);
146 ieee80211_debugfs_key_add_default(key->sdata);
147 }
211} 148}
212 149
213void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx) 150void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
214{ 151{
215 unsigned long flags; 152 mutex_lock(&sdata->local->key_mtx);
216
217 spin_lock_irqsave(&sdata->local->key_lock, flags);
218 __ieee80211_set_default_key(sdata, idx); 153 __ieee80211_set_default_key(sdata, idx);
219 spin_unlock_irqrestore(&sdata->local->key_lock, flags); 154 mutex_unlock(&sdata->local->key_mtx);
220} 155}
221 156
222static void 157static void
@@ -224,24 +159,26 @@ __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
224{ 159{
225 struct ieee80211_key *key = NULL; 160 struct ieee80211_key *key = NULL;
226 161
162 assert_key_lock(sdata->local);
163
227 if (idx >= NUM_DEFAULT_KEYS && 164 if (idx >= NUM_DEFAULT_KEYS &&
228 idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) 165 idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
229 key = sdata->keys[idx]; 166 key = sdata->keys[idx];
230 167
231 rcu_assign_pointer(sdata->default_mgmt_key, key); 168 rcu_assign_pointer(sdata->default_mgmt_key, key);
232 169
233 if (key) 170 if (key) {
234 add_todo(key, KEY_FLAG_TODO_DEFMGMTKEY); 171 ieee80211_debugfs_key_remove_mgmt_default(key->sdata);
172 ieee80211_debugfs_key_add_mgmt_default(key->sdata);
173 }
235} 174}
236 175
237void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, 176void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
238 int idx) 177 int idx)
239{ 178{
240 unsigned long flags; 179 mutex_lock(&sdata->local->key_mtx);
241
242 spin_lock_irqsave(&sdata->local->key_lock, flags);
243 __ieee80211_set_default_mgmt_key(sdata, idx); 180 __ieee80211_set_default_mgmt_key(sdata, idx);
244 spin_unlock_irqrestore(&sdata->local->key_lock, flags); 181 mutex_unlock(&sdata->local->key_mtx);
245} 182}
246 183
247 184
@@ -352,7 +289,6 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
352 } 289 }
353 memcpy(key->conf.key, key_data, key_len); 290 memcpy(key->conf.key, key_data, key_len);
354 INIT_LIST_HEAD(&key->list); 291 INIT_LIST_HEAD(&key->list);
355 INIT_LIST_HEAD(&key->todo);
356 292
357 if (alg == ALG_CCMP) { 293 if (alg == ALG_CCMP) {
358 /* 294 /*
@@ -382,12 +318,27 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
382 return key; 318 return key;
383} 319}
384 320
321static void __ieee80211_key_destroy(struct ieee80211_key *key)
322{
323 if (!key)
324 return;
325
326 ieee80211_key_disable_hw_accel(key);
327
328 if (key->conf.alg == ALG_CCMP)
329 ieee80211_aes_key_free(key->u.ccmp.tfm);
330 if (key->conf.alg == ALG_AES_CMAC)
331 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
332 ieee80211_debugfs_key_remove(key);
333
334 kfree(key);
335}
336
385void ieee80211_key_link(struct ieee80211_key *key, 337void ieee80211_key_link(struct ieee80211_key *key,
386 struct ieee80211_sub_if_data *sdata, 338 struct ieee80211_sub_if_data *sdata,
387 struct sta_info *sta) 339 struct sta_info *sta)
388{ 340{
389 struct ieee80211_key *old_key; 341 struct ieee80211_key *old_key;
390 unsigned long flags;
391 int idx; 342 int idx;
392 343
393 BUG_ON(!sdata); 344 BUG_ON(!sdata);
@@ -431,7 +382,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
431 } 382 }
432 } 383 }
433 384
434 spin_lock_irqsave(&sdata->local->key_lock, flags); 385 mutex_lock(&sdata->local->key_mtx);
435 386
436 if (sta) 387 if (sta)
437 old_key = sta->key; 388 old_key = sta->key;
@@ -439,15 +390,13 @@ void ieee80211_key_link(struct ieee80211_key *key,
439 old_key = sdata->keys[idx]; 390 old_key = sdata->keys[idx];
440 391
441 __ieee80211_key_replace(sdata, sta, old_key, key); 392 __ieee80211_key_replace(sdata, sta, old_key, key);
393 __ieee80211_key_destroy(old_key);
442 394
443 /* free old key later */ 395 ieee80211_debugfs_key_add(key);
444 add_todo(old_key, KEY_FLAG_TODO_DELETE);
445 396
446 add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); 397 ieee80211_key_enable_hw_accel(key);
447 if (ieee80211_sdata_running(sdata))
448 add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
449 398
450 spin_unlock_irqrestore(&sdata->local->key_lock, flags); 399 mutex_unlock(&sdata->local->key_mtx);
451} 400}
452 401
453static void __ieee80211_key_free(struct ieee80211_key *key) 402static void __ieee80211_key_free(struct ieee80211_key *key)
@@ -458,170 +407,65 @@ static void __ieee80211_key_free(struct ieee80211_key *key)
458 if (key->sdata) 407 if (key->sdata)
459 __ieee80211_key_replace(key->sdata, key->sta, 408 __ieee80211_key_replace(key->sdata, key->sta,
460 key, NULL); 409 key, NULL);
461 410 __ieee80211_key_destroy(key);
462 add_todo(key, KEY_FLAG_TODO_DELETE);
463} 411}
464 412
465void ieee80211_key_free(struct ieee80211_key *key) 413void ieee80211_key_free(struct ieee80211_key *key)
466{ 414{
467 unsigned long flags; 415 struct ieee80211_local *local;
468 416
469 if (!key) 417 if (!key)
470 return; 418 return;
471 419
472 if (!key->sdata) { 420 local = key->sdata->local;
473 /* The key has not been linked yet, simply free it
474 * and don't Oops */
475 if (key->conf.alg == ALG_CCMP)
476 ieee80211_aes_key_free(key->u.ccmp.tfm);
477 kfree(key);
478 return;
479 }
480 421
481 spin_lock_irqsave(&key->sdata->local->key_lock, flags); 422 mutex_lock(&local->key_mtx);
482 __ieee80211_key_free(key); 423 __ieee80211_key_free(key);
483 spin_unlock_irqrestore(&key->sdata->local->key_lock, flags); 424 mutex_unlock(&local->key_mtx);
484} 425}
485 426
486/* 427void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
487 * To be safe against concurrent manipulations of the list (which shouldn't
488 * actually happen) we need to hold the spinlock. But under the spinlock we
489 * can't actually do much, so we defer processing to the todo list. Then run
490 * the todo list to be sure the operation and possibly previously pending
491 * operations are completed.
492 */
493static void ieee80211_todo_for_each_key(struct ieee80211_sub_if_data *sdata,
494 u32 todo_flags)
495{ 428{
496 struct ieee80211_key *key; 429 struct ieee80211_key *key;
497 unsigned long flags;
498
499 might_sleep();
500
501 spin_lock_irqsave(&sdata->local->key_lock, flags);
502 list_for_each_entry(key, &sdata->key_list, list)
503 add_todo(key, todo_flags);
504 spin_unlock_irqrestore(&sdata->local->key_lock, flags);
505
506 ieee80211_key_todo();
507}
508 430
509void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
510{
511 ASSERT_RTNL(); 431 ASSERT_RTNL();
512 432
513 if (WARN_ON(!ieee80211_sdata_running(sdata))) 433 if (WARN_ON(!ieee80211_sdata_running(sdata)))
514 return; 434 return;
515 435
516 ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD); 436 mutex_lock(&sdata->local->key_mtx);
517}
518
519void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
520{
521 ASSERT_RTNL();
522
523 ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_REMOVE);
524}
525
526static void __ieee80211_key_destroy(struct ieee80211_key *key)
527{
528 if (!key)
529 return;
530
531 ieee80211_key_disable_hw_accel(key);
532 437
533 if (key->conf.alg == ALG_CCMP) 438 list_for_each_entry(key, &sdata->key_list, list)
534 ieee80211_aes_key_free(key->u.ccmp.tfm); 439 ieee80211_key_enable_hw_accel(key);
535 if (key->conf.alg == ALG_AES_CMAC)
536 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
537 ieee80211_debugfs_key_remove(key);
538 440
539 kfree(key); 441 mutex_unlock(&sdata->local->key_mtx);
540} 442}
541 443
542static void __ieee80211_key_todo(void) 444void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
543{ 445{
544 struct ieee80211_key *key; 446 struct ieee80211_key *key;
545 bool work_done;
546 u32 todoflags;
547 447
548 /* 448 ASSERT_RTNL();
549 * NB: sta_info_destroy relies on this!
550 */
551 synchronize_rcu();
552
553 spin_lock_bh(&todo_lock);
554 while (!list_empty(&todo_list)) {
555 key = list_first_entry(&todo_list, struct ieee80211_key, todo);
556 list_del_init(&key->todo);
557 todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS |
558 KEY_FLAG_TODO_DEFKEY |
559 KEY_FLAG_TODO_DEFMGMTKEY |
560 KEY_FLAG_TODO_HWACCEL_ADD |
561 KEY_FLAG_TODO_HWACCEL_REMOVE |
562 KEY_FLAG_TODO_DELETE);
563 key->flags &= ~todoflags;
564 spin_unlock_bh(&todo_lock);
565
566 work_done = false;
567
568 if (todoflags & KEY_FLAG_TODO_ADD_DEBUGFS) {
569 ieee80211_debugfs_key_add(key);
570 work_done = true;
571 }
572 if (todoflags & KEY_FLAG_TODO_DEFKEY) {
573 ieee80211_debugfs_key_remove_default(key->sdata);
574 ieee80211_debugfs_key_add_default(key->sdata);
575 work_done = true;
576 }
577 if (todoflags & KEY_FLAG_TODO_DEFMGMTKEY) {
578 ieee80211_debugfs_key_remove_mgmt_default(key->sdata);
579 ieee80211_debugfs_key_add_mgmt_default(key->sdata);
580 work_done = true;
581 }
582 if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) {
583 ieee80211_key_enable_hw_accel(key);
584 work_done = true;
585 }
586 if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) {
587 ieee80211_key_disable_hw_accel(key);
588 work_done = true;
589 }
590 if (todoflags & KEY_FLAG_TODO_DELETE) {
591 __ieee80211_key_destroy(key);
592 work_done = true;
593 }
594 449
595 WARN_ON(!work_done); 450 mutex_lock(&sdata->local->key_mtx);
596 451
597 spin_lock_bh(&todo_lock); 452 list_for_each_entry(key, &sdata->key_list, list)
598 } 453 ieee80211_key_disable_hw_accel(key);
599 spin_unlock_bh(&todo_lock);
600}
601 454
602void ieee80211_key_todo(void) 455 mutex_unlock(&sdata->local->key_mtx);
603{
604 ieee80211_key_lock();
605 __ieee80211_key_todo();
606 ieee80211_key_unlock();
607} 456}
608 457
609void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) 458void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
610{ 459{
611 struct ieee80211_key *key, *tmp; 460 struct ieee80211_key *key, *tmp;
612 unsigned long flags;
613 461
614 ieee80211_key_lock(); 462 mutex_lock(&sdata->local->key_mtx);
615 463
616 ieee80211_debugfs_key_remove_default(sdata); 464 ieee80211_debugfs_key_remove_default(sdata);
617 ieee80211_debugfs_key_remove_mgmt_default(sdata); 465 ieee80211_debugfs_key_remove_mgmt_default(sdata);
618 466
619 spin_lock_irqsave(&sdata->local->key_lock, flags);
620 list_for_each_entry_safe(key, tmp, &sdata->key_list, list) 467 list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
621 __ieee80211_key_free(key); 468 __ieee80211_key_free(key);
622 spin_unlock_irqrestore(&sdata->local->key_lock, flags);
623
624 __ieee80211_key_todo();
625 469
626 ieee80211_key_unlock(); 470 mutex_unlock(&sdata->local->key_mtx);
627} 471}
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index bdc2968c2bbe..9996e3be6e63 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -38,25 +38,9 @@ struct sta_info;
38 * 38 *
39 * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present 39 * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present
40 * in the hardware for TX crypto hardware acceleration. 40 * in the hardware for TX crypto hardware acceleration.
41 * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an
42 * RCU grace period, no longer be reachable other than from the
43 * todo list.
44 * @KEY_FLAG_TODO_HWACCEL_ADD: Key needs to be added to hardware acceleration.
45 * @KEY_FLAG_TODO_HWACCEL_REMOVE: Key needs to be removed from hardware
46 * acceleration.
47 * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated.
48 * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs.
49 * @KEY_FLAG_TODO_DEFMGMTKEY: Key is default management key and debugfs needs
50 * to be updated.
51 */ 41 */
52enum ieee80211_internal_key_flags { 42enum ieee80211_internal_key_flags {
53 KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), 43 KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0),
54 KEY_FLAG_TODO_DELETE = BIT(1),
55 KEY_FLAG_TODO_HWACCEL_ADD = BIT(2),
56 KEY_FLAG_TODO_HWACCEL_REMOVE = BIT(3),
57 KEY_FLAG_TODO_DEFKEY = BIT(4),
58 KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5),
59 KEY_FLAG_TODO_DEFMGMTKEY = BIT(6),
60}; 44};
61 45
62enum ieee80211_internal_tkip_state { 46enum ieee80211_internal_tkip_state {
@@ -79,10 +63,8 @@ struct ieee80211_key {
79 63
80 /* for sdata list */ 64 /* for sdata list */
81 struct list_head list; 65 struct list_head list;
82 /* for todo list */
83 struct list_head todo;
84 66
85 /* protected by todo lock! */ 67 /* protected by key mutex */
86 unsigned int flags; 68 unsigned int flags;
87 69
88 union { 70 union {
@@ -155,6 +137,4 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
155void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); 137void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
156void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); 138void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
157 139
158void ieee80211_key_todo(void);
159
160#endif /* IEEE80211_KEY_H */ 140#endif /* IEEE80211_KEY_H */
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 22a384dfab65..88b671a16a41 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -329,6 +329,63 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
329 mutex_unlock(&local->iflist_mtx); 329 mutex_unlock(&local->iflist_mtx);
330} 330}
331 331
332#ifdef CONFIG_INET
333int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata)
334{
335 struct in_device *idev;
336 int ret = 0;
337
338 BUG_ON(!sdata);
339 ASSERT_RTNL();
340
341 idev = sdata->dev->ip_ptr;
342 if (!idev)
343 return 0;
344
345 ret = drv_configure_arp_filter(sdata->local, &sdata->vif,
346 idev->ifa_list);
347 return ret;
348}
349
350static int ieee80211_ifa_changed(struct notifier_block *nb,
351 unsigned long data, void *arg)
352{
353 struct in_ifaddr *ifa = arg;
354 struct ieee80211_local *local =
355 container_of(nb, struct ieee80211_local,
356 ifa_notifier);
357 struct net_device *ndev = ifa->ifa_dev->dev;
358 struct wireless_dev *wdev = ndev->ieee80211_ptr;
359 struct ieee80211_sub_if_data *sdata;
360 struct ieee80211_if_managed *ifmgd;
361
362 if (!netif_running(ndev))
363 return NOTIFY_DONE;
364
365 /* Make sure it's our interface that got changed */
366 if (!wdev)
367 return NOTIFY_DONE;
368
369 if (wdev->wiphy != local->hw.wiphy)
370 return NOTIFY_DONE;
371
372 /* We are concerned about IP addresses only when associated */
373 sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
374
375 /* ARP filtering is only supported in managed mode */
376 if (sdata->vif.type != NL80211_IFTYPE_STATION)
377 return NOTIFY_DONE;
378
379 ifmgd = &sdata->u.mgd;
380 mutex_lock(&ifmgd->mtx);
381 if (ifmgd->associated)
382 ieee80211_set_arp_filter(sdata);
383 mutex_unlock(&ifmgd->mtx);
384
385 return NOTIFY_DONE;
386}
387#endif
388
332struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, 389struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
333 const struct ieee80211_ops *ops) 390 const struct ieee80211_ops *ops)
334{ 391{
@@ -396,7 +453,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
396 mutex_init(&local->iflist_mtx); 453 mutex_init(&local->iflist_mtx);
397 mutex_init(&local->scan_mtx); 454 mutex_init(&local->scan_mtx);
398 455
399 spin_lock_init(&local->key_lock); 456 mutex_init(&local->key_mtx);
400 spin_lock_init(&local->filter_lock); 457 spin_lock_init(&local->filter_lock);
401 spin_lock_init(&local->queue_stop_reason_lock); 458 spin_lock_init(&local->queue_stop_reason_lock);
402 459
@@ -612,14 +669,24 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
612 ieee80211_max_network_latency; 669 ieee80211_max_network_latency;
613 result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, 670 result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
614 &local->network_latency_notifier); 671 &local->network_latency_notifier);
615
616 if (result) { 672 if (result) {
617 rtnl_lock(); 673 rtnl_lock();
618 goto fail_pm_qos; 674 goto fail_pm_qos;
619 } 675 }
620 676
677#ifdef CONFIG_INET
678 local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
679 result = register_inetaddr_notifier(&local->ifa_notifier);
680 if (result)
681 goto fail_ifa;
682#endif
683
621 return 0; 684 return 0;
622 685
686 fail_ifa:
687 pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
688 &local->network_latency_notifier);
689 rtnl_lock();
623 fail_pm_qos: 690 fail_pm_qos:
624 ieee80211_led_exit(local); 691 ieee80211_led_exit(local);
625 ieee80211_remove_interfaces(local); 692 ieee80211_remove_interfaces(local);
@@ -647,6 +714,9 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
647 714
648 pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, 715 pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
649 &local->network_latency_notifier); 716 &local->network_latency_notifier);
717#ifdef CONFIG_INET
718 unregister_inetaddr_notifier(&local->ifa_notifier);
719#endif
650 720
651 rtnl_lock(); 721 rtnl_lock();
652 722
@@ -704,6 +774,10 @@ static int __init ieee80211_init(void)
704 if (ret) 774 if (ret)
705 return ret; 775 return ret;
706 776
777 ret = rc80211_minstrel_ht_init();
778 if (ret)
779 goto err_minstrel;
780
707 ret = rc80211_pid_init(); 781 ret = rc80211_pid_init();
708 if (ret) 782 if (ret)
709 goto err_pid; 783 goto err_pid;
@@ -716,6 +790,8 @@ static int __init ieee80211_init(void)
716 err_netdev: 790 err_netdev:
717 rc80211_pid_exit(); 791 rc80211_pid_exit();
718 err_pid: 792 err_pid:
793 rc80211_minstrel_ht_exit();
794 err_minstrel:
719 rc80211_minstrel_exit(); 795 rc80211_minstrel_exit();
720 796
721 return ret; 797 return ret;
@@ -724,6 +800,7 @@ static int __init ieee80211_init(void)
724static void __exit ieee80211_exit(void) 800static void __exit ieee80211_exit(void)
725{ 801{
726 rc80211_pid_exit(); 802 rc80211_pid_exit();
803 rc80211_minstrel_ht_exit();
727 rc80211_minstrel_exit(); 804 rc80211_minstrel_exit();
728 805
729 /* 806 /*
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0839c4e8fd2e..2ab4e86d9929 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1692,14 +1692,52 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
1692 rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); 1692 rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
1693 break; 1693 break;
1694 case IEEE80211_STYPE_ACTION: 1694 case IEEE80211_STYPE_ACTION:
1695 if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT) 1695 switch (mgmt->u.action.category) {
1696 case WLAN_CATEGORY_BACK: {
1697 struct ieee80211_local *local = sdata->local;
1698 int len = skb->len;
1699 struct sta_info *sta;
1700
1701 rcu_read_lock();
1702 sta = sta_info_get(sdata, mgmt->sa);
1703 if (!sta) {
1704 rcu_read_unlock();
1705 break;
1706 }
1707
1708 local_bh_disable();
1709
1710 switch (mgmt->u.action.u.addba_req.action_code) {
1711 case WLAN_ACTION_ADDBA_REQ:
1712 if (len < (IEEE80211_MIN_ACTION_SIZE +
1713 sizeof(mgmt->u.action.u.addba_req)))
1714 break;
1715 ieee80211_process_addba_request(local, sta, mgmt, len);
1716 break;
1717 case WLAN_ACTION_ADDBA_RESP:
1718 if (len < (IEEE80211_MIN_ACTION_SIZE +
1719 sizeof(mgmt->u.action.u.addba_resp)))
1720 break;
1721 ieee80211_process_addba_resp(local, sta, mgmt, len);
1722 break;
1723 case WLAN_ACTION_DELBA:
1724 if (len < (IEEE80211_MIN_ACTION_SIZE +
1725 sizeof(mgmt->u.action.u.delba)))
1726 break;
1727 ieee80211_process_delba(sdata, sta, mgmt, len);
1728 break;
1729 }
1730 local_bh_enable();
1731 rcu_read_unlock();
1696 break; 1732 break;
1697 1733 }
1698 ieee80211_sta_process_chanswitch(sdata, 1734 case WLAN_CATEGORY_SPECTRUM_MGMT:
1699 &mgmt->u.action.u.chan_switch.sw_elem, 1735 ieee80211_sta_process_chanswitch(sdata,
1700 (void *)ifmgd->associated->priv, 1736 &mgmt->u.action.u.chan_switch.sw_elem,
1701 rx_status->mactime); 1737 (void *)ifmgd->associated->priv,
1702 break; 1738 rx_status->mactime);
1739 break;
1740 }
1703 } 1741 }
1704 mutex_unlock(&ifmgd->mtx); 1742 mutex_unlock(&ifmgd->mtx);
1705 1743
@@ -1763,7 +1801,7 @@ static void ieee80211_sta_work(struct work_struct *work)
1763 1801
1764 /* 1802 /*
1765 * ieee80211_queue_work() should have picked up most cases, 1803 * ieee80211_queue_work() should have picked up most cases,
1766 * here we'll pick the the rest. 1804 * here we'll pick the rest.
1767 */ 1805 */
1768 if (WARN(local->suspended, "STA MLME work scheduled while " 1806 if (WARN(local->suspended, "STA MLME work scheduled while "
1769 "going to suspend\n")) 1807 "going to suspend\n"))
@@ -2078,8 +2116,18 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
2078 cfg80211_send_assoc_timeout(wk->sdata->dev, 2116 cfg80211_send_assoc_timeout(wk->sdata->dev,
2079 wk->filter_ta); 2117 wk->filter_ta);
2080 return WORK_DONE_DESTROY; 2118 return WORK_DONE_DESTROY;
2119 } else {
2120 mutex_unlock(&wk->sdata->u.mgd.mtx);
2121#ifdef CONFIG_INET
2122 /*
2123 * configure ARP filter IP addresses to the driver,
2124 * intentionally outside the mgd mutex.
2125 */
2126 rtnl_lock();
2127 ieee80211_set_arp_filter(wk->sdata);
2128 rtnl_unlock();
2129#endif
2081 } 2130 }
2082 mutex_unlock(&wk->sdata->u.mgd.mtx);
2083 } 2131 }
2084 2132
2085 cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); 2133 cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);
@@ -2308,6 +2356,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2308int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, 2356int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata,
2309 struct ieee80211_channel *chan, 2357 struct ieee80211_channel *chan,
2310 enum nl80211_channel_type channel_type, 2358 enum nl80211_channel_type channel_type,
2359 bool channel_type_valid,
2311 const u8 *buf, size_t len, u64 *cookie) 2360 const u8 *buf, size_t len, u64 *cookie)
2312{ 2361{
2313 struct ieee80211_local *local = sdata->local; 2362 struct ieee80211_local *local = sdata->local;
@@ -2315,9 +2364,11 @@ int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata,
2315 struct sk_buff *skb; 2364 struct sk_buff *skb;
2316 2365
2317 /* Check that we are on the requested channel for transmission */ 2366 /* Check that we are on the requested channel for transmission */
2318 if ((chan != local->tmp_channel || 2367 if (chan != local->tmp_channel &&
2319 channel_type != local->tmp_channel_type) && 2368 chan != local->oper_channel)
2320 (chan != local->oper_channel || 2369 return -EBUSY;
2370 if (channel_type_valid &&
2371 (channel_type != local->tmp_channel_type &&
2321 channel_type != local->_oper_channel_type)) 2372 channel_type != local->_oper_channel_type))
2322 return -EBUSY; 2373 return -EBUSY;
2323 2374
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index 065a96190e32..168427b0ffdc 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -147,5 +147,18 @@ static inline void rc80211_minstrel_exit(void)
147} 147}
148#endif 148#endif
149 149
150#ifdef CONFIG_MAC80211_RC_MINSTREL_HT
151extern int rc80211_minstrel_ht_init(void);
152extern void rc80211_minstrel_ht_exit(void);
153#else
154static inline int rc80211_minstrel_ht_init(void)
155{
156 return 0;
157}
158static inline void rc80211_minstrel_ht_exit(void)
159{
160}
161#endif
162
150 163
151#endif /* IEEE80211_RATE_H */ 164#endif /* IEEE80211_RATE_H */
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
new file mode 100644
index 000000000000..c23f08251da4
--- /dev/null
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -0,0 +1,824 @@
1/*
2 * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/netdevice.h>
9#include <linux/types.h>
10#include <linux/skbuff.h>
11#include <linux/debugfs.h>
12#include <linux/random.h>
13#include <linux/ieee80211.h>
14#include <net/mac80211.h>
15#include "rate.h"
16#include "rc80211_minstrel.h"
17#include "rc80211_minstrel_ht.h"
18
19#define AVG_PKT_SIZE 1200
20#define SAMPLE_COLUMNS 10
21#define EWMA_LEVEL 75
22
23/* Number of bits for an average sized packet */
24#define MCS_NBITS (AVG_PKT_SIZE << 3)
25
26/* Number of symbols for a packet with (bps) bits per symbol */
27#define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps))
28
29/* Transmission time for a packet containing (syms) symbols */
30#define MCS_SYMBOL_TIME(sgi, syms) \
31 (sgi ? \
32 ((syms) * 18 + 4) / 5 : /* syms * 3.6 us */ \
33 (syms) << 2 /* syms * 4 us */ \
34 )
35
36/* Transmit duration for the raw data part of an average sized packet */
37#define MCS_DURATION(streams, sgi, bps) MCS_SYMBOL_TIME(sgi, MCS_NSYMS((streams) * (bps)))
38
39/* MCS rate information for an MCS group */
40#define MCS_GROUP(_streams, _sgi, _ht40) { \
41 .streams = _streams, \
42 .flags = \
43 (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \
44 (_ht40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \
45 .duration = { \
46 MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26), \
47 MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52), \
48 MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78), \
49 MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104), \
50 MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156), \
51 MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208), \
52 MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234), \
53 MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) \
54 } \
55}
56
57/*
58 * To enable sufficiently targeted rate sampling, MCS rates are divided into
59 * groups, based on the number of streams and flags (HT40, SGI) that they
60 * use.
61 */
62const struct mcs_group minstrel_mcs_groups[] = {
63 MCS_GROUP(1, 0, 0),
64 MCS_GROUP(2, 0, 0),
65#if MINSTREL_MAX_STREAMS >= 3
66 MCS_GROUP(3, 0, 0),
67#endif
68
69 MCS_GROUP(1, 1, 0),
70 MCS_GROUP(2, 1, 0),
71#if MINSTREL_MAX_STREAMS >= 3
72 MCS_GROUP(3, 1, 0),
73#endif
74
75 MCS_GROUP(1, 0, 1),
76 MCS_GROUP(2, 0, 1),
77#if MINSTREL_MAX_STREAMS >= 3
78 MCS_GROUP(3, 0, 1),
79#endif
80
81 MCS_GROUP(1, 1, 1),
82 MCS_GROUP(2, 1, 1),
83#if MINSTREL_MAX_STREAMS >= 3
84 MCS_GROUP(3, 1, 1),
85#endif
86};
87
88static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES];
89
90/*
91 * Perform EWMA (Exponentially Weighted Moving Average) calculation
92 */
93static int
94minstrel_ewma(int old, int new, int weight)
95{
96 return (new * (100 - weight) + old * weight) / 100;
97}
98
99/*
100 * Look up an MCS group index based on mac80211 rate information
101 */
102static int
103minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate)
104{
105 int streams = (rate->idx / MCS_GROUP_RATES) + 1;
106 u32 flags = IEEE80211_TX_RC_SHORT_GI | IEEE80211_TX_RC_40_MHZ_WIDTH;
107 int i;
108
109 for (i = 0; i < ARRAY_SIZE(minstrel_mcs_groups); i++) {
110 if (minstrel_mcs_groups[i].streams != streams)
111 continue;
112 if (minstrel_mcs_groups[i].flags != (rate->flags & flags))
113 continue;
114
115 return i;
116 }
117
118 WARN_ON(1);
119 return 0;
120}
121
122static inline struct minstrel_rate_stats *
123minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index)
124{
125 return &mi->groups[index / MCS_GROUP_RATES].rates[index % MCS_GROUP_RATES];
126}
127
128
129/*
130 * Recalculate success probabilities and counters for a rate using EWMA
131 */
132static void
133minstrel_calc_rate_ewma(struct minstrel_priv *mp, struct minstrel_rate_stats *mr)
134{
135 if (unlikely(mr->attempts > 0)) {
136 mr->sample_skipped = 0;
137 mr->cur_prob = MINSTREL_FRAC(mr->success, mr->attempts);
138 if (!mr->att_hist)
139 mr->probability = mr->cur_prob;
140 else
141 mr->probability = minstrel_ewma(mr->probability,
142 mr->cur_prob, EWMA_LEVEL);
143 mr->att_hist += mr->attempts;
144 mr->succ_hist += mr->success;
145 } else {
146 mr->sample_skipped++;
147 }
148 mr->last_success = mr->success;
149 mr->last_attempts = mr->attempts;
150 mr->success = 0;
151 mr->attempts = 0;
152}
153
154/*
155 * Calculate throughput based on the average A-MPDU length, taking into account
156 * the expected number of retransmissions and their expected length
157 */
158static void
159minstrel_ht_calc_tp(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
160 int group, int rate)
161{
162 struct minstrel_rate_stats *mr;
163 unsigned int usecs;
164
165 mr = &mi->groups[group].rates[rate];
166
167 if (mr->probability < MINSTREL_FRAC(1, 10)) {
168 mr->cur_tp = 0;
169 return;
170 }
171
172 usecs = mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
173 usecs += minstrel_mcs_groups[group].duration[rate];
174 mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability);
175}
176
177/*
178 * Update rate statistics and select new primary rates
179 *
180 * Rules for rate selection:
181 * - max_prob_rate must use only one stream, as a tradeoff between delivery
182 * probability and throughput during strong fluctuations
183 * - as long as the max prob rate has a probability of more than 3/4, pick
184 * higher throughput rates, even if the probablity is a bit lower
185 */
186static void
187minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
188{
189 struct minstrel_mcs_group_data *mg;
190 struct minstrel_rate_stats *mr;
191 int cur_prob, cur_prob_tp, cur_tp, cur_tp2;
192 int group, i, index;
193
194 if (mi->ampdu_packets > 0) {
195 mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len,
196 MINSTREL_FRAC(mi->ampdu_len, mi->ampdu_packets), EWMA_LEVEL);
197 mi->ampdu_len = 0;
198 mi->ampdu_packets = 0;
199 }
200
201 mi->sample_slow = 0;
202 mi->sample_count = 0;
203 mi->max_tp_rate = 0;
204 mi->max_tp_rate2 = 0;
205 mi->max_prob_rate = 0;
206
207 for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
208 cur_prob = 0;
209 cur_prob_tp = 0;
210 cur_tp = 0;
211 cur_tp2 = 0;
212
213 mg = &mi->groups[group];
214 if (!mg->supported)
215 continue;
216
217 mg->max_tp_rate = 0;
218 mg->max_tp_rate2 = 0;
219 mg->max_prob_rate = 0;
220 mi->sample_count++;
221
222 for (i = 0; i < MCS_GROUP_RATES; i++) {
223 if (!(mg->supported & BIT(i)))
224 continue;
225
226 mr = &mg->rates[i];
227 mr->retry_updated = false;
228 index = MCS_GROUP_RATES * group + i;
229 minstrel_calc_rate_ewma(mp, mr);
230 minstrel_ht_calc_tp(mp, mi, group, i);
231
232 if (!mr->cur_tp)
233 continue;
234
235 /* ignore the lowest rate of each single-stream group */
236 if (!i && minstrel_mcs_groups[group].streams == 1)
237 continue;
238
239 if ((mr->cur_tp > cur_prob_tp && mr->probability >
240 MINSTREL_FRAC(3, 4)) || mr->probability > cur_prob) {
241 mg->max_prob_rate = index;
242 cur_prob = mr->probability;
243 }
244
245 if (mr->cur_tp > cur_tp) {
246 swap(index, mg->max_tp_rate);
247 cur_tp = mr->cur_tp;
248 mr = minstrel_get_ratestats(mi, index);
249 }
250
251 if (index >= mg->max_tp_rate)
252 continue;
253
254 if (mr->cur_tp > cur_tp2) {
255 mg->max_tp_rate2 = index;
256 cur_tp2 = mr->cur_tp;
257 }
258 }
259 }
260
261 /* try to sample up to half of the availble rates during each interval */
262 mi->sample_count *= 4;
263
264 cur_prob = 0;
265 cur_prob_tp = 0;
266 cur_tp = 0;
267 cur_tp2 = 0;
268 for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
269 mg = &mi->groups[group];
270 if (!mg->supported)
271 continue;
272
273 mr = minstrel_get_ratestats(mi, mg->max_prob_rate);
274 if (cur_prob_tp < mr->cur_tp &&
275 minstrel_mcs_groups[group].streams == 1) {
276 mi->max_prob_rate = mg->max_prob_rate;
277 cur_prob = mr->cur_prob;
278 }
279
280 mr = minstrel_get_ratestats(mi, mg->max_tp_rate);
281 if (cur_tp < mr->cur_tp) {
282 mi->max_tp_rate = mg->max_tp_rate;
283 cur_tp = mr->cur_tp;
284 }
285
286 mr = minstrel_get_ratestats(mi, mg->max_tp_rate2);
287 if (cur_tp2 < mr->cur_tp) {
288 mi->max_tp_rate2 = mg->max_tp_rate2;
289 cur_tp2 = mr->cur_tp;
290 }
291 }
292
293 mi->stats_update = jiffies;
294}
295
296static bool
297minstrel_ht_txstat_valid(struct ieee80211_tx_rate *rate)
298{
299 if (!rate->count)
300 return false;
301
302 if (rate->idx < 0)
303 return false;
304
305 return !!(rate->flags & IEEE80211_TX_RC_MCS);
306}
307
308static void
309minstrel_next_sample_idx(struct minstrel_ht_sta *mi)
310{
311 struct minstrel_mcs_group_data *mg;
312
313 for (;;) {
314 mi->sample_group++;
315 mi->sample_group %= ARRAY_SIZE(minstrel_mcs_groups);
316 mg = &mi->groups[mi->sample_group];
317
318 if (!mg->supported)
319 continue;
320
321 if (++mg->index >= MCS_GROUP_RATES) {
322 mg->index = 0;
323 if (++mg->column >= ARRAY_SIZE(sample_table))
324 mg->column = 0;
325 }
326 break;
327 }
328}
329
330static void
331minstrel_downgrade_rate(struct minstrel_ht_sta *mi, int *idx, bool primary)
332{
333 int group, orig_group;
334
335 orig_group = group = *idx / MCS_GROUP_RATES;
336 while (group > 0) {
337 group--;
338
339 if (!mi->groups[group].supported)
340 continue;
341
342 if (minstrel_mcs_groups[group].streams >
343 minstrel_mcs_groups[orig_group].streams)
344 continue;
345
346 if (primary)
347 *idx = mi->groups[group].max_tp_rate;
348 else
349 *idx = mi->groups[group].max_tp_rate2;
350 break;
351 }
352}
353
354static void
355minstrel_aggr_check(struct minstrel_priv *mp, struct ieee80211_sta *pubsta, struct sk_buff *skb)
356{
357 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
358 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
359 u16 tid;
360
361 if (unlikely(!ieee80211_is_data_qos(hdr->frame_control)))
362 return;
363
364 if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE)))
365 return;
366
367 tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
368 if (likely(sta->ampdu_mlme.tid_state_tx[tid] != HT_AGG_STATE_IDLE))
369 return;
370
371 ieee80211_start_tx_ba_session(pubsta, tid);
372}
373
374static void
375minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
376 struct ieee80211_sta *sta, void *priv_sta,
377 struct sk_buff *skb)
378{
379 struct minstrel_ht_sta_priv *msp = priv_sta;
380 struct minstrel_ht_sta *mi = &msp->ht;
381 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
382 struct ieee80211_tx_rate *ar = info->status.rates;
383 struct minstrel_rate_stats *rate, *rate2;
384 struct minstrel_priv *mp = priv;
385 bool last = false;
386 int group;
387 int i = 0;
388
389 if (!msp->is_ht)
390 return mac80211_minstrel.tx_status(priv, sband, sta, &msp->legacy, skb);
391
392 /* This packet was aggregated but doesn't carry status info */
393 if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
394 !(info->flags & IEEE80211_TX_STAT_AMPDU))
395 return;
396
397 if (!info->status.ampdu_len) {
398 info->status.ampdu_ack_len = 1;
399 info->status.ampdu_len = 1;
400 }
401
402 mi->ampdu_packets++;
403 mi->ampdu_len += info->status.ampdu_len;
404
405 if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) {
406 mi->sample_wait = 4 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len);
407 mi->sample_tries = 3;
408 mi->sample_count--;
409 }
410
411 if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) {
412 mi->sample_packets += info->status.ampdu_len;
413 minstrel_next_sample_idx(mi);
414 }
415
416 for (i = 0; !last; i++) {
417 last = (i == IEEE80211_TX_MAX_RATES - 1) ||
418 !minstrel_ht_txstat_valid(&ar[i + 1]);
419
420 if (!minstrel_ht_txstat_valid(&ar[i]))
421 break;
422
423 group = minstrel_ht_get_group_idx(&ar[i]);
424 rate = &mi->groups[group].rates[ar[i].idx % 8];
425
426 if (last && (info->flags & IEEE80211_TX_STAT_ACK))
427 rate->success += info->status.ampdu_ack_len;
428
429 rate->attempts += ar[i].count * info->status.ampdu_len;
430 }
431
432 /*
433 * check for sudden death of spatial multiplexing,
434 * downgrade to a lower number of streams if necessary.
435 */
436 rate = minstrel_get_ratestats(mi, mi->max_tp_rate);
437 if (rate->attempts > 30 &&
438 MINSTREL_FRAC(rate->success, rate->attempts) <
439 MINSTREL_FRAC(20, 100))
440 minstrel_downgrade_rate(mi, &mi->max_tp_rate, true);
441
442 rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2);
443 if (rate->attempts > 30 &&
444 MINSTREL_FRAC(rate->success, rate->attempts) <
445 MINSTREL_FRAC(20, 100))
446 minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false);
447
448 if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
449 minstrel_ht_update_stats(mp, mi);
450 minstrel_aggr_check(mp, sta, skb);
451 }
452}
453
454static void
455minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
456 int index)
457{
458 struct minstrel_rate_stats *mr;
459 const struct mcs_group *group;
460 unsigned int tx_time, tx_time_rtscts, tx_time_data;
461 unsigned int cw = mp->cw_min;
462 unsigned int t_slot = 9; /* FIXME */
463 unsigned int ampdu_len = MINSTREL_TRUNC(mi->avg_ampdu_len);
464
465 mr = minstrel_get_ratestats(mi, index);
466 if (mr->probability < MINSTREL_FRAC(1, 10)) {
467 mr->retry_count = 1;
468 mr->retry_count_rtscts = 1;
469 return;
470 }
471
472 mr->retry_count = 2;
473 mr->retry_count_rtscts = 2;
474 mr->retry_updated = true;
475
476 group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
477 tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len;
478 tx_time = 2 * (t_slot + mi->overhead + tx_time_data);
479 tx_time_rtscts = 2 * (t_slot + mi->overhead_rtscts + tx_time_data);
480 do {
481 cw = (cw << 1) | 1;
482 cw = min(cw, mp->cw_max);
483 tx_time += cw + t_slot + mi->overhead;
484 tx_time_rtscts += cw + t_slot + mi->overhead_rtscts;
485 if (tx_time_rtscts < mp->segment_size)
486 mr->retry_count_rtscts++;
487 } while ((tx_time < mp->segment_size) &&
488 (++mr->retry_count < mp->max_retry));
489}
490
491
492static void
493minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
494 struct ieee80211_tx_rate *rate, int index,
495 struct ieee80211_tx_rate_control *txrc,
496 bool sample, bool rtscts)
497{
498 const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
499 struct minstrel_rate_stats *mr;
500
501 mr = minstrel_get_ratestats(mi, index);
502 if (!mr->retry_updated)
503 minstrel_calc_retransmit(mp, mi, index);
504
505 if (mr->probability < MINSTREL_FRAC(20, 100))
506 rate->count = 2;
507 else if (rtscts)
508 rate->count = mr->retry_count_rtscts;
509 else
510 rate->count = mr->retry_count;
511
512 rate->flags = IEEE80211_TX_RC_MCS | group->flags;
513 if (txrc->short_preamble)
514 rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
515 if (txrc->rts || rtscts)
516 rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
517 rate->idx = index % MCS_GROUP_RATES + (group->streams - 1) * MCS_GROUP_RATES;
518}
519
520static inline int
521minstrel_get_duration(int index)
522{
523 const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
524 return group->duration[index % MCS_GROUP_RATES];
525}
526
527static int
528minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
529{
530 struct minstrel_rate_stats *mr;
531 struct minstrel_mcs_group_data *mg;
532 int sample_idx = 0;
533
534 if (mi->sample_wait > 0) {
535 mi->sample_wait--;
536 return -1;
537 }
538
539 if (!mi->sample_tries)
540 return -1;
541
542 mi->sample_tries--;
543 mg = &mi->groups[mi->sample_group];
544 sample_idx = sample_table[mg->column][mg->index];
545 mr = &mg->rates[sample_idx];
546 sample_idx += mi->sample_group * MCS_GROUP_RATES;
547
548 /*
549 * When not using MRR, do not sample if the probability is already
550 * higher than 95% to avoid wasting airtime
551 */
552 if (!mp->has_mrr && (mr->probability > MINSTREL_FRAC(95, 100)))
553 goto next;
554
555 /*
556 * Make sure that lower rates get sampled only occasionally,
557 * if the link is working perfectly.
558 */
559 if (minstrel_get_duration(sample_idx) >
560 minstrel_get_duration(mi->max_tp_rate)) {
561 if (mr->sample_skipped < 10)
562 goto next;
563
564 if (mi->sample_slow++ > 2)
565 goto next;
566 }
567
568 return sample_idx;
569
570next:
571 minstrel_next_sample_idx(mi);
572 return -1;
573}
574
575static void
576minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
577 struct ieee80211_tx_rate_control *txrc)
578{
579 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
580 struct ieee80211_tx_rate *ar = info->status.rates;
581 struct minstrel_ht_sta_priv *msp = priv_sta;
582 struct minstrel_ht_sta *mi = &msp->ht;
583 struct minstrel_priv *mp = priv;
584 int sample_idx;
585
586 if (rate_control_send_low(sta, priv_sta, txrc))
587 return;
588
589 if (!msp->is_ht)
590 return mac80211_minstrel.get_rate(priv, sta, &msp->legacy, txrc);
591
592 info->flags |= mi->tx_flags;
593 sample_idx = minstrel_get_sample_rate(mp, mi);
594 if (sample_idx >= 0) {
595 minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
596 txrc, true, false);
597 minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
598 txrc, false, true);
599 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
600 } else {
601 minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
602 txrc, false, false);
603 minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
604 txrc, false, true);
605 }
606 minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate, txrc, false, true);
607
608 ar[3].count = 0;
609 ar[3].idx = -1;
610
611 mi->total_packets++;
612
613 /* wraparound */
614 if (mi->total_packets == ~0) {
615 mi->total_packets = 0;
616 mi->sample_packets = 0;
617 }
618}
619
620static void
621minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
622 struct ieee80211_sta *sta, void *priv_sta,
623 enum nl80211_channel_type oper_chan_type)
624{
625 struct minstrel_priv *mp = priv;
626 struct minstrel_ht_sta_priv *msp = priv_sta;
627 struct minstrel_ht_sta *mi = &msp->ht;
628 struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
629 struct ieee80211_local *local = hw_to_local(mp->hw);
630 u16 sta_cap = sta->ht_cap.cap;
631 int ack_dur;
632 int stbc;
633 int i;
634
635 /* fall back to the old minstrel for legacy stations */
636 if (sta && !sta->ht_cap.ht_supported) {
637 msp->is_ht = false;
638 memset(&msp->legacy, 0, sizeof(msp->legacy));
639 msp->legacy.r = msp->ratelist;
640 msp->legacy.sample_table = msp->sample_table;
641 return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy);
642 }
643
644 BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) !=
645 MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS);
646
647 msp->is_ht = true;
648 memset(mi, 0, sizeof(*mi));
649 mi->stats_update = jiffies;
650
651 ack_dur = ieee80211_frame_duration(local, 10, 60, 1, 1);
652 mi->overhead = ieee80211_frame_duration(local, 0, 60, 1, 1) + ack_dur;
653 mi->overhead_rtscts = mi->overhead + 2 * ack_dur;
654
655 mi->avg_ampdu_len = MINSTREL_FRAC(1, 1);
656
657 /* When using MRR, sample more on the first attempt, without delay */
658 if (mp->has_mrr) {
659 mi->sample_count = 16;
660 mi->sample_wait = 0;
661 } else {
662 mi->sample_count = 8;
663 mi->sample_wait = 8;
664 }
665 mi->sample_tries = 4;
666
667 stbc = (sta_cap & IEEE80211_HT_CAP_RX_STBC) >>
668 IEEE80211_HT_CAP_RX_STBC_SHIFT;
669 mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
670
671 if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING)
672 mi->tx_flags |= IEEE80211_TX_CTL_LDPC;
673
674 if (oper_chan_type != NL80211_CHAN_HT40MINUS &&
675 oper_chan_type != NL80211_CHAN_HT40PLUS)
676 sta_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
677
678 for (i = 0; i < ARRAY_SIZE(mi->groups); i++) {
679 u16 req = 0;
680
681 mi->groups[i].supported = 0;
682 if (minstrel_mcs_groups[i].flags & IEEE80211_TX_RC_SHORT_GI) {
683 if (minstrel_mcs_groups[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
684 req |= IEEE80211_HT_CAP_SGI_40;
685 else
686 req |= IEEE80211_HT_CAP_SGI_20;
687 }
688
689 if (minstrel_mcs_groups[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
690 req |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
691
692 if ((sta_cap & req) != req)
693 continue;
694
695 mi->groups[i].supported =
696 mcs->rx_mask[minstrel_mcs_groups[i].streams - 1];
697 }
698}
699
700static void
701minstrel_ht_rate_init(void *priv, struct ieee80211_supported_band *sband,
702 struct ieee80211_sta *sta, void *priv_sta)
703{
704 struct minstrel_priv *mp = priv;
705
706 minstrel_ht_update_caps(priv, sband, sta, priv_sta, mp->hw->conf.channel_type);
707}
708
709static void
710minstrel_ht_rate_update(void *priv, struct ieee80211_supported_band *sband,
711 struct ieee80211_sta *sta, void *priv_sta,
712 u32 changed, enum nl80211_channel_type oper_chan_type)
713{
714 minstrel_ht_update_caps(priv, sband, sta, priv_sta, oper_chan_type);
715}
716
717static void *
718minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
719{
720 struct ieee80211_supported_band *sband;
721 struct minstrel_ht_sta_priv *msp;
722 struct minstrel_priv *mp = priv;
723 struct ieee80211_hw *hw = mp->hw;
724 int max_rates = 0;
725 int i;
726
727 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
728 sband = hw->wiphy->bands[i];
729 if (sband && sband->n_bitrates > max_rates)
730 max_rates = sband->n_bitrates;
731 }
732
733 msp = kzalloc(sizeof(struct minstrel_ht_sta), gfp);
734 if (!msp)
735 return NULL;
736
737 msp->ratelist = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp);
738 if (!msp->ratelist)
739 goto error;
740
741 msp->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp);
742 if (!msp->sample_table)
743 goto error1;
744
745 return msp;
746
747error1:
748 kfree(msp->sample_table);
749error:
750 kfree(msp);
751 return NULL;
752}
753
754static void
755minstrel_ht_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta)
756{
757 struct minstrel_ht_sta_priv *msp = priv_sta;
758
759 kfree(msp->sample_table);
760 kfree(msp->ratelist);
761 kfree(msp);
762}
763
764static void *
765minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
766{
767 return mac80211_minstrel.alloc(hw, debugfsdir);
768}
769
770static void
771minstrel_ht_free(void *priv)
772{
773 mac80211_minstrel.free(priv);
774}
775
776static struct rate_control_ops mac80211_minstrel_ht = {
777 .name = "minstrel_ht",
778 .tx_status = minstrel_ht_tx_status,
779 .get_rate = minstrel_ht_get_rate,
780 .rate_init = minstrel_ht_rate_init,
781 .rate_update = minstrel_ht_rate_update,
782 .alloc_sta = minstrel_ht_alloc_sta,
783 .free_sta = minstrel_ht_free_sta,
784 .alloc = minstrel_ht_alloc,
785 .free = minstrel_ht_free,
786#ifdef CONFIG_MAC80211_DEBUGFS
787 .add_sta_debugfs = minstrel_ht_add_sta_debugfs,
788 .remove_sta_debugfs = minstrel_ht_remove_sta_debugfs,
789#endif
790};
791
792
793static void
794init_sample_table(void)
795{
796 int col, i, new_idx;
797 u8 rnd[MCS_GROUP_RATES];
798
799 memset(sample_table, 0xff, sizeof(sample_table));
800 for (col = 0; col < SAMPLE_COLUMNS; col++) {
801 for (i = 0; i < MCS_GROUP_RATES; i++) {
802 get_random_bytes(rnd, sizeof(rnd));
803 new_idx = (i + rnd[i]) % MCS_GROUP_RATES;
804
805 while (sample_table[col][new_idx] != 0xff)
806 new_idx = (new_idx + 1) % MCS_GROUP_RATES;
807
808 sample_table[col][new_idx] = i;
809 }
810 }
811}
812
813int __init
814rc80211_minstrel_ht_init(void)
815{
816 init_sample_table();
817 return ieee80211_rate_control_register(&mac80211_minstrel_ht);
818}
819
820void
821rc80211_minstrel_ht_exit(void)
822{
823 ieee80211_rate_control_unregister(&mac80211_minstrel_ht);
824}
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
new file mode 100644
index 000000000000..696c0fc6e0b7
--- /dev/null
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -0,0 +1,128 @@
1/*
2 * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef __RC_MINSTREL_HT_H
10#define __RC_MINSTREL_HT_H
11
12/*
13 * The number of streams can be changed to 2 to reduce code
14 * size and memory footprint.
15 */
16#define MINSTREL_MAX_STREAMS 3
17#define MINSTREL_STREAM_GROUPS 4
18
19/* scaled fraction values */
20#define MINSTREL_SCALE 16
21#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)
22#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE)
23
24#define MCS_GROUP_RATES 8
25
26struct mcs_group {
27 u32 flags;
28 unsigned int streams;
29 unsigned int duration[MCS_GROUP_RATES];
30};
31
32struct minstrel_rate_stats {
33 /* current / last sampling period attempts/success counters */
34 unsigned int attempts, last_attempts;
35 unsigned int success, last_success;
36
37 /* total attempts/success counters */
38 u64 att_hist, succ_hist;
39
40 /* current throughput */
41 unsigned int cur_tp;
42
43 /* packet delivery probabilities */
44 unsigned int cur_prob, probability;
45
46 /* maximum retry counts */
47 unsigned int retry_count;
48 unsigned int retry_count_rtscts;
49
50 bool retry_updated;
51 u8 sample_skipped;
52};
53
54struct minstrel_mcs_group_data {
55 u8 index;
56 u8 column;
57
58 /* bitfield of supported MCS rates of this group */
59 u8 supported;
60
61 /* selected primary rates */
62 unsigned int max_tp_rate;
63 unsigned int max_tp_rate2;
64 unsigned int max_prob_rate;
65
66 /* MCS rate statistics */
67 struct minstrel_rate_stats rates[MCS_GROUP_RATES];
68};
69
70struct minstrel_ht_sta {
71 /* ampdu length (average, per sampling interval) */
72 unsigned int ampdu_len;
73 unsigned int ampdu_packets;
74
75 /* ampdu length (EWMA) */
76 unsigned int avg_ampdu_len;
77
78 /* best throughput rate */
79 unsigned int max_tp_rate;
80
81 /* second best throughput rate */
82 unsigned int max_tp_rate2;
83
84 /* best probability rate */
85 unsigned int max_prob_rate;
86
87 /* time of last status update */
88 unsigned long stats_update;
89
90 /* overhead time in usec for each frame */
91 unsigned int overhead;
92 unsigned int overhead_rtscts;
93
94 unsigned int total_packets;
95 unsigned int sample_packets;
96
97 /* tx flags to add for frames for this sta */
98 u32 tx_flags;
99
100 u8 sample_wait;
101 u8 sample_tries;
102 u8 sample_count;
103 u8 sample_slow;
104
105 /* current MCS group to be sampled */
106 u8 sample_group;
107
108 /* MCS rate group info and statistics */
109 struct minstrel_mcs_group_data groups[MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS];
110};
111
112struct minstrel_ht_sta_priv {
113 union {
114 struct minstrel_ht_sta ht;
115 struct minstrel_sta_info legacy;
116 };
117#ifdef CONFIG_MAC80211_DEBUGFS
118 struct dentry *dbg_stats;
119#endif
120 void *ratelist;
121 void *sample_table;
122 bool is_ht;
123};
124
125void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
126void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta);
127
128#endif
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
new file mode 100644
index 000000000000..4fb3ccbd8b40
--- /dev/null
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -0,0 +1,120 @@
1/*
2 * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/netdevice.h>
9#include <linux/types.h>
10#include <linux/skbuff.h>
11#include <linux/debugfs.h>
12#include <linux/ieee80211.h>
13#include <net/mac80211.h>
14#include "rc80211_minstrel.h"
15#include "rc80211_minstrel_ht.h"
16
17extern const struct mcs_group minstrel_mcs_groups[];
18
19static int
20minstrel_ht_stats_open(struct inode *inode, struct file *file)
21{
22 struct minstrel_ht_sta_priv *msp = inode->i_private;
23 struct minstrel_ht_sta *mi = &msp->ht;
24 struct minstrel_debugfs_info *ms;
25 unsigned int i, j, tp, prob, eprob;
26 char *p;
27 int ret;
28
29 if (!msp->is_ht) {
30 inode->i_private = &msp->legacy;
31 ret = minstrel_stats_open(inode, file);
32 inode->i_private = msp;
33 return ret;
34 }
35
36 ms = kmalloc(sizeof(*ms) + 8192, GFP_KERNEL);
37 if (!ms)
38 return -ENOMEM;
39
40 file->private_data = ms;
41 p = ms->buf;
42 p += sprintf(p, "type rate throughput ewma prob this prob "
43 "this succ/attempt success attempts\n");
44 for (i = 0; i < MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS; i++) {
45 char htmode = '2';
46 char gimode = 'L';
47
48 if (!mi->groups[i].supported)
49 continue;
50
51 if (minstrel_mcs_groups[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
52 htmode = '4';
53 if (minstrel_mcs_groups[i].flags & IEEE80211_TX_RC_SHORT_GI)
54 gimode = 'S';
55
56 for (j = 0; j < MCS_GROUP_RATES; j++) {
57 struct minstrel_rate_stats *mr = &mi->groups[i].rates[j];
58 int idx = i * MCS_GROUP_RATES + j;
59
60 if (!(mi->groups[i].supported & BIT(j)))
61 continue;
62
63 p += sprintf(p, "HT%c0/%cGI ", htmode, gimode);
64
65 *(p++) = (idx == mi->max_tp_rate) ? 'T' : ' ';
66 *(p++) = (idx == mi->max_tp_rate2) ? 't' : ' ';
67 *(p++) = (idx == mi->max_prob_rate) ? 'P' : ' ';
68 p += sprintf(p, "MCS%-2u", (minstrel_mcs_groups[i].streams - 1) *
69 MCS_GROUP_RATES + j);
70
71 tp = mr->cur_tp / 10;
72 prob = MINSTREL_TRUNC(mr->cur_prob * 1000);
73 eprob = MINSTREL_TRUNC(mr->probability * 1000);
74
75 p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u "
76 "%3u(%3u) %8llu %8llu\n",
77 tp / 10, tp % 10,
78 eprob / 10, eprob % 10,
79 prob / 10, prob % 10,
80 mr->last_success,
81 mr->last_attempts,
82 (unsigned long long)mr->succ_hist,
83 (unsigned long long)mr->att_hist);
84 }
85 }
86 p += sprintf(p, "\nTotal packet count:: ideal %d "
87 "lookaround %d\n",
88 max(0, (int) mi->total_packets - (int) mi->sample_packets),
89 mi->sample_packets);
90 p += sprintf(p, "Average A-MPDU length: %d.%d\n",
91 MINSTREL_TRUNC(mi->avg_ampdu_len),
92 MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
93 ms->len = p - ms->buf;
94
95 return 0;
96}
97
98static const struct file_operations minstrel_ht_stat_fops = {
99 .owner = THIS_MODULE,
100 .open = minstrel_ht_stats_open,
101 .read = minstrel_stats_read,
102 .release = minstrel_stats_release,
103};
104
105void
106minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir)
107{
108 struct minstrel_ht_sta_priv *msp = priv_sta;
109
110 msp->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, msp,
111 &minstrel_ht_stat_fops);
112}
113
114void
115minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta)
116{
117 struct minstrel_ht_sta_priv *msp = priv_sta;
118
119 debugfs_remove(msp->dbg_stats);
120}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index dd232061e4c4..6a15632e7eca 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -825,6 +825,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
825 ieee80211_rx_result result = RX_DROP_UNUSABLE; 825 ieee80211_rx_result result = RX_DROP_UNUSABLE;
826 struct ieee80211_key *stakey = NULL; 826 struct ieee80211_key *stakey = NULL;
827 int mmie_keyidx = -1; 827 int mmie_keyidx = -1;
828 __le16 fc;
828 829
829 /* 830 /*
830 * Key selection 101 831 * Key selection 101
@@ -866,13 +867,15 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
866 if (rx->sta) 867 if (rx->sta)
867 stakey = rcu_dereference(rx->sta->key); 868 stakey = rcu_dereference(rx->sta->key);
868 869
869 if (!ieee80211_has_protected(hdr->frame_control)) 870 fc = hdr->frame_control;
871
872 if (!ieee80211_has_protected(fc))
870 mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); 873 mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
871 874
872 if (!is_multicast_ether_addr(hdr->addr1) && stakey) { 875 if (!is_multicast_ether_addr(hdr->addr1) && stakey) {
873 rx->key = stakey; 876 rx->key = stakey;
874 /* Skip decryption if the frame is not protected. */ 877 /* Skip decryption if the frame is not protected. */
875 if (!ieee80211_has_protected(hdr->frame_control)) 878 if (!ieee80211_has_protected(fc))
876 return RX_CONTINUE; 879 return RX_CONTINUE;
877 } else if (mmie_keyidx >= 0) { 880 } else if (mmie_keyidx >= 0) {
878 /* Broadcast/multicast robust management frame / BIP */ 881 /* Broadcast/multicast robust management frame / BIP */
@@ -884,7 +887,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
884 mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) 887 mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
885 return RX_DROP_MONITOR; /* unexpected BIP keyidx */ 888 return RX_DROP_MONITOR; /* unexpected BIP keyidx */
886 rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); 889 rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]);
887 } else if (!ieee80211_has_protected(hdr->frame_control)) { 890 } else if (!ieee80211_has_protected(fc)) {
888 /* 891 /*
889 * The frame was not protected, so skip decryption. However, we 892 * The frame was not protected, so skip decryption. However, we
890 * need to set rx->key if there is a key that could have been 893 * need to set rx->key if there is a key that could have been
@@ -892,7 +895,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
892 * have been expected. 895 * have been expected.
893 */ 896 */
894 struct ieee80211_key *key = NULL; 897 struct ieee80211_key *key = NULL;
895 if (ieee80211_is_mgmt(hdr->frame_control) && 898 if (ieee80211_is_mgmt(fc) &&
896 is_multicast_ether_addr(hdr->addr1) && 899 is_multicast_ether_addr(hdr->addr1) &&
897 (key = rcu_dereference(rx->sdata->default_mgmt_key))) 900 (key = rcu_dereference(rx->sdata->default_mgmt_key)))
898 rx->key = key; 901 rx->key = key;
@@ -914,7 +917,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
914 (status->flag & RX_FLAG_IV_STRIPPED)) 917 (status->flag & RX_FLAG_IV_STRIPPED))
915 return RX_CONTINUE; 918 return RX_CONTINUE;
916 919
917 hdrlen = ieee80211_hdrlen(hdr->frame_control); 920 hdrlen = ieee80211_hdrlen(fc);
918 921
919 if (rx->skb->len < 8 + hdrlen) 922 if (rx->skb->len < 8 + hdrlen)
920 return RX_DROP_UNUSABLE; /* TODO: count this? */ 923 return RX_DROP_UNUSABLE; /* TODO: count this? */
@@ -947,19 +950,17 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
947 950
948 if (skb_linearize(rx->skb)) 951 if (skb_linearize(rx->skb))
949 return RX_DROP_UNUSABLE; 952 return RX_DROP_UNUSABLE;
950 953 /* the hdr variable is invalid now! */
951 hdr = (struct ieee80211_hdr *)rx->skb->data;
952
953 /* Check for weak IVs if possible */
954 if (rx->sta && rx->key->conf.alg == ALG_WEP &&
955 ieee80211_is_data(hdr->frame_control) &&
956 (!(status->flag & RX_FLAG_IV_STRIPPED) ||
957 !(status->flag & RX_FLAG_DECRYPTED)) &&
958 ieee80211_wep_is_weak_iv(rx->skb, rx->key))
959 rx->sta->wep_weak_iv_count++;
960 954
961 switch (rx->key->conf.alg) { 955 switch (rx->key->conf.alg) {
962 case ALG_WEP: 956 case ALG_WEP:
957 /* Check for weak IVs if possible */
958 if (rx->sta && ieee80211_is_data(fc) &&
959 (!(status->flag & RX_FLAG_IV_STRIPPED) ||
960 !(status->flag & RX_FLAG_DECRYPTED)) &&
961 ieee80211_wep_is_weak_iv(rx->skb, rx->key))
962 rx->sta->wep_weak_iv_count++;
963
963 result = ieee80211_crypto_wep_decrypt(rx); 964 result = ieee80211_crypto_wep_decrypt(rx);
964 break; 965 break;
965 case ALG_TKIP: 966 case ALG_TKIP:
@@ -1852,7 +1853,12 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
1852 return RX_QUEUED; 1853 return RX_QUEUED;
1853 } 1854 }
1854 1855
1855 return RX_CONTINUE; 1856 /*
1857 * After this point, we only want management frames,
1858 * so we can drop all remaining control frames to
1859 * cooked monitor interfaces.
1860 */
1861 return RX_DROP_MONITOR;
1856} 1862}
1857 1863
1858static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, 1864static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
@@ -1944,6 +1950,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1944 if (len < IEEE80211_MIN_ACTION_SIZE + 1) 1950 if (len < IEEE80211_MIN_ACTION_SIZE + 1)
1945 break; 1951 break;
1946 1952
1953 if (sdata->vif.type == NL80211_IFTYPE_STATION)
1954 return ieee80211_sta_rx_mgmt(sdata, rx->skb);
1955
1947 switch (mgmt->u.action.u.addba_req.action_code) { 1956 switch (mgmt->u.action.u.addba_req.action_code) {
1948 case WLAN_ACTION_ADDBA_REQ: 1957 case WLAN_ACTION_ADDBA_REQ:
1949 if (len < (IEEE80211_MIN_ACTION_SIZE + 1958 if (len < (IEEE80211_MIN_ACTION_SIZE +
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index ba9360a475b0..4607da9a6ff7 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -648,14 +648,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
648 648
649 if (sta->key) { 649 if (sta->key) {
650 ieee80211_key_free(sta->key); 650 ieee80211_key_free(sta->key);
651 /*
652 * We have only unlinked the key, and actually destroying it
653 * may mean it is removed from hardware which requires that
654 * the key->sta pointer is still valid, so flush the key todo
655 * list here.
656 */
657 ieee80211_key_todo();
658
659 WARN_ON(sta->key); 651 WARN_ON(sta->key);
660 } 652 }
661 653
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index df9d45544ca5..813da34db733 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -120,6 +120,28 @@ struct tid_ampdu_rx {
120}; 120};
121 121
122/** 122/**
123 * struct sta_ampdu_mlme - STA aggregation information.
124 *
125 * @tid_active_rx: TID's state in Rx session state machine.
126 * @tid_rx: aggregation info for Rx per TID
127 * @tid_state_tx: TID's state in Tx session state machine.
128 * @tid_tx: aggregation info for Tx per TID
129 * @addba_req_num: number of times addBA request has been sent.
130 * @dialog_token_allocator: dialog token enumerator for each new session;
131 */
132struct sta_ampdu_mlme {
133 /* rx */
134 bool tid_active_rx[STA_TID_NUM];
135 struct tid_ampdu_rx *tid_rx[STA_TID_NUM];
136 /* tx */
137 u8 tid_state_tx[STA_TID_NUM];
138 struct tid_ampdu_tx *tid_tx[STA_TID_NUM];
139 u8 addba_req_num[STA_TID_NUM];
140 u8 dialog_token_allocator;
141};
142
143
144/**
123 * enum plink_state - state of a mesh peer link finite state machine 145 * enum plink_state - state of a mesh peer link finite state machine
124 * 146 *
125 * @PLINK_LISTEN: initial state, considered the implicit state of non existant 147 * @PLINK_LISTEN: initial state, considered the implicit state of non existant
@@ -143,28 +165,6 @@ enum plink_state {
143}; 165};
144 166
145/** 167/**
146 * struct sta_ampdu_mlme - STA aggregation information.
147 *
148 * @tid_active_rx: TID's state in Rx session state machine.
149 * @tid_rx: aggregation info for Rx per TID
150 * @tid_state_tx: TID's state in Tx session state machine.
151 * @tid_tx: aggregation info for Tx per TID
152 * @addba_req_num: number of times addBA request has been sent.
153 * @dialog_token_allocator: dialog token enumerator for each new session;
154 */
155struct sta_ampdu_mlme {
156 /* rx */
157 bool tid_active_rx[STA_TID_NUM];
158 struct tid_ampdu_rx *tid_rx[STA_TID_NUM];
159 /* tx */
160 u8 tid_state_tx[STA_TID_NUM];
161 struct tid_ampdu_tx *tid_tx[STA_TID_NUM];
162 u8 addba_req_num[STA_TID_NUM];
163 u8 dialog_token_allocator;
164};
165
166
167/**
168 * struct sta_info - STA information 168 * struct sta_info - STA information
169 * 169 *
170 * This structure collects information about a station that 170 * This structure collects information about a station that
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 94613af009f3..34da67995d94 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -47,7 +47,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
47 /* 47 /*
48 * This skb 'survived' a round-trip through the driver, and 48 * This skb 'survived' a round-trip through the driver, and
49 * hopefully the driver didn't mangle it too badly. However, 49 * hopefully the driver didn't mangle it too badly. However,
50 * we can definitely not rely on the the control information 50 * we can definitely not rely on the control information
51 * being correct. Clear it so we don't get junk there, and 51 * being correct. Clear it so we don't get junk there, and
52 * indicate that it needs new processing, but must not be 52 * indicate that it needs new processing, but must not be
53 * modified/encrypted again. 53 * modified/encrypted again.
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index be3d4a698692..4157717ed786 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -840,7 +840,7 @@ static void ieee80211_work_work(struct work_struct *work)
840 840
841 /* 841 /*
842 * ieee80211_queue_work() should have picked up most cases, 842 * ieee80211_queue_work() should have picked up most cases,
843 * here we'll pick the the rest. 843 * here we'll pick the rest.
844 */ 844 */
845 if (WARN(local->suspended, "work scheduled while going to suspend\n")) 845 if (WARN(local->suspended, "work scheduled while going to suspend\n"))
846 return; 846 return;
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index b01a6f6397d7..d0c92dddb26b 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -35,8 +35,9 @@ rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
35 if (!ht_cap->ht_supported) 35 if (!ht_cap->ht_supported)
36 return NULL; 36 return NULL;
37 37
38 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || 38 if (channel_type != NL80211_CHAN_HT20 &&
39 ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT) 39 (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
40 ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT))
40 return NULL; 41 return NULL;
41 } 42 }
42 43
diff --git a/net/wireless/core.h b/net/wireless/core.h
index ae930acf75e9..63d57ae399c3 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -339,6 +339,7 @@ int cfg80211_mlme_action(struct cfg80211_registered_device *rdev,
339 struct net_device *dev, 339 struct net_device *dev,
340 struct ieee80211_channel *chan, 340 struct ieee80211_channel *chan,
341 enum nl80211_channel_type channel_type, 341 enum nl80211_channel_type channel_type,
342 bool channel_type_valid,
342 const u8 *buf, size_t len, u64 *cookie); 343 const u8 *buf, size_t len, u64 *cookie);
343 344
344/* SME */ 345/* SME */
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 48ead6f0426d..f69ae19f497f 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -827,6 +827,7 @@ int cfg80211_mlme_action(struct cfg80211_registered_device *rdev,
827 struct net_device *dev, 827 struct net_device *dev,
828 struct ieee80211_channel *chan, 828 struct ieee80211_channel *chan,
829 enum nl80211_channel_type channel_type, 829 enum nl80211_channel_type channel_type,
830 bool channel_type_valid,
830 const u8 *buf, size_t len, u64 *cookie) 831 const u8 *buf, size_t len, u64 *cookie)
831{ 832{
832 struct wireless_dev *wdev = dev->ieee80211_ptr; 833 struct wireless_dev *wdev = dev->ieee80211_ptr;
@@ -855,7 +856,7 @@ int cfg80211_mlme_action(struct cfg80211_registered_device *rdev,
855 856
856 /* Transmit the Action frame as requested by user space */ 857 /* Transmit the Action frame as requested by user space */
857 return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type, 858 return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type,
858 buf, len, cookie); 859 channel_type_valid, buf, len, cookie);
859} 860}
860 861
861bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, 862bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index db71150b8040..90ab3c8519be 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4681,6 +4681,7 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info)
4681 struct net_device *dev; 4681 struct net_device *dev;
4682 struct ieee80211_channel *chan; 4682 struct ieee80211_channel *chan;
4683 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; 4683 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
4684 bool channel_type_valid = false;
4684 u32 freq; 4685 u32 freq;
4685 int err; 4686 int err;
4686 void *hdr; 4687 void *hdr;
@@ -4722,6 +4723,7 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info)
4722 err = -EINVAL; 4723 err = -EINVAL;
4723 goto out; 4724 goto out;
4724 } 4725 }
4726 channel_type_valid = true;
4725 } 4727 }
4726 4728
4727 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); 4729 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
@@ -4745,6 +4747,7 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info)
4745 goto free_msg; 4747 goto free_msg;
4746 } 4748 }
4747 err = cfg80211_mlme_action(rdev, dev, chan, channel_type, 4749 err = cfg80211_mlme_action(rdev, dev, chan, channel_type,
4750 channel_type_valid,
4748 nla_data(info->attrs[NL80211_ATTR_FRAME]), 4751 nla_data(info->attrs[NL80211_ATTR_FRAME]),
4749 nla_len(info->attrs[NL80211_ATTR_FRAME]), 4752 nla_len(info->attrs[NL80211_ATTR_FRAME]),
4750 &cookie); 4753 &cookie);