diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2010-01-04 15:55:52 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-01-05 17:13:28 -0500 |
commit | c6e9601071173fed2a77f9c435c41f3b33d1018f (patch) | |
tree | 64fa716b002e891571af4ceb2f63a6a4d7dad27a /drivers/net/wireless/mwl8k.c | |
parent | a680400e8ac32adda81b5e2d7f23dfac63e064fe (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.c | 57 |
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 | ||
259 | static 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 | ||
2075 | static 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 | |||
2079 | static int | 2091 | static int |
2080 | mwl8k_cmd_set_aid(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 2092 | mwl8k_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 | ||
2134 | static int | 2146 | static int |
2135 | mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 2147 | mwl8k_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 | ||
2646 | static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, | 2659 | static 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 | ||
3144 | static void mwl8k_sta_notify_worker(struct work_struct *work) | 3171 | static 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); |