diff options
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 291 |
1 files changed, 147 insertions, 144 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 36016363d225..f79f6b9938a6 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -35,8 +35,6 @@ | |||
35 | #include "debugfs.h" | 35 | #include "debugfs.h" |
36 | #include "debugfs_netdev.h" | 36 | #include "debugfs_netdev.h" |
37 | 37 | ||
38 | #define SUPP_MCS_SET_LEN 16 | ||
39 | |||
40 | /* | 38 | /* |
41 | * For seeing transmitted packets on monitor interfaces | 39 | * For seeing transmitted packets on monitor interfaces |
42 | * we have a radiotap header too. | 40 | * we have a radiotap header too. |
@@ -112,7 +110,13 @@ static int ieee80211_master_open(struct net_device *dev) | |||
112 | break; | 110 | break; |
113 | } | 111 | } |
114 | } | 112 | } |
115 | return res; | 113 | |
114 | if (res) | ||
115 | return res; | ||
116 | |||
117 | netif_start_queue(local->mdev); | ||
118 | |||
119 | return 0; | ||
116 | } | 120 | } |
117 | 121 | ||
118 | static int ieee80211_master_stop(struct net_device *dev) | 122 | static int ieee80211_master_stop(struct net_device *dev) |
@@ -585,8 +589,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
585 | sta = sta_info_get(local, ra); | 589 | sta = sta_info_get(local, ra); |
586 | if (!sta) { | 590 | if (!sta) { |
587 | printk(KERN_DEBUG "Could not find the station\n"); | 591 | printk(KERN_DEBUG "Could not find the station\n"); |
588 | rcu_read_unlock(); | 592 | ret = -ENOENT; |
589 | return -ENOENT; | 593 | goto exit; |
590 | } | 594 | } |
591 | 595 | ||
592 | spin_lock_bh(&sta->lock); | 596 | spin_lock_bh(&sta->lock); |
@@ -594,7 +598,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
594 | /* we have tried too many times, receiver does not want A-MPDU */ | 598 | /* we have tried too many times, receiver does not want A-MPDU */ |
595 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { | 599 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { |
596 | ret = -EBUSY; | 600 | ret = -EBUSY; |
597 | goto start_ba_exit; | 601 | goto err_unlock_sta; |
598 | } | 602 | } |
599 | 603 | ||
600 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 604 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
@@ -605,7 +609,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
605 | "idle on tid %u\n", tid); | 609 | "idle on tid %u\n", tid); |
606 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 610 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
607 | ret = -EAGAIN; | 611 | ret = -EAGAIN; |
608 | goto start_ba_exit; | 612 | goto err_unlock_sta; |
609 | } | 613 | } |
610 | 614 | ||
611 | /* prepare A-MPDU MLME for Tx aggregation */ | 615 | /* prepare A-MPDU MLME for Tx aggregation */ |
@@ -616,7 +620,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
616 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", | 620 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", |
617 | tid); | 621 | tid); |
618 | ret = -ENOMEM; | 622 | ret = -ENOMEM; |
619 | goto start_ba_exit; | 623 | goto err_unlock_sta; |
620 | } | 624 | } |
621 | /* Tx timer */ | 625 | /* Tx timer */ |
622 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = | 626 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = |
@@ -639,7 +643,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
639 | printk(KERN_DEBUG "BA request denied - queue unavailable for" | 643 | printk(KERN_DEBUG "BA request denied - queue unavailable for" |
640 | " tid %d\n", tid); | 644 | " tid %d\n", tid); |
641 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 645 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
642 | goto start_ba_err; | 646 | goto err_unlock_queue; |
643 | } | 647 | } |
644 | sdata = sta->sdata; | 648 | sdata = sta->sdata; |
645 | 649 | ||
@@ -661,12 +665,13 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
661 | " tid %d\n", tid); | 665 | " tid %d\n", tid); |
662 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 666 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
663 | *state = HT_AGG_STATE_IDLE; | 667 | *state = HT_AGG_STATE_IDLE; |
664 | goto start_ba_err; | 668 | goto err_unlock_queue; |
665 | } | 669 | } |
666 | 670 | ||
667 | /* Will put all the packets in the new SW queue */ | 671 | /* Will put all the packets in the new SW queue */ |
668 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); | 672 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); |
669 | spin_unlock_bh(&local->mdev->queue_lock); | 673 | spin_unlock_bh(&local->mdev->queue_lock); |
674 | spin_unlock_bh(&sta->lock); | ||
670 | 675 | ||
671 | /* send an addBA request */ | 676 | /* send an addBA request */ |
672 | sta->ampdu_mlme.dialog_token_allocator++; | 677 | sta->ampdu_mlme.dialog_token_allocator++; |
@@ -674,25 +679,26 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
674 | sta->ampdu_mlme.dialog_token_allocator; | 679 | sta->ampdu_mlme.dialog_token_allocator; |
675 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; | 680 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; |
676 | 681 | ||
682 | |||
677 | ieee80211_send_addba_request(sta->sdata->dev, ra, tid, | 683 | ieee80211_send_addba_request(sta->sdata->dev, ra, tid, |
678 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, | 684 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, |
679 | sta->ampdu_mlme.tid_tx[tid]->ssn, | 685 | sta->ampdu_mlme.tid_tx[tid]->ssn, |
680 | 0x40, 5000); | 686 | 0x40, 5000); |
681 | |||
682 | /* activate the timer for the recipient's addBA response */ | 687 | /* activate the timer for the recipient's addBA response */ |
683 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = | 688 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = |
684 | jiffies + ADDBA_RESP_INTERVAL; | 689 | jiffies + ADDBA_RESP_INTERVAL; |
685 | add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | 690 | add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); |
686 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | 691 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); |
687 | goto start_ba_exit; | 692 | goto exit; |
688 | 693 | ||
689 | start_ba_err: | 694 | err_unlock_queue: |
690 | kfree(sta->ampdu_mlme.tid_tx[tid]); | 695 | kfree(sta->ampdu_mlme.tid_tx[tid]); |
691 | sta->ampdu_mlme.tid_tx[tid] = NULL; | 696 | sta->ampdu_mlme.tid_tx[tid] = NULL; |
692 | spin_unlock_bh(&local->mdev->queue_lock); | 697 | spin_unlock_bh(&local->mdev->queue_lock); |
693 | ret = -EBUSY; | 698 | ret = -EBUSY; |
694 | start_ba_exit: | 699 | err_unlock_sta: |
695 | spin_unlock_bh(&sta->lock); | 700 | spin_unlock_bh(&sta->lock); |
701 | exit: | ||
696 | rcu_read_unlock(); | 702 | rcu_read_unlock(); |
697 | return ret; | 703 | return ret; |
698 | } | 704 | } |
@@ -831,10 +837,11 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
831 | } | 837 | } |
832 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 838 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
833 | 839 | ||
834 | spin_lock_bh(&sta->lock); | 840 | /* NOTE: no need to use sta->lock in this state check, as |
841 | * ieee80211_stop_tx_ba_session will let only | ||
842 | * one stop call to pass through per sta/tid */ | ||
835 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { | 843 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { |
836 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); | 844 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); |
837 | spin_unlock_bh(&sta->lock); | ||
838 | rcu_read_unlock(); | 845 | rcu_read_unlock(); |
839 | return; | 846 | return; |
840 | } | 847 | } |
@@ -857,6 +864,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
857 | * ieee80211_wake_queue is not used here as this queue is not | 864 | * ieee80211_wake_queue is not used here as this queue is not |
858 | * necessarily stopped */ | 865 | * necessarily stopped */ |
859 | netif_schedule(local->mdev); | 866 | netif_schedule(local->mdev); |
867 | spin_lock_bh(&sta->lock); | ||
860 | *state = HT_AGG_STATE_IDLE; | 868 | *state = HT_AGG_STATE_IDLE; |
861 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 869 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
862 | kfree(sta->ampdu_mlme.tid_tx[tid]); | 870 | kfree(sta->ampdu_mlme.tid_tx[tid]); |
@@ -967,8 +975,7 @@ void ieee80211_if_setup(struct net_device *dev) | |||
967 | /* everything else */ | 975 | /* everything else */ |
968 | 976 | ||
969 | static int __ieee80211_if_config(struct net_device *dev, | 977 | static int __ieee80211_if_config(struct net_device *dev, |
970 | struct sk_buff *beacon, | 978 | struct sk_buff *beacon) |
971 | struct ieee80211_tx_control *control) | ||
972 | { | 979 | { |
973 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 980 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
974 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 981 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
@@ -986,13 +993,11 @@ static int __ieee80211_if_config(struct net_device *dev, | |||
986 | conf.ssid_len = sdata->u.sta.ssid_len; | 993 | conf.ssid_len = sdata->u.sta.ssid_len; |
987 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 994 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
988 | conf.beacon = beacon; | 995 | conf.beacon = beacon; |
989 | conf.beacon_control = control; | ||
990 | ieee80211_start_mesh(dev); | 996 | ieee80211_start_mesh(dev); |
991 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { | 997 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { |
992 | conf.ssid = sdata->u.ap.ssid; | 998 | conf.ssid = sdata->u.ap.ssid; |
993 | conf.ssid_len = sdata->u.ap.ssid_len; | 999 | conf.ssid_len = sdata->u.ap.ssid_len; |
994 | conf.beacon = beacon; | 1000 | conf.beacon = beacon; |
995 | conf.beacon_control = control; | ||
996 | } | 1001 | } |
997 | return local->ops->config_interface(local_to_hw(local), | 1002 | return local->ops->config_interface(local_to_hw(local), |
998 | &sdata->vif, &conf); | 1003 | &sdata->vif, &conf); |
@@ -1005,23 +1010,21 @@ int ieee80211_if_config(struct net_device *dev) | |||
1005 | if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT && | 1010 | if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT && |
1006 | (local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) | 1011 | (local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) |
1007 | return ieee80211_if_config_beacon(dev); | 1012 | return ieee80211_if_config_beacon(dev); |
1008 | return __ieee80211_if_config(dev, NULL, NULL); | 1013 | return __ieee80211_if_config(dev, NULL); |
1009 | } | 1014 | } |
1010 | 1015 | ||
1011 | int ieee80211_if_config_beacon(struct net_device *dev) | 1016 | int ieee80211_if_config_beacon(struct net_device *dev) |
1012 | { | 1017 | { |
1013 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1018 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1014 | struct ieee80211_tx_control control; | ||
1015 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1019 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1016 | struct sk_buff *skb; | 1020 | struct sk_buff *skb; |
1017 | 1021 | ||
1018 | if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) | 1022 | if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) |
1019 | return 0; | 1023 | return 0; |
1020 | skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif, | 1024 | skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif); |
1021 | &control); | ||
1022 | if (!skb) | 1025 | if (!skb) |
1023 | return -ENOMEM; | 1026 | return -ENOMEM; |
1024 | return __ieee80211_if_config(dev, skb, &control); | 1027 | return __ieee80211_if_config(dev, skb); |
1025 | } | 1028 | } |
1026 | 1029 | ||
1027 | int ieee80211_hw_config(struct ieee80211_local *local) | 1030 | int ieee80211_hw_config(struct ieee80211_local *local) |
@@ -1068,56 +1071,84 @@ u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, | |||
1068 | struct ieee80211_supported_band *sband; | 1071 | struct ieee80211_supported_band *sband; |
1069 | struct ieee80211_ht_info ht_conf; | 1072 | struct ieee80211_ht_info ht_conf; |
1070 | struct ieee80211_ht_bss_info ht_bss_conf; | 1073 | struct ieee80211_ht_bss_info ht_bss_conf; |
1071 | int i; | ||
1072 | u32 changed = 0; | 1074 | u32 changed = 0; |
1075 | int i; | ||
1076 | u8 max_tx_streams = IEEE80211_HT_CAP_MAX_STREAMS; | ||
1077 | u8 tx_mcs_set_cap; | ||
1073 | 1078 | ||
1074 | sband = local->hw.wiphy->bands[conf->channel->band]; | 1079 | sband = local->hw.wiphy->bands[conf->channel->band]; |
1075 | 1080 | ||
1081 | memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info)); | ||
1082 | memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info)); | ||
1083 | |||
1076 | /* HT is not supported */ | 1084 | /* HT is not supported */ |
1077 | if (!sband->ht_info.ht_supported) { | 1085 | if (!sband->ht_info.ht_supported) { |
1078 | conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; | 1086 | conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; |
1079 | return 0; | 1087 | goto out; |
1080 | } | 1088 | } |
1081 | 1089 | ||
1082 | memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info)); | 1090 | /* disable HT */ |
1083 | memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info)); | 1091 | if (!enable_ht) { |
1084 | 1092 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) | |
1085 | if (enable_ht) { | ||
1086 | if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) | ||
1087 | changed |= BSS_CHANGED_HT; | 1093 | changed |= BSS_CHANGED_HT; |
1094 | conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; | ||
1095 | conf->ht_conf.ht_supported = 0; | ||
1096 | goto out; | ||
1097 | } | ||
1088 | 1098 | ||
1089 | conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; | ||
1090 | ht_conf.ht_supported = 1; | ||
1091 | 1099 | ||
1092 | ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; | 1100 | if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) |
1093 | ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); | 1101 | changed |= BSS_CHANGED_HT; |
1094 | ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; | ||
1095 | 1102 | ||
1096 | for (i = 0; i < SUPP_MCS_SET_LEN; i++) | 1103 | conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; |
1097 | ht_conf.supp_mcs_set[i] = | 1104 | ht_conf.ht_supported = 1; |
1098 | sband->ht_info.supp_mcs_set[i] & | ||
1099 | req_ht_cap->supp_mcs_set[i]; | ||
1100 | 1105 | ||
1101 | ht_bss_conf.primary_channel = req_bss_cap->primary_channel; | 1106 | ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; |
1102 | ht_bss_conf.bss_cap = req_bss_cap->bss_cap; | 1107 | ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); |
1103 | ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; | 1108 | ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; |
1109 | ht_bss_conf.primary_channel = req_bss_cap->primary_channel; | ||
1110 | ht_bss_conf.bss_cap = req_bss_cap->bss_cap; | ||
1111 | ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; | ||
1104 | 1112 | ||
1105 | ht_conf.ampdu_factor = req_ht_cap->ampdu_factor; | 1113 | ht_conf.ampdu_factor = req_ht_cap->ampdu_factor; |
1106 | ht_conf.ampdu_density = req_ht_cap->ampdu_density; | 1114 | ht_conf.ampdu_density = req_ht_cap->ampdu_density; |
1107 | 1115 | ||
1108 | /* if bss configuration changed store the new one */ | 1116 | /* Bits 96-100 */ |
1109 | if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) || | 1117 | tx_mcs_set_cap = sband->ht_info.supp_mcs_set[12]; |
1110 | memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) { | 1118 | |
1111 | changed |= BSS_CHANGED_HT; | 1119 | /* configure suppoerted Tx MCS according to requested MCS |
1112 | memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf)); | 1120 | * (based in most cases on Rx capabilities of peer) and self |
1113 | memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf)); | 1121 | * Tx MCS capabilities (as defined by low level driver HW |
1114 | } | 1122 | * Tx capabilities) */ |
1115 | } else { | 1123 | if (!(tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_DEFINED)) |
1116 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) | 1124 | goto check_changed; |
1117 | changed |= BSS_CHANGED_HT; | 1125 | |
1118 | conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; | 1126 | /* Counting from 0 therfore + 1 */ |
1119 | } | 1127 | if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_RX_DIFF) |
1128 | max_tx_streams = ((tx_mcs_set_cap & | ||
1129 | IEEE80211_HT_CAP_MCS_TX_STREAMS) >> 2) + 1; | ||
1130 | |||
1131 | for (i = 0; i < max_tx_streams; i++) | ||
1132 | ht_conf.supp_mcs_set[i] = | ||
1133 | sband->ht_info.supp_mcs_set[i] & | ||
1134 | req_ht_cap->supp_mcs_set[i]; | ||
1135 | |||
1136 | if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_UEQM) | ||
1137 | for (i = IEEE80211_SUPP_MCS_SET_UEQM; | ||
1138 | i < IEEE80211_SUPP_MCS_SET_LEN; i++) | ||
1139 | ht_conf.supp_mcs_set[i] = | ||
1140 | sband->ht_info.supp_mcs_set[i] & | ||
1141 | req_ht_cap->supp_mcs_set[i]; | ||
1120 | 1142 | ||
1143 | check_changed: | ||
1144 | /* if bss configuration changed store the new one */ | ||
1145 | if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) || | ||
1146 | memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) { | ||
1147 | changed |= BSS_CHANGED_HT; | ||
1148 | memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf)); | ||
1149 | memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf)); | ||
1150 | } | ||
1151 | out: | ||
1121 | return changed; | 1152 | return changed; |
1122 | } | 1153 | } |
1123 | 1154 | ||
@@ -1148,38 +1179,20 @@ void ieee80211_reset_erp_info(struct net_device *dev) | |||
1148 | } | 1179 | } |
1149 | 1180 | ||
1150 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | 1181 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, |
1151 | struct sk_buff *skb, | 1182 | struct sk_buff *skb) |
1152 | struct ieee80211_tx_status *status) | ||
1153 | { | 1183 | { |
1154 | struct ieee80211_local *local = hw_to_local(hw); | 1184 | struct ieee80211_local *local = hw_to_local(hw); |
1155 | struct ieee80211_tx_status *saved; | 1185 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1156 | int tmp; | 1186 | int tmp; |
1157 | 1187 | ||
1158 | skb->dev = local->mdev; | 1188 | skb->dev = local->mdev; |
1159 | saved = kmalloc(sizeof(struct ieee80211_tx_status), GFP_ATOMIC); | ||
1160 | if (unlikely(!saved)) { | ||
1161 | if (net_ratelimit()) | ||
1162 | printk(KERN_WARNING "%s: Not enough memory, " | ||
1163 | "dropping tx status", skb->dev->name); | ||
1164 | /* should be dev_kfree_skb_irq, but due to this function being | ||
1165 | * named _irqsafe instead of just _irq we can't be sure that | ||
1166 | * people won't call it from non-irq contexts */ | ||
1167 | dev_kfree_skb_any(skb); | ||
1168 | return; | ||
1169 | } | ||
1170 | memcpy(saved, status, sizeof(struct ieee80211_tx_status)); | ||
1171 | /* copy pointer to saved status into skb->cb for use by tasklet */ | ||
1172 | memcpy(skb->cb, &saved, sizeof(saved)); | ||
1173 | |||
1174 | skb->pkt_type = IEEE80211_TX_STATUS_MSG; | 1189 | skb->pkt_type = IEEE80211_TX_STATUS_MSG; |
1175 | skb_queue_tail(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS ? | 1190 | skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ? |
1176 | &local->skb_queue : &local->skb_queue_unreliable, skb); | 1191 | &local->skb_queue : &local->skb_queue_unreliable, skb); |
1177 | tmp = skb_queue_len(&local->skb_queue) + | 1192 | tmp = skb_queue_len(&local->skb_queue) + |
1178 | skb_queue_len(&local->skb_queue_unreliable); | 1193 | skb_queue_len(&local->skb_queue_unreliable); |
1179 | while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT && | 1194 | while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT && |
1180 | (skb = skb_dequeue(&local->skb_queue_unreliable))) { | 1195 | (skb = skb_dequeue(&local->skb_queue_unreliable))) { |
1181 | memcpy(&saved, skb->cb, sizeof(saved)); | ||
1182 | kfree(saved); | ||
1183 | dev_kfree_skb_irq(skb); | 1196 | dev_kfree_skb_irq(skb); |
1184 | tmp--; | 1197 | tmp--; |
1185 | I802_DEBUG_INC(local->tx_status_drop); | 1198 | I802_DEBUG_INC(local->tx_status_drop); |
@@ -1193,7 +1206,6 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
1193 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 1206 | struct ieee80211_local *local = (struct ieee80211_local *) data; |
1194 | struct sk_buff *skb; | 1207 | struct sk_buff *skb; |
1195 | struct ieee80211_rx_status rx_status; | 1208 | struct ieee80211_rx_status rx_status; |
1196 | struct ieee80211_tx_status *tx_status; | ||
1197 | struct ieee80211_ra_tid *ra_tid; | 1209 | struct ieee80211_ra_tid *ra_tid; |
1198 | 1210 | ||
1199 | while ((skb = skb_dequeue(&local->skb_queue)) || | 1211 | while ((skb = skb_dequeue(&local->skb_queue)) || |
@@ -1208,12 +1220,8 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
1208 | __ieee80211_rx(local_to_hw(local), skb, &rx_status); | 1220 | __ieee80211_rx(local_to_hw(local), skb, &rx_status); |
1209 | break; | 1221 | break; |
1210 | case IEEE80211_TX_STATUS_MSG: | 1222 | case IEEE80211_TX_STATUS_MSG: |
1211 | /* get pointer to saved status out of skb->cb */ | ||
1212 | memcpy(&tx_status, skb->cb, sizeof(tx_status)); | ||
1213 | skb->pkt_type = 0; | 1223 | skb->pkt_type = 0; |
1214 | ieee80211_tx_status(local_to_hw(local), | 1224 | ieee80211_tx_status(local_to_hw(local), skb); |
1215 | skb, tx_status); | ||
1216 | kfree(tx_status); | ||
1217 | break; | 1225 | break; |
1218 | case IEEE80211_DELBA_MSG: | 1226 | case IEEE80211_DELBA_MSG: |
1219 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | 1227 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; |
@@ -1242,24 +1250,15 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
1242 | * Also, tx_packet_data in cb is restored from tx_control. */ | 1250 | * Also, tx_packet_data in cb is restored from tx_control. */ |
1243 | static void ieee80211_remove_tx_extra(struct ieee80211_local *local, | 1251 | static void ieee80211_remove_tx_extra(struct ieee80211_local *local, |
1244 | struct ieee80211_key *key, | 1252 | struct ieee80211_key *key, |
1245 | struct sk_buff *skb, | 1253 | struct sk_buff *skb) |
1246 | struct ieee80211_tx_control *control) | ||
1247 | { | 1254 | { |
1248 | int hdrlen, iv_len, mic_len; | 1255 | int hdrlen, iv_len, mic_len; |
1249 | struct ieee80211_tx_packet_data *pkt_data; | 1256 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1250 | 1257 | ||
1251 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | 1258 | info->flags &= IEEE80211_TX_CTL_REQ_TX_STATUS | |
1252 | pkt_data->ifindex = vif_to_sdata(control->vif)->dev->ifindex; | 1259 | IEEE80211_TX_CTL_DO_NOT_ENCRYPT | |
1253 | pkt_data->flags = 0; | 1260 | IEEE80211_TX_CTL_REQUEUE | |
1254 | if (control->flags & IEEE80211_TXCTL_REQ_TX_STATUS) | 1261 | IEEE80211_TX_CTL_EAPOL_FRAME; |
1255 | pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS; | ||
1256 | if (control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT) | ||
1257 | pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT; | ||
1258 | if (control->flags & IEEE80211_TXCTL_REQUEUE) | ||
1259 | pkt_data->flags |= IEEE80211_TXPD_REQUEUE; | ||
1260 | if (control->flags & IEEE80211_TXCTL_EAPOL_FRAME) | ||
1261 | pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME; | ||
1262 | pkt_data->queue = control->queue; | ||
1263 | 1262 | ||
1264 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1263 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
1265 | 1264 | ||
@@ -1306,9 +1305,10 @@ no_key: | |||
1306 | 1305 | ||
1307 | static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | 1306 | static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, |
1308 | struct sta_info *sta, | 1307 | struct sta_info *sta, |
1309 | struct sk_buff *skb, | 1308 | struct sk_buff *skb) |
1310 | struct ieee80211_tx_status *status) | ||
1311 | { | 1309 | { |
1310 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1311 | |||
1312 | sta->tx_filtered_count++; | 1312 | sta->tx_filtered_count++; |
1313 | 1313 | ||
1314 | /* | 1314 | /* |
@@ -1350,18 +1350,16 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
1350 | */ | 1350 | */ |
1351 | if (test_sta_flags(sta, WLAN_STA_PS) && | 1351 | if (test_sta_flags(sta, WLAN_STA_PS) && |
1352 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { | 1352 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { |
1353 | ieee80211_remove_tx_extra(local, sta->key, skb, | 1353 | ieee80211_remove_tx_extra(local, sta->key, skb); |
1354 | &status->control); | ||
1355 | skb_queue_tail(&sta->tx_filtered, skb); | 1354 | skb_queue_tail(&sta->tx_filtered, skb); |
1356 | return; | 1355 | return; |
1357 | } | 1356 | } |
1358 | 1357 | ||
1359 | if (!test_sta_flags(sta, WLAN_STA_PS) && | 1358 | if (!test_sta_flags(sta, WLAN_STA_PS) && |
1360 | !(status->control.flags & IEEE80211_TXCTL_REQUEUE)) { | 1359 | !(info->flags & IEEE80211_TX_CTL_REQUEUE)) { |
1361 | /* Software retry the packet once */ | 1360 | /* Software retry the packet once */ |
1362 | status->control.flags |= IEEE80211_TXCTL_REQUEUE; | 1361 | info->flags |= IEEE80211_TX_CTL_REQUEUE; |
1363 | ieee80211_remove_tx_extra(local, sta->key, skb, | 1362 | ieee80211_remove_tx_extra(local, sta->key, skb); |
1364 | &status->control); | ||
1365 | dev_queue_xmit(skb); | 1363 | dev_queue_xmit(skb); |
1366 | return; | 1364 | return; |
1367 | } | 1365 | } |
@@ -1375,28 +1373,20 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
1375 | dev_kfree_skb(skb); | 1373 | dev_kfree_skb(skb); |
1376 | } | 1374 | } |
1377 | 1375 | ||
1378 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | 1376 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) |
1379 | struct ieee80211_tx_status *status) | ||
1380 | { | 1377 | { |
1381 | struct sk_buff *skb2; | 1378 | struct sk_buff *skb2; |
1382 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1379 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1383 | struct ieee80211_local *local = hw_to_local(hw); | 1380 | struct ieee80211_local *local = hw_to_local(hw); |
1381 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1384 | u16 frag, type; | 1382 | u16 frag, type; |
1385 | struct ieee80211_tx_status_rtap_hdr *rthdr; | 1383 | struct ieee80211_tx_status_rtap_hdr *rthdr; |
1386 | struct ieee80211_sub_if_data *sdata; | 1384 | struct ieee80211_sub_if_data *sdata; |
1387 | struct net_device *prev_dev = NULL; | 1385 | struct net_device *prev_dev = NULL; |
1388 | 1386 | ||
1389 | if (!status) { | ||
1390 | printk(KERN_ERR | ||
1391 | "%s: ieee80211_tx_status called with NULL status\n", | ||
1392 | wiphy_name(local->hw.wiphy)); | ||
1393 | dev_kfree_skb(skb); | ||
1394 | return; | ||
1395 | } | ||
1396 | |||
1397 | rcu_read_lock(); | 1387 | rcu_read_lock(); |
1398 | 1388 | ||
1399 | if (status->excessive_retries) { | 1389 | if (info->status.excessive_retries) { |
1400 | struct sta_info *sta; | 1390 | struct sta_info *sta; |
1401 | sta = sta_info_get(local, hdr->addr1); | 1391 | sta = sta_info_get(local, hdr->addr1); |
1402 | if (sta) { | 1392 | if (sta) { |
@@ -1405,27 +1395,23 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1405 | * The STA is in power save mode, so assume | 1395 | * The STA is in power save mode, so assume |
1406 | * that this TX packet failed because of that. | 1396 | * that this TX packet failed because of that. |
1407 | */ | 1397 | */ |
1408 | status->excessive_retries = 0; | 1398 | ieee80211_handle_filtered_frame(local, sta, skb); |
1409 | status->flags |= IEEE80211_TX_STATUS_TX_FILTERED; | ||
1410 | ieee80211_handle_filtered_frame(local, sta, | ||
1411 | skb, status); | ||
1412 | rcu_read_unlock(); | 1399 | rcu_read_unlock(); |
1413 | return; | 1400 | return; |
1414 | } | 1401 | } |
1415 | } | 1402 | } |
1416 | } | 1403 | } |
1417 | 1404 | ||
1418 | if (status->flags & IEEE80211_TX_STATUS_TX_FILTERED) { | 1405 | if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { |
1419 | struct sta_info *sta; | 1406 | struct sta_info *sta; |
1420 | sta = sta_info_get(local, hdr->addr1); | 1407 | sta = sta_info_get(local, hdr->addr1); |
1421 | if (sta) { | 1408 | if (sta) { |
1422 | ieee80211_handle_filtered_frame(local, sta, skb, | 1409 | ieee80211_handle_filtered_frame(local, sta, skb); |
1423 | status); | ||
1424 | rcu_read_unlock(); | 1410 | rcu_read_unlock(); |
1425 | return; | 1411 | return; |
1426 | } | 1412 | } |
1427 | } else | 1413 | } else |
1428 | rate_control_tx_status(local->mdev, skb, status); | 1414 | rate_control_tx_status(local->mdev, skb); |
1429 | 1415 | ||
1430 | rcu_read_unlock(); | 1416 | rcu_read_unlock(); |
1431 | 1417 | ||
@@ -1439,14 +1425,14 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1439 | frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; | 1425 | frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; |
1440 | type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE; | 1426 | type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE; |
1441 | 1427 | ||
1442 | if (status->flags & IEEE80211_TX_STATUS_ACK) { | 1428 | if (info->flags & IEEE80211_TX_STAT_ACK) { |
1443 | if (frag == 0) { | 1429 | if (frag == 0) { |
1444 | local->dot11TransmittedFrameCount++; | 1430 | local->dot11TransmittedFrameCount++; |
1445 | if (is_multicast_ether_addr(hdr->addr1)) | 1431 | if (is_multicast_ether_addr(hdr->addr1)) |
1446 | local->dot11MulticastTransmittedFrameCount++; | 1432 | local->dot11MulticastTransmittedFrameCount++; |
1447 | if (status->retry_count > 0) | 1433 | if (info->status.retry_count > 0) |
1448 | local->dot11RetryCount++; | 1434 | local->dot11RetryCount++; |
1449 | if (status->retry_count > 1) | 1435 | if (info->status.retry_count > 1) |
1450 | local->dot11MultipleRetryCount++; | 1436 | local->dot11MultipleRetryCount++; |
1451 | } | 1437 | } |
1452 | 1438 | ||
@@ -1492,17 +1478,17 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1492 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | | 1478 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | |
1493 | (1 << IEEE80211_RADIOTAP_DATA_RETRIES)); | 1479 | (1 << IEEE80211_RADIOTAP_DATA_RETRIES)); |
1494 | 1480 | ||
1495 | if (!(status->flags & IEEE80211_TX_STATUS_ACK) && | 1481 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && |
1496 | !is_multicast_ether_addr(hdr->addr1)) | 1482 | !is_multicast_ether_addr(hdr->addr1)) |
1497 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); | 1483 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); |
1498 | 1484 | ||
1499 | if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) && | 1485 | if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) && |
1500 | (status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) | 1486 | (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) |
1501 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); | 1487 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); |
1502 | else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) | 1488 | else if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) |
1503 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); | 1489 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); |
1504 | 1490 | ||
1505 | rthdr->data_retries = status->retry_count; | 1491 | rthdr->data_retries = info->status.retry_count; |
1506 | 1492 | ||
1507 | /* XXX: is this sufficient for BPF? */ | 1493 | /* XXX: is this sufficient for BPF? */ |
1508 | skb_set_mac_header(skb, 0); | 1494 | skb_set_mac_header(skb, 0); |
@@ -1652,12 +1638,32 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1652 | if (result < 0) | 1638 | if (result < 0) |
1653 | return result; | 1639 | return result; |
1654 | 1640 | ||
1641 | /* | ||
1642 | * We use the number of queues for feature tests (QoS, HT) internally | ||
1643 | * so restrict them appropriately. | ||
1644 | */ | ||
1645 | #ifdef CONFIG_MAC80211_QOS | ||
1646 | if (hw->queues > IEEE80211_MAX_QUEUES) | ||
1647 | hw->queues = IEEE80211_MAX_QUEUES; | ||
1648 | if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES) | ||
1649 | hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES; | ||
1650 | if (hw->queues < 4) | ||
1651 | hw->ampdu_queues = 0; | ||
1652 | #else | ||
1653 | hw->queues = 1; | ||
1654 | hw->ampdu_queues = 0; | ||
1655 | #endif | ||
1656 | |||
1655 | /* for now, mdev needs sub_if_data :/ */ | 1657 | /* for now, mdev needs sub_if_data :/ */ |
1656 | mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), | 1658 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_sub_if_data), |
1657 | "wmaster%d", ether_setup); | 1659 | "wmaster%d", ether_setup, |
1660 | ieee80211_num_queues(hw)); | ||
1658 | if (!mdev) | 1661 | if (!mdev) |
1659 | goto fail_mdev_alloc; | 1662 | goto fail_mdev_alloc; |
1660 | 1663 | ||
1664 | if (ieee80211_num_queues(hw) > 1) | ||
1665 | mdev->features |= NETIF_F_MULTI_QUEUE; | ||
1666 | |||
1661 | sdata = IEEE80211_DEV_TO_SUB_IF(mdev); | 1667 | sdata = IEEE80211_DEV_TO_SUB_IF(mdev); |
1662 | mdev->ieee80211_ptr = &sdata->wdev; | 1668 | mdev->ieee80211_ptr = &sdata->wdev; |
1663 | sdata->wdev.wiphy = local->hw.wiphy; | 1669 | sdata->wdev.wiphy = local->hw.wiphy; |
@@ -1746,11 +1752,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1746 | goto fail_wep; | 1752 | goto fail_wep; |
1747 | } | 1753 | } |
1748 | 1754 | ||
1749 | if (hw->queues > IEEE80211_MAX_QUEUES) | ||
1750 | hw->queues = IEEE80211_MAX_QUEUES; | ||
1751 | if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES) | ||
1752 | hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES; | ||
1753 | |||
1754 | ieee80211_install_qdisc(local->mdev); | 1755 | ieee80211_install_qdisc(local->mdev); |
1755 | 1756 | ||
1756 | /* add one default STA interface */ | 1757 | /* add one default STA interface */ |
@@ -1863,7 +1864,9 @@ static int __init ieee80211_init(void) | |||
1863 | struct sk_buff *skb; | 1864 | struct sk_buff *skb; |
1864 | int ret; | 1865 | int ret; |
1865 | 1866 | ||
1866 | BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb)); | 1867 | BUILD_BUG_ON(sizeof(struct ieee80211_tx_info) > sizeof(skb->cb)); |
1868 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) + | ||
1869 | IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb)); | ||
1867 | 1870 | ||
1868 | ret = rc80211_pid_init(); | 1871 | ret = rc80211_pid_init(); |
1869 | if (ret) | 1872 | if (ret) |