aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2010-01-04 15:57:59 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-01-05 17:13:32 -0500
commit13935e2cf39b124c9a2ff0349b294e0b1e2e3aef (patch)
treefaf724cf39bd9d3def6c2ab2ffd84b9fd33e1e7c /drivers/net/wireless/mwl8k.c
parent610677d2f0415570a7590790e8be376a946cd08b (diff)
mwl8k: pass in HT capabilities and rates when associating
Pass the AP's MCS rate mask to SET_RATE when associating, and make UPDATE_STADB pass in the peer's HT caps and rates when adding a new hardware station database entry. Signed-off-by: Lennert Buytenhek <buytenh@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r--drivers/net/wireless/mwl8k.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 2ae6c363f374..e0301b6310f9 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -2153,7 +2153,7 @@ struct mwl8k_cmd_set_rate {
2153 2153
2154static int 2154static int
2155mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 2155mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2156 u32 legacy_rate_mask) 2156 u32 legacy_rate_mask, u8 *mcs_rates)
2157{ 2157{
2158 struct mwl8k_cmd_set_rate *cmd; 2158 struct mwl8k_cmd_set_rate *cmd;
2159 int rc; 2159 int rc;
@@ -2165,6 +2165,7 @@ mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2165 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); 2165 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE);
2166 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2166 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2167 legacy_rate_mask_to_array(cmd->legacy_rates, legacy_rate_mask); 2167 legacy_rate_mask_to_array(cmd->legacy_rates, legacy_rate_mask);
2168 memcpy(cmd->mcs_set, mcs_rates, 16);
2168 2169
2169 rc = mwl8k_post_cmd(hw, &cmd->header); 2170 rc = mwl8k_post_cmd(hw, &cmd->header);
2170 kfree(cmd); 2171 kfree(cmd);
@@ -2666,7 +2667,7 @@ struct mwl8k_cmd_update_stadb {
2666 2667
2667static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, 2668static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw,
2668 struct ieee80211_vif *vif, 2669 struct ieee80211_vif *vif,
2669 u8 *addr, u32 legacy_rate_mask) 2670 struct ieee80211_sta *sta)
2670{ 2671{
2671 struct mwl8k_cmd_update_stadb *cmd; 2672 struct mwl8k_cmd_update_stadb *cmd;
2672 struct peer_capability_info *p; 2673 struct peer_capability_info *p;
@@ -2679,12 +2680,18 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw,
2679 cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); 2680 cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB);
2680 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2681 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2681 cmd->action = cpu_to_le32(MWL8K_STA_DB_MODIFY_ENTRY); 2682 cmd->action = cpu_to_le32(MWL8K_STA_DB_MODIFY_ENTRY);
2682 memcpy(cmd->peer_addr, addr, ETH_ALEN); 2683 memcpy(cmd->peer_addr, sta->addr, ETH_ALEN);
2683 2684
2684 p = &cmd->peer_info; 2685 p = &cmd->peer_info;
2685 p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; 2686 p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT;
2686 p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability); 2687 p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability);
2687 legacy_rate_mask_to_array(p->legacy_rates, legacy_rate_mask); 2688 p->ht_support = sta->ht_cap.ht_supported;
2689 p->ht_caps = sta->ht_cap.cap;
2690 p->extended_ht_caps = (sta->ht_cap.ampdu_factor & 3) |
2691 ((sta->ht_cap.ampdu_density & 7) << 2);
2692 legacy_rate_mask_to_array(p->legacy_rates,
2693 sta->supp_rates[IEEE80211_BAND_2GHZ]);
2694 memcpy(p->ht_rates, sta->ht_cap.mcs.rx_mask, 16);
2688 p->interop = 1; 2695 p->interop = 1;
2689 p->amsdu_enabled = 0; 2696 p->amsdu_enabled = 0;
2690 2697
@@ -2967,6 +2974,7 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
2967{ 2974{
2968 struct mwl8k_priv *priv = hw->priv; 2975 struct mwl8k_priv *priv = hw->priv;
2969 u32 ap_legacy_rates; 2976 u32 ap_legacy_rates;
2977 u8 ap_mcs_rates[16];
2970 int rc; 2978 int rc;
2971 2979
2972 if (mwl8k_fw_lock(hw)) 2980 if (mwl8k_fw_lock(hw))
@@ -2979,12 +2987,11 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
2979 priv->capture_beacon = false; 2987 priv->capture_beacon = false;
2980 2988
2981 /* 2989 /*
2982 * Get the AP's legacy rates. 2990 * Get the AP's legacy and MCS rates.
2983 */ 2991 */
2984 ap_legacy_rates = 0; 2992 ap_legacy_rates = 0;
2985 if (vif->bss_conf.assoc) { 2993 if (vif->bss_conf.assoc) {
2986 struct ieee80211_sta *ap; 2994 struct ieee80211_sta *ap;
2987
2988 rcu_read_lock(); 2995 rcu_read_lock();
2989 2996
2990 ap = ieee80211_find_sta(vif, vif->bss_conf.bssid); 2997 ap = ieee80211_find_sta(vif, vif->bss_conf.bssid);
@@ -2994,12 +3001,13 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
2994 } 3001 }
2995 3002
2996 ap_legacy_rates = ap->supp_rates[IEEE80211_BAND_2GHZ]; 3003 ap_legacy_rates = ap->supp_rates[IEEE80211_BAND_2GHZ];
3004 memcpy(ap_mcs_rates, ap->ht_cap.mcs.rx_mask, 16);
2997 3005
2998 rcu_read_unlock(); 3006 rcu_read_unlock();
2999 } 3007 }
3000 3008
3001 if ((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) { 3009 if ((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) {
3002 rc = mwl8k_cmd_set_rate(hw, vif, ap_legacy_rates); 3010 rc = mwl8k_cmd_set_rate(hw, vif, ap_legacy_rates, ap_mcs_rates);
3003 if (rc) 3011 if (rc)
3004 goto out; 3012 goto out;
3005 3013
@@ -3186,8 +3194,7 @@ struct mwl8k_sta_notify_item
3186 struct list_head list; 3194 struct list_head list;
3187 struct ieee80211_vif *vif; 3195 struct ieee80211_vif *vif;
3188 enum sta_notify_cmd cmd; 3196 enum sta_notify_cmd cmd;
3189 u8 addr[ETH_ALEN]; 3197 struct ieee80211_sta sta;
3190 u32 legacy_rate_mask;
3191}; 3198};
3192 3199
3193static void mwl8k_sta_notify_worker(struct work_struct *work) 3200static void mwl8k_sta_notify_worker(struct work_struct *work)
@@ -3209,19 +3216,18 @@ static void mwl8k_sta_notify_worker(struct work_struct *work)
3209 if (s->cmd == STA_NOTIFY_ADD) { 3216 if (s->cmd == STA_NOTIFY_ADD) {
3210 int rc; 3217 int rc;
3211 3218
3212 rc = mwl8k_cmd_update_stadb_add(hw, s->vif, 3219 rc = mwl8k_cmd_update_stadb_add(hw, s->vif, &s->sta);
3213 s->addr, s->legacy_rate_mask);
3214 if (rc >= 0) { 3220 if (rc >= 0) {
3215 struct ieee80211_sta *sta; 3221 struct ieee80211_sta *sta;
3216 3222
3217 rcu_read_lock(); 3223 rcu_read_lock();
3218 sta = ieee80211_find_sta(s->vif, s->addr); 3224 sta = ieee80211_find_sta(s->vif, s->sta.addr);
3219 if (sta != NULL) 3225 if (sta != NULL)
3220 MWL8K_STA(sta)->peer_id = rc; 3226 MWL8K_STA(sta)->peer_id = rc;
3221 rcu_read_unlock(); 3227 rcu_read_unlock();
3222 } 3228 }
3223 } else { 3229 } else {
3224 mwl8k_cmd_update_stadb_del(hw, s->vif, s->addr); 3230 mwl8k_cmd_update_stadb_del(hw, s->vif, s->sta.addr);
3225 } 3231 }
3226 3232
3227 kfree(s); 3233 kfree(s);
@@ -3245,8 +3251,7 @@ mwl8k_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
3245 if (s != NULL) { 3251 if (s != NULL) {
3246 s->vif = vif; 3252 s->vif = vif;
3247 s->cmd = cmd; 3253 s->cmd = cmd;
3248 memcpy(s->addr, sta->addr, ETH_ALEN); 3254 s->sta = *sta;
3249 s->legacy_rate_mask = sta->supp_rates[IEEE80211_BAND_2GHZ];
3250 3255
3251 spin_lock(&priv->sta_notify_list_lock); 3256 spin_lock(&priv->sta_notify_list_lock);
3252 list_add_tail(&s->list, &priv->sta_notify_list); 3257 list_add_tail(&s->list, &priv->sta_notify_list);