aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2800lib.c
diff options
context:
space:
mode:
authorHelmut Schaa <helmut.schaa@googlemail.com>2010-10-02 05:28:34 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-10-05 13:35:26 -0400
commit87c1915d2c271a8998a79f16bcf5353e2c28db45 (patch)
treea27d5423cdc242db45ebffecc23523890bdc8335 /drivers/net/wireless/rt2x00/rt2800lib.c
parenta13ac9df0a2125507295da02444cd88bebf0df36 (diff)
rt2x00: Implement HT protection for rt2800
Update the HT operation mode when mac80211 sends it to us and set the different HT protection modes and rates accordingly. For now only use CTS-to-self with OFDM 24M or CCK 11M when protection is required. Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 19534f272d7..4ecacea677a 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