aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
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);