diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 99 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00config.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 2 |
4 files changed, 104 insertions, 1 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 19534f272d76..4ecacea677ac 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1169,6 +1169,102 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, | |||
1169 | } | 1169 | } |
1170 | EXPORT_SYMBOL_GPL(rt2800_config_intf); | 1170 | EXPORT_SYMBOL_GPL(rt2800_config_intf); |
1171 | 1171 | ||
1172 | static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev, | ||
1173 | struct rt2x00lib_erp *erp) | ||
1174 | { | ||
1175 | bool any_sta_nongf = !!(erp->ht_opmode & | ||
1176 | IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | ||
1177 | u8 protection = erp->ht_opmode & IEEE80211_HT_OP_MODE_PROTECTION; | ||
1178 | u8 mm20_mode, mm40_mode, gf20_mode, gf40_mode; | ||
1179 | u16 mm20_rate, mm40_rate, gf20_rate, gf40_rate; | ||
1180 | u32 reg; | ||
1181 | |||
1182 | /* default protection rate for HT20: OFDM 24M */ | ||
1183 | mm20_rate = gf20_rate = 0x4004; | ||
1184 | |||
1185 | /* default protection rate for HT40: duplicate OFDM 24M */ | ||
1186 | mm40_rate = gf40_rate = 0x4084; | ||
1187 | |||
1188 | switch (protection) { | ||
1189 | case IEEE80211_HT_OP_MODE_PROTECTION_NONE: | ||
1190 | /* | ||
1191 | * All STAs in this BSS are HT20/40 but there might be | ||
1192 | * STAs not supporting greenfield mode. | ||
1193 | * => Disable protection for HT transmissions. | ||
1194 | */ | ||
1195 | mm20_mode = mm40_mode = gf20_mode = gf40_mode = 0; | ||
1196 | |||
1197 | break; | ||
1198 | case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: | ||
1199 | /* | ||
1200 | * All STAs in this BSS are HT20 or HT20/40 but there | ||
1201 | * might be STAs not supporting greenfield mode. | ||
1202 | * => Protect all HT40 transmissions. | ||
1203 | */ | ||
1204 | mm20_mode = gf20_mode = 0; | ||
1205 | mm40_mode = gf40_mode = 2; | ||
1206 | |||
1207 | break; | ||
1208 | case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER: | ||
1209 | /* | ||
1210 | * Nonmember protection: | ||
1211 | * According to 802.11n we _should_ protect all | ||
1212 | * HT transmissions (but we don't have to). | ||
1213 | * | ||
1214 | * But if cts_protection is enabled we _shall_ protect | ||
1215 | * all HT transmissions using a CCK rate. | ||
1216 | * | ||
1217 | * And if any station is non GF we _shall_ protect | ||
1218 | * GF transmissions. | ||
1219 | * | ||
1220 | * We decide to protect everything | ||
1221 | * -> fall through to mixed mode. | ||
1222 | */ | ||
1223 | case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: | ||
1224 | /* | ||
1225 | * Legacy STAs are present | ||
1226 | * => Protect all HT transmissions. | ||
1227 | */ | ||
1228 | mm20_mode = mm40_mode = gf20_mode = gf40_mode = 2; | ||
1229 | |||
1230 | /* | ||
1231 | * If erp protection is needed we have to protect HT | ||
1232 | * transmissions with CCK 11M long preamble. | ||
1233 | */ | ||
1234 | if (erp->cts_protection) { | ||
1235 | /* don't duplicate RTS/CTS in CCK mode */ | ||
1236 | mm20_rate = mm40_rate = 0x0003; | ||
1237 | gf20_rate = gf40_rate = 0x0003; | ||
1238 | } | ||
1239 | break; | ||
1240 | }; | ||
1241 | |||
1242 | /* check for STAs not supporting greenfield mode */ | ||
1243 | if (any_sta_nongf) | ||
1244 | gf20_mode = gf40_mode = 2; | ||
1245 | |||
1246 | /* Update HT protection config */ | ||
1247 | rt2800_register_read(rt2x00dev, MM20_PROT_CFG, ®); | ||
1248 | rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_RATE, mm20_rate); | ||
1249 | rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_CTRL, mm20_mode); | ||
1250 | rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg); | ||
1251 | |||
1252 | rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®); | ||
1253 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, mm40_rate); | ||
1254 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, mm40_mode); | ||
1255 | rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg); | ||
1256 | |||
1257 | rt2800_register_read(rt2x00dev, GF20_PROT_CFG, ®); | ||
1258 | rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_RATE, gf20_rate); | ||
1259 | rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_CTRL, gf20_mode); | ||
1260 | rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg); | ||
1261 | |||
1262 | rt2800_register_read(rt2x00dev, GF40_PROT_CFG, ®); | ||
1263 | rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_RATE, gf40_rate); | ||
1264 | rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_CTRL, gf40_mode); | ||
1265 | rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg); | ||
1266 | } | ||
1267 | |||
1172 | void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp, | 1268 | void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp, |
1173 | u32 changed) | 1269 | u32 changed) |
1174 | { | 1270 | { |
@@ -1213,6 +1309,9 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp, | |||
1213 | erp->beacon_int * 16); | 1309 | erp->beacon_int * 16); |
1214 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 1310 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
1215 | } | 1311 | } |
1312 | |||
1313 | if (changed & BSS_CHANGED_HT) | ||
1314 | rt2800_config_ht_opmode(rt2x00dev, erp); | ||
1216 | } | 1315 | } |
1217 | EXPORT_SYMBOL_GPL(rt2800_config_erp); | 1316 | EXPORT_SYMBOL_GPL(rt2800_config_erp); |
1218 | 1317 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index bab10adae537..75ac6624bf9e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -458,6 +458,7 @@ struct rt2x00lib_erp { | |||
458 | short eifs; | 458 | short eifs; |
459 | 459 | ||
460 | u16 beacon_int; | 460 | u16 beacon_int; |
461 | u16 ht_opmode; | ||
461 | }; | 462 | }; |
462 | 463 | ||
463 | /* | 464 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 4c7ff765a8bf..54ffb5aeb34e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -103,6 +103,9 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, | |||
103 | /* Update global beacon interval time, this is needed for PS support */ | 103 | /* Update global beacon interval time, this is needed for PS support */ |
104 | rt2x00dev->beacon_int = bss_conf->beacon_int; | 104 | rt2x00dev->beacon_int = bss_conf->beacon_int; |
105 | 105 | ||
106 | if (changed & BSS_CHANGED_HT) | ||
107 | erp.ht_opmode = bss_conf->ht_operation_mode; | ||
108 | |||
106 | rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed); | 109 | rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed); |
107 | } | 110 | } |
108 | 111 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 7862a840984a..c3c206a97d54 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -671,7 +671,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
671 | */ | 671 | */ |
672 | if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE | | 672 | if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE | |
673 | BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BASIC_RATES | | 673 | BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BASIC_RATES | |
674 | BSS_CHANGED_BEACON_INT)) | 674 | BSS_CHANGED_BEACON_INT | BSS_CHANGED_HT)) |
675 | rt2x00lib_config_erp(rt2x00dev, intf, bss_conf, changes); | 675 | rt2x00lib_config_erp(rt2x00dev, intf, bss_conf, changes); |
676 | } | 676 | } |
677 | EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); | 677 | EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); |