diff options
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); |