aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-12-21 22:57:10 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-21 22:57:10 -0500
commitc2da953a46b18b7515ad476c1c1686640a12e93a (patch)
treeb384f097718119e715cdebd74710ddceeb80fdc8 /net
parentc94cb314503a69492bf4455dce4f6d300cff0851 (diff)
parent9cf7f247bd0cd21e475c71a4e018bb612ef02aab (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c42
-rw-r--r--net/mac80211/ht.c35
-rw-r--r--net/mac80211/ieee80211_i.h25
-rw-r--r--net/mac80211/main.c39
-rw-r--r--net/mac80211/mlme.c70
-rw-r--r--net/mac80211/rx.c59
-rw-r--r--net/mac80211/tx.c13
-rw-r--r--net/mac80211/util.c88
-rw-r--r--net/mac80211/wext.c46
-rw-r--r--net/wireless/nl80211.c85
10 files changed, 421 insertions, 81 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7912eb14eca0..9d4e4d846ec1 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
310 310
311 sinfo->filled = STATION_INFO_INACTIVE_TIME | 311 sinfo->filled = STATION_INFO_INACTIVE_TIME |
312 STATION_INFO_RX_BYTES | 312 STATION_INFO_RX_BYTES |
313 STATION_INFO_TX_BYTES; 313 STATION_INFO_TX_BYTES |
314 STATION_INFO_TX_BITRATE;
314 315
315 sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); 316 sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
316 sinfo->rx_bytes = sta->rx_bytes; 317 sinfo->rx_bytes = sta->rx_bytes;
317 sinfo->tx_bytes = sta->tx_bytes; 318 sinfo->tx_bytes = sta->tx_bytes;
318 319
320 if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
321 sinfo->filled |= STATION_INFO_SIGNAL;
322 sinfo->signal = (s8)sta->last_signal;
323 }
324
325 sinfo->txrate.flags = 0;
326 if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
327 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
328 if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
329 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
330 if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
331 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
332
333 if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
334 struct ieee80211_supported_band *sband;
335 sband = sta->local->hw.wiphy->bands[
336 sta->local->hw.conf.channel->band];
337 sinfo->txrate.legacy =
338 sband->bitrates[sta->last_tx_rate.idx].bitrate;
339 } else
340 sinfo->txrate.mcs = sta->last_tx_rate.idx;
341
319 if (ieee80211_vif_is_mesh(&sdata->vif)) { 342 if (ieee80211_vif_is_mesh(&sdata->vif)) {
320#ifdef CONFIG_MAC80211_MESH 343#ifdef CONFIG_MAC80211_MESH
321 sinfo->filled |= STATION_INFO_LLID | 344 sinfo->filled |= STATION_INFO_LLID |
@@ -663,6 +686,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
663 struct sta_info *sta; 686 struct sta_info *sta;
664 struct ieee80211_sub_if_data *sdata; 687 struct ieee80211_sub_if_data *sdata;
665 int err; 688 int err;
689 int layer2_update;
666 690
667 /* Prevent a race with changing the rate control algorithm */ 691 /* Prevent a race with changing the rate control algorithm */
668 if (!netif_running(dev)) 692 if (!netif_running(dev))
@@ -693,17 +717,25 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
693 717
694 rate_control_rate_init(sta); 718 rate_control_rate_init(sta);
695 719
720 layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
721 sdata->vif.type == NL80211_IFTYPE_AP;
722
696 rcu_read_lock(); 723 rcu_read_lock();
697 724
698 err = sta_info_insert(sta); 725 err = sta_info_insert(sta);
699 if (err) { 726 if (err) {
700 /* STA has been freed */ 727 /* STA has been freed */
728 if (err == -EEXIST && layer2_update) {
729 /* Need to update layer 2 devices on reassociation */
730 sta = sta_info_get(local, mac);
731 if (sta)
732 ieee80211_send_layer2_update(sta);
733 }
701 rcu_read_unlock(); 734 rcu_read_unlock();
702 return err; 735 return err;
703 } 736 }
704 737
705 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || 738 if (layer2_update)
706 sdata->vif.type == NL80211_IFTYPE_AP)
707 ieee80211_send_layer2_update(sta); 739 ieee80211_send_layer2_update(sta);
708 740
709 rcu_read_unlock(); 741 rcu_read_unlock();
@@ -1099,12 +1131,12 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
1099 1131
1100static int ieee80211_set_channel(struct wiphy *wiphy, 1132static int ieee80211_set_channel(struct wiphy *wiphy,
1101 struct ieee80211_channel *chan, 1133 struct ieee80211_channel *chan,
1102 enum nl80211_sec_chan_offset sec_chan_offset) 1134 enum nl80211_channel_type channel_type)
1103{ 1135{
1104 struct ieee80211_local *local = wiphy_priv(wiphy); 1136 struct ieee80211_local *local = wiphy_priv(wiphy);
1105 1137
1106 local->oper_channel = chan; 1138 local->oper_channel = chan;
1107 local->oper_sec_chan_offset = sec_chan_offset; 1139 local->oper_channel_type = channel_type;
1108 1140
1109 return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 1141 return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
1110} 1142}
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index a1eed7032c9b..5f510a13b9f0 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -98,6 +98,7 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
98 struct ieee80211_bss_ht_conf ht; 98 struct ieee80211_bss_ht_conf ht;
99 u32 changed = 0; 99 u32 changed = 0;
100 bool enable_ht = true, ht_changed; 100 bool enable_ht = true, ht_changed;
101 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
101 102
102 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 103 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
103 104
@@ -112,24 +113,36 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
112 ieee80211_channel_to_frequency(hti->control_chan)) 113 ieee80211_channel_to_frequency(hti->control_chan))
113 enable_ht = false; 114 enable_ht = false;
114 115
115 /* 116 if (enable_ht) {
116 * XXX: This is totally incorrect when there are multiple virtual 117 channel_type = NL80211_CHAN_HT20;
117 * interfaces, needs to be fixed later. 118
118 */ 119 if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
119 ht_changed = local->hw.conf.ht.enabled != enable_ht; 120 (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
121 (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
122 switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
123 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
124 channel_type = NL80211_CHAN_HT40PLUS;
125 break;
126 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
127 channel_type = NL80211_CHAN_HT40MINUS;
128 break;
129 }
130 }
131 }
132
133 ht_changed = local->hw.conf.ht.enabled != enable_ht ||
134 channel_type != local->hw.conf.ht.channel_type;
135
136 local->oper_channel_type = channel_type;
120 local->hw.conf.ht.enabled = enable_ht; 137 local->hw.conf.ht.enabled = enable_ht;
138
121 if (ht_changed) 139 if (ht_changed)
122 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); 140 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT);
123 141
124 /* disable HT */ 142 /* disable HT */
125 if (!enable_ht) 143 if (!enable_ht)
126 return 0; 144 return 0;
127 ht.secondary_channel_offset = 145
128 hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
129 ht.width_40_ok =
130 !(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
131 (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
132 (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY);
133 ht.operation_mode = le16_to_cpu(hti->operation_mode); 146 ht.operation_mode = le16_to_cpu(hti->operation_mode);
134 147
135 /* if bss configuration changed store the new one */ 148 /* if bss configuration changed store the new one */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 6f59e11d7b33..f3eec989662b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -538,6 +538,11 @@ enum {
538 IEEE80211_ADDBA_MSG = 4, 538 IEEE80211_ADDBA_MSG = 4,
539}; 539};
540 540
541enum queue_stop_reason {
542 IEEE80211_QUEUE_STOP_REASON_DRIVER,
543 IEEE80211_QUEUE_STOP_REASON_PS,
544};
545
541/* maximum number of hardware queues we support. */ 546/* maximum number of hardware queues we support. */
542#define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) 547#define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES)
543 548
@@ -554,7 +559,8 @@ struct ieee80211_local {
554 const struct ieee80211_ops *ops; 559 const struct ieee80211_ops *ops;
555 560
556 unsigned long queue_pool[BITS_TO_LONGS(QD_MAX_QUEUES)]; 561 unsigned long queue_pool[BITS_TO_LONGS(QD_MAX_QUEUES)];
557 562 unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
563 spinlock_t queue_stop_reason_lock;
558 struct net_device *mdev; /* wmaster# - "master" 802.11 device */ 564 struct net_device *mdev; /* wmaster# - "master" 802.11 device */
559 int open_count; 565 int open_count;
560 int monitors, cooked_mntrs; 566 int monitors, cooked_mntrs;
@@ -625,7 +631,7 @@ struct ieee80211_local {
625 struct delayed_work scan_work; 631 struct delayed_work scan_work;
626 struct ieee80211_sub_if_data *scan_sdata; 632 struct ieee80211_sub_if_data *scan_sdata;
627 struct ieee80211_channel *oper_channel, *scan_channel; 633 struct ieee80211_channel *oper_channel, *scan_channel;
628 enum nl80211_sec_chan_offset oper_sec_chan_offset; 634 enum nl80211_channel_type oper_channel_type;
629 u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; 635 u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
630 size_t scan_ssid_len; 636 size_t scan_ssid_len;
631 struct list_head bss_list; 637 struct list_head bss_list;
@@ -689,6 +695,12 @@ struct ieee80211_local {
689 int wifi_wme_noack_test; 695 int wifi_wme_noack_test;
690 unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ 696 unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
691 697
698 bool powersave;
699 int dynamic_ps_timeout;
700 struct work_struct dynamic_ps_enable_work;
701 struct work_struct dynamic_ps_disable_work;
702 struct timer_list dynamic_ps_timer;
703
692#ifdef CONFIG_MAC80211_DEBUGFS 704#ifdef CONFIG_MAC80211_DEBUGFS
693 struct local_debugfsdentries { 705 struct local_debugfsdentries {
694 struct dentry *rcdir; 706 struct dentry *rcdir;
@@ -971,6 +983,15 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq);
971u64 ieee80211_mandatory_rates(struct ieee80211_local *local, 983u64 ieee80211_mandatory_rates(struct ieee80211_local *local,
972 enum ieee80211_band band); 984 enum ieee80211_band band);
973 985
986void ieee80211_dynamic_ps_enable_work(struct work_struct *work);
987void ieee80211_dynamic_ps_disable_work(struct work_struct *work);
988void ieee80211_dynamic_ps_timer(unsigned long data);
989
990void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
991 enum queue_stop_reason reason);
992void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
993 enum queue_stop_reason reason);
994
974#ifdef CONFIG_MAC80211_NOINLINE 995#ifdef CONFIG_MAC80211_NOINLINE
975#define debug_noinline noinline 996#define debug_noinline noinline
976#else 997#else
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 6d8710327d14..24b14363d6e7 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -195,37 +195,30 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
195 struct ieee80211_channel *chan; 195 struct ieee80211_channel *chan;
196 int ret = 0; 196 int ret = 0;
197 int power; 197 int power;
198 enum nl80211_sec_chan_offset sec_chan_offset; 198 enum nl80211_channel_type channel_type;
199 199
200 might_sleep(); 200 might_sleep();
201 201
202 if (local->sw_scanning) { 202 if (local->sw_scanning) {
203 chan = local->scan_channel; 203 chan = local->scan_channel;
204 sec_chan_offset = NL80211_SEC_CHAN_NO_HT; 204 channel_type = NL80211_CHAN_NO_HT;
205 } else { 205 } else {
206 chan = local->oper_channel; 206 chan = local->oper_channel;
207 sec_chan_offset = local->oper_sec_chan_offset; 207 channel_type = local->oper_channel_type;
208 } 208 }
209 209
210 if (chan != local->hw.conf.channel || 210 if (chan != local->hw.conf.channel ||
211 sec_chan_offset != local->hw.conf.ht.sec_chan_offset) { 211 channel_type != local->hw.conf.ht.channel_type) {
212 local->hw.conf.channel = chan; 212 local->hw.conf.channel = chan;
213 switch (sec_chan_offset) { 213 local->hw.conf.ht.channel_type = channel_type;
214 case NL80211_SEC_CHAN_NO_HT: 214 switch (channel_type) {
215 case NL80211_CHAN_NO_HT:
215 local->hw.conf.ht.enabled = false; 216 local->hw.conf.ht.enabled = false;
216 local->hw.conf.ht.sec_chan_offset = 0;
217 break; 217 break;
218 case NL80211_SEC_CHAN_DISABLED: 218 case NL80211_CHAN_HT20:
219 case NL80211_CHAN_HT40MINUS:
220 case NL80211_CHAN_HT40PLUS:
219 local->hw.conf.ht.enabled = true; 221 local->hw.conf.ht.enabled = true;
220 local->hw.conf.ht.sec_chan_offset = 0;
221 break;
222 case NL80211_SEC_CHAN_BELOW:
223 local->hw.conf.ht.enabled = true;
224 local->hw.conf.ht.sec_chan_offset = -1;
225 break;
226 case NL80211_SEC_CHAN_ABOVE:
227 local->hw.conf.ht.enabled = true;
228 local->hw.conf.ht.sec_chan_offset = 1;
229 break; 222 break;
230 } 223 }
231 changed |= IEEE80211_CONF_CHANGE_CHANNEL; 224 changed |= IEEE80211_CONF_CHANGE_CHANNEL;
@@ -348,7 +341,8 @@ static void ieee80211_tasklet_handler(unsigned long data)
348 dev_kfree_skb(skb); 341 dev_kfree_skb(skb);
349 break ; 342 break ;
350 default: 343 default:
351 WARN_ON(1); 344 WARN(1, "mac80211: Packet is of unknown type %d\n",
345 skb->pkt_type);
352 dev_kfree_skb(skb); 346 dev_kfree_skb(skb);
353 break; 347 break;
354 } 348 }
@@ -731,8 +725,17 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
731 725
732 spin_lock_init(&local->key_lock); 726 spin_lock_init(&local->key_lock);
733 727
728 spin_lock_init(&local->queue_stop_reason_lock);
729
734 INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); 730 INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
735 731
732 INIT_WORK(&local->dynamic_ps_enable_work,
733 ieee80211_dynamic_ps_enable_work);
734 INIT_WORK(&local->dynamic_ps_disable_work,
735 ieee80211_dynamic_ps_disable_work);
736 setup_timer(&local->dynamic_ps_timer,
737 ieee80211_dynamic_ps_timer, (unsigned long) local);
738
736 sta_info_init(local); 739 sta_info_init(local);
737 740
738 tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, 741 tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 290b0017ef2e..5ba721b6a399 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -309,7 +309,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
309 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 309 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
310 IEEE80211_STYPE_ASSOC_REQ); 310 IEEE80211_STYPE_ASSOC_REQ);
311 mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); 311 mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
312 mgmt->u.reassoc_req.listen_interval = 312 mgmt->u.assoc_req.listen_interval =
313 cpu_to_le16(local->hw.conf.listen_interval); 313 cpu_to_le16(local->hw.conf.listen_interval);
314 } 314 }
315 315
@@ -744,6 +744,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
744 bss_info_changed |= BSS_CHANGED_BASIC_RATES; 744 bss_info_changed |= BSS_CHANGED_BASIC_RATES;
745 ieee80211_bss_info_change_notify(sdata, bss_info_changed); 745 ieee80211_bss_info_change_notify(sdata, bss_info_changed);
746 746
747 if (local->powersave) {
748 if (local->dynamic_ps_timeout > 0)
749 mod_timer(&local->dynamic_ps_timer, jiffies +
750 msecs_to_jiffies(local->dynamic_ps_timeout));
751 else {
752 conf->flags |= IEEE80211_CONF_PS;
753 ieee80211_hw_config(local,
754 IEEE80211_CONF_CHANGE_PS);
755 }
756 }
757
747 netif_tx_start_all_queues(sdata->dev); 758 netif_tx_start_all_queues(sdata->dev);
748 netif_carrier_on(sdata->dev); 759 netif_carrier_on(sdata->dev);
749 760
@@ -812,7 +823,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
812{ 823{
813 struct ieee80211_local *local = sdata->local; 824 struct ieee80211_local *local = sdata->local;
814 struct sta_info *sta; 825 struct sta_info *sta;
815 u32 changed = 0; 826 u32 changed = 0, config_changed = 0;
816 827
817 rcu_read_lock(); 828 rcu_read_lock();
818 829
@@ -858,8 +869,18 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
858 rcu_read_unlock(); 869 rcu_read_unlock();
859 870
860 local->hw.conf.ht.enabled = false; 871 local->hw.conf.ht.enabled = false;
861 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); 872 local->oper_channel_type = NL80211_CHAN_NO_HT;
873 config_changed |= IEEE80211_CONF_CHANGE_HT;
874
875 del_timer_sync(&local->dynamic_ps_timer);
876 cancel_work_sync(&local->dynamic_ps_enable_work);
862 877
878 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
879 local->hw.conf.flags &= ~IEEE80211_CONF_PS;
880 config_changed |= IEEE80211_CONF_CHANGE_PS;
881 }
882
883 ieee80211_hw_config(local, config_changed);
863 ieee80211_bss_info_change_notify(sdata, changed); 884 ieee80211_bss_info_change_notify(sdata, changed);
864 885
865 rcu_read_lock(); 886 rcu_read_lock();
@@ -1612,8 +1633,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
1612 * e.g: at 1 MBit that means mactime is 192 usec earlier 1633 * e.g: at 1 MBit that means mactime is 192 usec earlier
1613 * (=24 bytes * 8 usecs/byte) than the beacon timestamp. 1634 * (=24 bytes * 8 usecs/byte) than the beacon timestamp.
1614 */ 1635 */
1615 int rate = local->hw.wiphy->bands[band]-> 1636 int rate;
1637 if (rx_status->flag & RX_FLAG_HT) {
1638 rate = 65; /* TODO: HT rates */
1639 } else {
1640 rate = local->hw.wiphy->bands[band]->
1616 bitrates[rx_status->rate_idx].bitrate; 1641 bitrates[rx_status->rate_idx].bitrate;
1642 }
1617 rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); 1643 rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate);
1618 } else if (local && local->ops && local->ops->get_tsf) 1644 } else if (local && local->ops && local->ops->get_tsf)
1619 /* second best option: get current TSF */ 1645 /* second best option: get current TSF */
@@ -2576,3 +2602,39 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
2576 ieee80211_restart_sta_timer(sdata); 2602 ieee80211_restart_sta_timer(sdata);
2577 rcu_read_unlock(); 2603 rcu_read_unlock();
2578} 2604}
2605
2606void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
2607{
2608 struct ieee80211_local *local =
2609 container_of(work, struct ieee80211_local,
2610 dynamic_ps_disable_work);
2611
2612 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
2613 local->hw.conf.flags &= ~IEEE80211_CONF_PS;
2614 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
2615 }
2616
2617 ieee80211_wake_queues_by_reason(&local->hw,
2618 IEEE80211_QUEUE_STOP_REASON_PS);
2619}
2620
2621void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
2622{
2623 struct ieee80211_local *local =
2624 container_of(work, struct ieee80211_local,
2625 dynamic_ps_enable_work);
2626
2627 if (local->hw.conf.flags & IEEE80211_CONF_PS)
2628 return;
2629
2630 local->hw.conf.flags |= IEEE80211_CONF_PS;
2631
2632 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
2633}
2634
2635void ieee80211_dynamic_ps_timer(unsigned long data)
2636{
2637 struct ieee80211_local *local = (void *) data;
2638
2639 queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work);
2640}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 73cf126cef49..7175ae80c36a 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -123,7 +123,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
123 /* radiotap header, set always present flags */ 123 /* radiotap header, set always present flags */
124 rthdr->it_present = 124 rthdr->it_present =
125 cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | 125 cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
126 (1 << IEEE80211_RADIOTAP_RATE) |
127 (1 << IEEE80211_RADIOTAP_CHANNEL) | 126 (1 << IEEE80211_RADIOTAP_CHANNEL) |
128 (1 << IEEE80211_RADIOTAP_ANTENNA) | 127 (1 << IEEE80211_RADIOTAP_ANTENNA) |
129 (1 << IEEE80211_RADIOTAP_RX_FLAGS)); 128 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
@@ -149,7 +148,19 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
149 pos++; 148 pos++;
150 149
151 /* IEEE80211_RADIOTAP_RATE */ 150 /* IEEE80211_RADIOTAP_RATE */
152 *pos = rate->bitrate / 5; 151 if (status->flag & RX_FLAG_HT) {
152 /*
153 * TODO: add following information into radiotap header once
154 * suitable fields are defined for it:
155 * - MCS index (status->rate_idx)
156 * - HT40 (status->flag & RX_FLAG_40MHZ)
157 * - short-GI (status->flag & RX_FLAG_SHORT_GI)
158 */
159 *pos = 0;
160 } else {
161 rthdr->it_present |= (1 << IEEE80211_RADIOTAP_RATE);
162 *pos = rate->bitrate / 5;
163 }
153 pos++; 164 pos++;
154 165
155 /* IEEE80211_RADIOTAP_CHANNEL */ 166 /* IEEE80211_RADIOTAP_CHANNEL */
@@ -1849,9 +1860,15 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
1849 if (!(sdata->dev->flags & IFF_PROMISC)) 1860 if (!(sdata->dev->flags & IFF_PROMISC))
1850 return 0; 1861 return 0;
1851 rx->flags &= ~IEEE80211_RX_RA_MATCH; 1862 rx->flags &= ~IEEE80211_RX_RA_MATCH;
1852 } else if (!rx->sta) 1863 } else if (!rx->sta) {
1864 int rate_idx;
1865 if (rx->status->flag & RX_FLAG_HT)
1866 rate_idx = 0; /* TODO: HT rates */
1867 else
1868 rate_idx = rx->status->rate_idx;
1853 rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2, 1869 rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2,
1854 BIT(rx->status->rate_idx)); 1870 BIT(rate_idx));
1871 }
1855 break; 1872 break;
1856 case NL80211_IFTYPE_MESH_POINT: 1873 case NL80211_IFTYPE_MESH_POINT:
1857 if (!multicast && 1874 if (!multicast &&
@@ -2057,7 +2074,13 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
2057 tid_agg_rx->reorder_buf[index]->cb, 2074 tid_agg_rx->reorder_buf[index]->cb,
2058 sizeof(status)); 2075 sizeof(status));
2059 sband = local->hw.wiphy->bands[status.band]; 2076 sband = local->hw.wiphy->bands[status.band];
2060 rate = &sband->bitrates[status.rate_idx]; 2077 if (status.flag & RX_FLAG_HT) {
2078 /* TODO: HT rates */
2079 rate = sband->bitrates;
2080 } else {
2081 rate = &sband->bitrates
2082 [status.rate_idx];
2083 }
2061 __ieee80211_rx_handle_packet(hw, 2084 __ieee80211_rx_handle_packet(hw,
2062 tid_agg_rx->reorder_buf[index], 2085 tid_agg_rx->reorder_buf[index],
2063 &status, rate); 2086 &status, rate);
@@ -2101,7 +2124,10 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
2101 memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, 2124 memcpy(&status, tid_agg_rx->reorder_buf[index]->cb,
2102 sizeof(status)); 2125 sizeof(status));
2103 sband = local->hw.wiphy->bands[status.band]; 2126 sband = local->hw.wiphy->bands[status.band];
2104 rate = &sband->bitrates[status.rate_idx]; 2127 if (status.flag & RX_FLAG_HT)
2128 rate = sband->bitrates; /* TODO: HT rates */
2129 else
2130 rate = &sband->bitrates[status.rate_idx];
2105 __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], 2131 __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index],
2106 &status, rate); 2132 &status, rate);
2107 tid_agg_rx->stored_mpdu_num--; 2133 tid_agg_rx->stored_mpdu_num--;
@@ -2189,15 +2215,26 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
2189 } 2215 }
2190 2216
2191 sband = local->hw.wiphy->bands[status->band]; 2217 sband = local->hw.wiphy->bands[status->band];
2192 2218 if (!sband) {
2193 if (!sband ||
2194 status->rate_idx < 0 ||
2195 status->rate_idx >= sband->n_bitrates) {
2196 WARN_ON(1); 2219 WARN_ON(1);
2197 return; 2220 return;
2198 } 2221 }
2199 2222
2200 rate = &sband->bitrates[status->rate_idx]; 2223 if (status->flag & RX_FLAG_HT) {
2224 /* rate_idx is MCS index */
2225 if (WARN_ON(status->rate_idx < 0 ||
2226 status->rate_idx >= 76))
2227 return;
2228 /* HT rates are not in the table - use the highest legacy rate
2229 * for now since other parts of mac80211 may not yet be fully
2230 * MCS aware. */
2231 rate = &sband->bitrates[sband->n_bitrates - 1];
2232 } else {
2233 if (WARN_ON(status->rate_idx < 0 ||
2234 status->rate_idx >= sband->n_bitrates))
2235 return;
2236 rate = &sband->bitrates[status->rate_idx];
2237 }
2201 2238
2202 /* 2239 /*
2203 * key references and virtual interfaces are protected using RCU 2240 * key references and virtual interfaces are protected using RCU
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index b098c58d216f..a4af3a124cce 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1473,6 +1473,19 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
1473 goto fail; 1473 goto fail;
1474 } 1474 }
1475 1475
1476 if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) &&
1477 local->dynamic_ps_timeout > 0) {
1478 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
1479 ieee80211_stop_queues_by_reason(&local->hw,
1480 IEEE80211_QUEUE_STOP_REASON_PS);
1481 queue_work(local->hw.workqueue,
1482 &local->dynamic_ps_disable_work);
1483 }
1484
1485 mod_timer(&local->dynamic_ps_timer, jiffies +
1486 msecs_to_jiffies(local->dynamic_ps_timeout));
1487 }
1488
1476 nh_pos = skb_network_header(skb) - skb->data; 1489 nh_pos = skb_network_header(skb) - skb->data;
1477 h_pos = skb_transport_header(skb) - skb->data; 1490 h_pos = skb_transport_header(skb) - skb->data;
1478 1491
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 505d68f344ce..fb89e1d0aa03 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -330,10 +330,20 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
330} 330}
331EXPORT_SYMBOL(ieee80211_ctstoself_duration); 331EXPORT_SYMBOL(ieee80211_ctstoself_duration);
332 332
333void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) 333static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
334 enum queue_stop_reason reason)
334{ 335{
335 struct ieee80211_local *local = hw_to_local(hw); 336 struct ieee80211_local *local = hw_to_local(hw);
336 337
338 /* we don't need to track ampdu queues */
339 if (queue < ieee80211_num_regular_queues(hw)) {
340 __clear_bit(reason, &local->queue_stop_reasons[queue]);
341
342 if (local->queue_stop_reasons[queue] != 0)
343 /* someone still has this queue stopped */
344 return;
345 }
346
337 if (test_bit(queue, local->queues_pending)) { 347 if (test_bit(queue, local->queues_pending)) {
338 set_bit(queue, local->queues_pending_run); 348 set_bit(queue, local->queues_pending_run);
339 tasklet_schedule(&local->tx_pending_tasklet); 349 tasklet_schedule(&local->tx_pending_tasklet);
@@ -341,22 +351,74 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
341 netif_wake_subqueue(local->mdev, queue); 351 netif_wake_subqueue(local->mdev, queue);
342 } 352 }
343} 353}
354
355void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
356 enum queue_stop_reason reason)
357{
358 struct ieee80211_local *local = hw_to_local(hw);
359 unsigned long flags;
360
361 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
362 __ieee80211_wake_queue(hw, queue, reason);
363 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
364}
365
366void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
367{
368 ieee80211_wake_queue_by_reason(hw, queue,
369 IEEE80211_QUEUE_STOP_REASON_DRIVER);
370}
344EXPORT_SYMBOL(ieee80211_wake_queue); 371EXPORT_SYMBOL(ieee80211_wake_queue);
345 372
346void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) 373static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
374 enum queue_stop_reason reason)
347{ 375{
348 struct ieee80211_local *local = hw_to_local(hw); 376 struct ieee80211_local *local = hw_to_local(hw);
349 377
378 /* we don't need to track ampdu queues */
379 if (queue < ieee80211_num_regular_queues(hw))
380 __set_bit(reason, &local->queue_stop_reasons[queue]);
381
350 netif_stop_subqueue(local->mdev, queue); 382 netif_stop_subqueue(local->mdev, queue);
351} 383}
384
385void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
386 enum queue_stop_reason reason)
387{
388 struct ieee80211_local *local = hw_to_local(hw);
389 unsigned long flags;
390
391 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
392 __ieee80211_stop_queue(hw, queue, reason);
393 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
394}
395
396void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
397{
398 ieee80211_stop_queue_by_reason(hw, queue,
399 IEEE80211_QUEUE_STOP_REASON_DRIVER);
400}
352EXPORT_SYMBOL(ieee80211_stop_queue); 401EXPORT_SYMBOL(ieee80211_stop_queue);
353 402
354void ieee80211_stop_queues(struct ieee80211_hw *hw) 403void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
404 enum queue_stop_reason reason)
355{ 405{
406 struct ieee80211_local *local = hw_to_local(hw);
407 unsigned long flags;
356 int i; 408 int i;
357 409
410 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
411
358 for (i = 0; i < ieee80211_num_queues(hw); i++) 412 for (i = 0; i < ieee80211_num_queues(hw); i++)
359 ieee80211_stop_queue(hw, i); 413 __ieee80211_stop_queue(hw, i, reason);
414
415 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
416}
417
418void ieee80211_stop_queues(struct ieee80211_hw *hw)
419{
420 ieee80211_stop_queues_by_reason(hw,
421 IEEE80211_QUEUE_STOP_REASON_DRIVER);
360} 422}
361EXPORT_SYMBOL(ieee80211_stop_queues); 423EXPORT_SYMBOL(ieee80211_stop_queues);
362 424
@@ -367,12 +429,24 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
367} 429}
368EXPORT_SYMBOL(ieee80211_queue_stopped); 430EXPORT_SYMBOL(ieee80211_queue_stopped);
369 431
370void ieee80211_wake_queues(struct ieee80211_hw *hw) 432void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
433 enum queue_stop_reason reason)
371{ 434{
435 struct ieee80211_local *local = hw_to_local(hw);
436 unsigned long flags;
372 int i; 437 int i;
373 438
439 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
440
374 for (i = 0; i < hw->queues + hw->ampdu_queues; i++) 441 for (i = 0; i < hw->queues + hw->ampdu_queues; i++)
375 ieee80211_wake_queue(hw, i); 442 __ieee80211_wake_queue(hw, i, reason);
443
444 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
445}
446
447void ieee80211_wake_queues(struct ieee80211_hw *hw)
448{
449 ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_DRIVER);
376} 450}
377EXPORT_SYMBOL(ieee80211_wake_queues); 451EXPORT_SYMBOL(ieee80211_wake_queues);
378 452
@@ -641,7 +715,7 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz)
641 chan->flags & IEEE80211_CHAN_NO_IBSS) 715 chan->flags & IEEE80211_CHAN_NO_IBSS)
642 return ret; 716 return ret;
643 local->oper_channel = chan; 717 local->oper_channel = chan;
644 local->oper_sec_chan_offset = NL80211_SEC_CHAN_NO_HT; 718 local->oper_channel_type = NL80211_CHAN_NO_HT;
645 719
646 if (local->sw_scanning || local->hw_scanning) 720 if (local->sw_scanning || local->hw_scanning)
647 ret = 0; 721 ret = 0;
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 15428048d01a..7162d5816f39 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -830,25 +830,56 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
830 struct iw_param *wrq, 830 struct iw_param *wrq,
831 char *extra) 831 char *extra)
832{ 832{
833 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
833 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 834 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
834 struct ieee80211_conf *conf = &local->hw.conf; 835 struct ieee80211_conf *conf = &local->hw.conf;
836 int ret = 0, timeout = 0;
837 bool ps;
838
839 if (sdata->vif.type != NL80211_IFTYPE_STATION)
840 return -EINVAL;
835 841
836 if (wrq->disabled) { 842 if (wrq->disabled) {
837 conf->flags &= ~IEEE80211_CONF_PS; 843 ps = false;
838 return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); 844 timeout = 0;
845 goto set;
839 } 846 }
840 847
841 switch (wrq->flags & IW_POWER_MODE) { 848 switch (wrq->flags & IW_POWER_MODE) {
842 case IW_POWER_ON: /* If not specified */ 849 case IW_POWER_ON: /* If not specified */
843 case IW_POWER_MODE: /* If set all mask */ 850 case IW_POWER_MODE: /* If set all mask */
844 case IW_POWER_ALL_R: /* If explicitely state all */ 851 case IW_POWER_ALL_R: /* If explicitely state all */
845 conf->flags |= IEEE80211_CONF_PS; 852 ps = true;
853 break;
854 default: /* Otherwise we ignore */
846 break; 855 break;
847 default: /* Otherwise we don't support it */
848 return -EINVAL;
849 } 856 }
850 857
851 return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); 858 if (wrq->flags & IW_POWER_TIMEOUT)
859 timeout = wrq->value / 1000;
860
861set:
862 if (ps == local->powersave && timeout == local->dynamic_ps_timeout)
863 return ret;
864
865 local->powersave = ps;
866 local->dynamic_ps_timeout = timeout;
867
868 if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
869 if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) &&
870 local->dynamic_ps_timeout > 0)
871 mod_timer(&local->dynamic_ps_timer, jiffies +
872 msecs_to_jiffies(local->dynamic_ps_timeout));
873 else {
874 if (local->powersave)
875 conf->flags |= IEEE80211_CONF_PS;
876 else
877 conf->flags &= ~IEEE80211_CONF_PS;
878 }
879 ret = ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
880 }
881
882 return ret;
852} 883}
853 884
854static int ieee80211_ioctl_giwpower(struct net_device *dev, 885static int ieee80211_ioctl_giwpower(struct net_device *dev,
@@ -857,9 +888,8 @@ static int ieee80211_ioctl_giwpower(struct net_device *dev,
857 char *extra) 888 char *extra)
858{ 889{
859 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 890 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
860 struct ieee80211_conf *conf = &local->hw.conf;
861 891
862 wrqu->power.disabled = !(conf->flags & IEEE80211_CONF_PS); 892 wrqu->power.disabled = !local->powersave;
863 893
864 return 0; 894 return 0;
865} 895}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4335f76be71f..1e728fff474e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -60,7 +60,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
60 .len = BUS_ID_SIZE-1 }, 60 .len = BUS_ID_SIZE-1 },
61 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, 61 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
62 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, 62 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
63 [NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET] = { .type = NLA_U32 }, 63 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
64 64
65 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, 65 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
66 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, 66 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
@@ -362,8 +362,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
362 } 362 }
363 363
364 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { 364 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
365 enum nl80211_sec_chan_offset sec_chan_offset = 365 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
366 NL80211_SEC_CHAN_NO_HT;
367 struct ieee80211_channel *chan; 366 struct ieee80211_channel *chan;
368 struct ieee80211_sta_ht_cap *ht_cap; 367 struct ieee80211_sta_ht_cap *ht_cap;
369 u32 freq, sec_freq; 368 u32 freq, sec_freq;
@@ -375,13 +374,13 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
375 374
376 result = -EINVAL; 375 result = -EINVAL;
377 376
378 if (info->attrs[NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]) { 377 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
379 sec_chan_offset = nla_get_u32(info->attrs[ 378 channel_type = nla_get_u32(info->attrs[
380 NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]); 379 NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
381 if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT && 380 if (channel_type != NL80211_CHAN_NO_HT &&
382 sec_chan_offset != NL80211_SEC_CHAN_DISABLED && 381 channel_type != NL80211_CHAN_HT20 &&
383 sec_chan_offset != NL80211_SEC_CHAN_BELOW && 382 channel_type != NL80211_CHAN_HT40PLUS &&
384 sec_chan_offset != NL80211_SEC_CHAN_ABOVE) 383 channel_type != NL80211_CHAN_HT40MINUS)
385 goto bad_res; 384 goto bad_res;
386 } 385 }
387 386
@@ -392,9 +391,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
392 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) 391 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
393 goto bad_res; 392 goto bad_res;
394 393
395 if (sec_chan_offset == NL80211_SEC_CHAN_BELOW) 394 if (channel_type == NL80211_CHAN_HT40MINUS)
396 sec_freq = freq - 20; 395 sec_freq = freq - 20;
397 else if (sec_chan_offset == NL80211_SEC_CHAN_ABOVE) 396 else if (channel_type == NL80211_CHAN_HT40PLUS)
398 sec_freq = freq + 20; 397 sec_freq = freq + 20;
399 else 398 else
400 sec_freq = 0; 399 sec_freq = 0;
@@ -402,7 +401,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
402 ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; 401 ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
403 402
404 /* no HT capabilities */ 403 /* no HT capabilities */
405 if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT && 404 if (channel_type != NL80211_CHAN_NO_HT &&
406 !ht_cap->ht_supported) 405 !ht_cap->ht_supported)
407 goto bad_res; 406 goto bad_res;
408 407
@@ -422,7 +421,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
422 } 421 }
423 422
424 result = rdev->ops->set_channel(&rdev->wiphy, chan, 423 result = rdev->ops->set_channel(&rdev->wiphy, chan,
425 sec_chan_offset); 424 channel_type);
426 if (result) 425 if (result)
427 goto bad_res; 426 goto bad_res;
428 } 427 }
@@ -1091,12 +1090,46 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
1091 return 0; 1090 return 0;
1092} 1091}
1093 1092
1093static u16 nl80211_calculate_bitrate(struct rate_info *rate)
1094{
1095 int modulation, streams, bitrate;
1096
1097 if (!(rate->flags & RATE_INFO_FLAGS_MCS))
1098 return rate->legacy;
1099
1100 /* the formula below does only work for MCS values smaller than 32 */
1101 if (rate->mcs >= 32)
1102 return 0;
1103
1104 modulation = rate->mcs & 7;
1105 streams = (rate->mcs >> 3) + 1;
1106
1107 bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
1108 13500000 : 6500000;
1109
1110 if (modulation < 4)
1111 bitrate *= (modulation + 1);
1112 else if (modulation == 4)
1113 bitrate *= (modulation + 2);
1114 else
1115 bitrate *= (modulation + 3);
1116
1117 bitrate *= streams;
1118
1119 if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
1120 bitrate = (bitrate / 9) * 10;
1121
1122 /* do NOT round down here */
1123 return (bitrate + 50000) / 100000;
1124}
1125
1094static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, 1126static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
1095 int flags, struct net_device *dev, 1127 int flags, struct net_device *dev,
1096 u8 *mac_addr, struct station_info *sinfo) 1128 u8 *mac_addr, struct station_info *sinfo)
1097{ 1129{
1098 void *hdr; 1130 void *hdr;
1099 struct nlattr *sinfoattr; 1131 struct nlattr *sinfoattr, *txrate;
1132 u16 bitrate;
1100 1133
1101 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); 1134 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
1102 if (!hdr) 1135 if (!hdr)
@@ -1126,7 +1159,29 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
1126 if (sinfo->filled & STATION_INFO_PLINK_STATE) 1159 if (sinfo->filled & STATION_INFO_PLINK_STATE)
1127 NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE, 1160 NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
1128 sinfo->plink_state); 1161 sinfo->plink_state);
1162 if (sinfo->filled & STATION_INFO_SIGNAL)
1163 NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
1164 sinfo->signal);
1165 if (sinfo->filled & STATION_INFO_TX_BITRATE) {
1166 txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
1167 if (!txrate)
1168 goto nla_put_failure;
1169
1170 /* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
1171 bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
1172 if (bitrate > 0)
1173 NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
1129 1174
1175 if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
1176 NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
1177 sinfo->txrate.mcs);
1178 if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
1179 NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
1180 if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
1181 NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
1182
1183 nla_nest_end(msg, txrate);
1184 }
1130 nla_nest_end(msg, sinfoattr); 1185 nla_nest_end(msg, sinfoattr);
1131 1186
1132 return genlmsg_end(msg, hdr); 1187 return genlmsg_end(msg, hdr);