aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2010-01-04 15:55:52 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-01-05 17:13:28 -0500
commitc6e9601071173fed2a77f9c435c41f3b33d1018f (patch)
tree64fa716b002e891571af4ceb2f63a6a4d7dad27a /drivers/net/wireless/mwl8k.c
parenta680400e8ac32adda81b5e2d7f23dfac63e064fe (diff)
mwl8k: honor peer rate set
When calling SET_RATE, SET_AID, or when creating a station database entry for our AP, pass in the AP's rate set instead of just blindly enabling all legacy rates, so as to end up doing the right thing when talking to 11b-only APs. 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.c57
1 files changed, 43 insertions, 14 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 5b5cf9357dbf..d8eff68978f1 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -256,10 +256,6 @@ static const struct ieee80211_rate mwl8k_rates[] = {
256 { .bitrate = 720, .hw_value = 144, }, 256 { .bitrate = 720, .hw_value = 144, },
257}; 257};
258 258
259static const u8 mwl8k_rateids[12] = {
260 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108,
261};
262
263/* Set or get info from Firmware */ 259/* Set or get info from Firmware */
264#define MWL8K_CMD_SET 0x0001 260#define MWL8K_CMD_SET 0x0001
265#define MWL8K_CMD_GET 0x0000 261#define MWL8K_CMD_GET 0x0000
@@ -2076,8 +2072,25 @@ struct mwl8k_cmd_update_set_aid {
2076 __u8 supp_rates[14]; 2072 __u8 supp_rates[14];
2077} __attribute__((packed)); 2073} __attribute__((packed));
2078 2074
2075static void legacy_rate_mask_to_array(u8 *rates, u32 mask)
2076{
2077 int i;
2078 int j;
2079
2080 /*
2081 * Clear nonstandard rates 4 and 13.
2082 */
2083 mask &= 0x1fef;
2084
2085 for (i = 0, j = 0; i < 14; i++) {
2086 if (mask & (1 << i))
2087 rates[j++] = mwl8k_rates[i].hw_value;
2088 }
2089}
2090
2079static int 2091static int
2080mwl8k_cmd_set_aid(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 2092mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
2093 struct ieee80211_vif *vif, u32 legacy_rate_mask)
2081{ 2094{
2082 struct mwl8k_cmd_update_set_aid *cmd; 2095 struct mwl8k_cmd_update_set_aid *cmd;
2083 u16 prot_mode; 2096 u16 prot_mode;
@@ -2090,7 +2103,6 @@ mwl8k_cmd_set_aid(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
2090 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); 2103 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID);
2091 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2104 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2092 cmd->aid = cpu_to_le16(vif->bss_conf.aid); 2105 cmd->aid = cpu_to_le16(vif->bss_conf.aid);
2093
2094 memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); 2106 memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN);
2095 2107
2096 if (vif->bss_conf.use_cts_prot) { 2108 if (vif->bss_conf.use_cts_prot) {
@@ -2111,7 +2123,7 @@ mwl8k_cmd_set_aid(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
2111 } 2123 }
2112 cmd->protection_mode = cpu_to_le16(prot_mode); 2124 cmd->protection_mode = cpu_to_le16(prot_mode);
2113 2125
2114 memcpy(cmd->supp_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); 2126 legacy_rate_mask_to_array(cmd->supp_rates, legacy_rate_mask);
2115 2127
2116 rc = mwl8k_post_cmd(hw, &cmd->header); 2128 rc = mwl8k_post_cmd(hw, &cmd->header);
2117 kfree(cmd); 2129 kfree(cmd);
@@ -2132,7 +2144,8 @@ struct mwl8k_cmd_set_rate {
2132} __attribute__((packed)); 2144} __attribute__((packed));
2133 2145
2134static int 2146static int
2135mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 2147mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2148 u32 legacy_rate_mask)
2136{ 2149{
2137 struct mwl8k_cmd_set_rate *cmd; 2150 struct mwl8k_cmd_set_rate *cmd;
2138 int rc; 2151 int rc;
@@ -2143,7 +2156,7 @@ mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
2143 2156
2144 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); 2157 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE);
2145 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2158 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2146 memcpy(cmd->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); 2159 legacy_rate_mask_to_array(cmd->legacy_rates, legacy_rate_mask);
2147 2160
2148 rc = mwl8k_post_cmd(hw, &cmd->header); 2161 rc = mwl8k_post_cmd(hw, &cmd->header);
2149 kfree(cmd); 2162 kfree(cmd);
@@ -2644,7 +2657,8 @@ struct mwl8k_cmd_update_stadb {
2644#define MWL8K_PEER_TYPE_ACCESSPOINT 2 2657#define MWL8K_PEER_TYPE_ACCESSPOINT 2
2645 2658
2646static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, 2659static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw,
2647 struct ieee80211_vif *vif, u8 *addr) 2660 struct ieee80211_vif *vif,
2661 u8 *addr, u32 legacy_rate_mask)
2648{ 2662{
2649 struct mwl8k_cmd_update_stadb *cmd; 2663 struct mwl8k_cmd_update_stadb *cmd;
2650 struct peer_capability_info *p; 2664 struct peer_capability_info *p;
@@ -2662,7 +2676,7 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw,
2662 p = &cmd->peer_info; 2676 p = &cmd->peer_info;
2663 p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; 2677 p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT;
2664 p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability); 2678 p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability);
2665 memcpy(p->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); 2679 legacy_rate_mask_to_array(p->legacy_rates, legacy_rate_mask);
2666 p->interop = 1; 2680 p->interop = 1;
2667 p->amsdu_enabled = 0; 2681 p->amsdu_enabled = 0;
2668 2682
@@ -2956,8 +2970,20 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
2956 return; 2970 return;
2957 2971
2958 if (vif->bss_conf.assoc) { 2972 if (vif->bss_conf.assoc) {
2973 struct ieee80211_sta *ap;
2974 u32 legacy_rate_mask;
2975
2976 rcu_read_lock();
2977 ap = ieee80211_find_sta(vif, vif->bss_conf.bssid);
2978 if (ap != NULL)
2979 legacy_rate_mask = ap->supp_rates[IEEE80211_BAND_2GHZ];
2980 rcu_read_unlock();
2981
2982 if (ap == NULL)
2983 goto out;
2984
2959 /* Install rates */ 2985 /* Install rates */
2960 rc = mwl8k_cmd_set_rate(hw, vif); 2986 rc = mwl8k_cmd_set_rate(hw, vif, legacy_rate_mask);
2961 if (rc) 2987 if (rc)
2962 goto out; 2988 goto out;
2963 2989
@@ -2979,7 +3005,7 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
2979 goto out; 3005 goto out;
2980 3006
2981 /* Set AID */ 3007 /* Set AID */
2982 rc = mwl8k_cmd_set_aid(hw, vif); 3008 rc = mwl8k_cmd_set_aid(hw, vif, legacy_rate_mask);
2983 if (rc) 3009 if (rc)
2984 goto out; 3010 goto out;
2985 3011
@@ -3139,6 +3165,7 @@ struct mwl8k_sta_notify_item
3139 struct ieee80211_vif *vif; 3165 struct ieee80211_vif *vif;
3140 enum sta_notify_cmd cmd; 3166 enum sta_notify_cmd cmd;
3141 u8 addr[ETH_ALEN]; 3167 u8 addr[ETH_ALEN];
3168 u32 legacy_rate_mask;
3142}; 3169};
3143 3170
3144static void mwl8k_sta_notify_worker(struct work_struct *work) 3171static void mwl8k_sta_notify_worker(struct work_struct *work)
@@ -3160,7 +3187,8 @@ static void mwl8k_sta_notify_worker(struct work_struct *work)
3160 if (s->cmd == STA_NOTIFY_ADD) { 3187 if (s->cmd == STA_NOTIFY_ADD) {
3161 int rc; 3188 int rc;
3162 3189
3163 rc = mwl8k_cmd_update_stadb_add(hw, s->vif, s->addr); 3190 rc = mwl8k_cmd_update_stadb_add(hw, s->vif,
3191 s->addr, s->legacy_rate_mask);
3164 if (rc >= 0) { 3192 if (rc >= 0) {
3165 struct ieee80211_sta *sta; 3193 struct ieee80211_sta *sta;
3166 3194
@@ -3196,6 +3224,7 @@ mwl8k_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
3196 s->vif = vif; 3224 s->vif = vif;
3197 s->cmd = cmd; 3225 s->cmd = cmd;
3198 memcpy(s->addr, sta->addr, ETH_ALEN); 3226 memcpy(s->addr, sta->addr, ETH_ALEN);
3227 s->legacy_rate_mask = sta->supp_rates[IEEE80211_BAND_2GHZ];
3199 3228
3200 spin_lock(&priv->sta_notify_list_lock); 3229 spin_lock(&priv->sta_notify_list_lock);
3201 list_add_tail(&s->list, &priv->sta_notify_list); 3230 list_add_tail(&s->list, &priv->sta_notify_list);