aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c99
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c2
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}
1170EXPORT_SYMBOL_GPL(rt2800_config_intf); 1170EXPORT_SYMBOL_GPL(rt2800_config_intf);
1171 1171
1172static 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, &reg);
1248 rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, mm20_rate);
1249 rt2x00_set_field32(&reg, 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, &reg);
1253 rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, mm40_rate);
1254 rt2x00_set_field32(&reg, 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, &reg);
1258 rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, gf20_rate);
1259 rt2x00_set_field32(&reg, 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, &reg);
1263 rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, gf40_rate);
1264 rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, gf40_mode);
1265 rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
1266}
1267
1172void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp, 1268void 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}
1217EXPORT_SYMBOL_GPL(rt2800_config_erp); 1316EXPORT_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}
677EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); 677EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);