aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHelmut Schaa <helmut.schaa@googlemail.com>2010-09-08 14:56:32 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-09-14 16:03:43 -0400
commit0204464329c17ba6d293e1899f71223599a0e582 (patch)
tree368b9617c1ad770b77fd22612edbb49300d0f500
parent47ee3eb1359a5444efd9f529e3d28c02e8e405e7 (diff)
rt2x00: Check for specific changed flags when updating the erp config
Previously rt2x00 was always updating all erp related config variables even though mac80211 might only have changed one. Hence, pass the changed flags to the config_erp driver callback so that the driver can limit the changes to the correct values. This fixes an issue in AP mode where the beacon interval is not initialized (and thus zero) but still sent to the hardware causing an interrupt storm on rt2800pci hanging the system. 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>
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c114
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c115
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c34
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c60
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.h3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c5
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c47
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c47
11 files changed, 256 insertions, 181 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index e3005ff5ae98..4b88909275a1 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -321,7 +321,8 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
321} 321}
322 322
323static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, 323static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
324 struct rt2x00lib_erp *erp) 324 struct rt2x00lib_erp *erp,
325 u32 changed)
325{ 326{
326 int preamble_mask; 327 int preamble_mask;
327 u32 reg; 328 u32 reg;
@@ -329,59 +330,72 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
329 /* 330 /*
330 * When short preamble is enabled, we should set bit 0x08 331 * When short preamble is enabled, we should set bit 0x08
331 */ 332 */
332 preamble_mask = erp->short_preamble << 3; 333 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
333 334 preamble_mask = erp->short_preamble << 3;
334 rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg); 335
335 rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x1ff); 336 rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
336 rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0x13a); 337 rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x1ff);
337 rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); 338 rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0x13a);
338 rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1); 339 rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
339 rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); 340 rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
340 341 rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
341 rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg); 342
342 rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00); 343 rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
343 rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04); 344 rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
344 rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10)); 345 rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
345 rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); 346 rt2x00_set_field32(&reg, ARCSR2_LENGTH,
346 347 GET_DURATION(ACK_SIZE, 10));
347 rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg); 348 rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
348 rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask); 349
349 rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04); 350 rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
350 rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20)); 351 rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
351 rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); 352 rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
352 353 rt2x00_set_field32(&reg, ARCSR2_LENGTH,
353 rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg); 354 GET_DURATION(ACK_SIZE, 20));
354 rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask); 355 rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
355 rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04); 356
356 rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55)); 357 rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
357 rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); 358 rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
358 359 rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
359 rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg); 360 rt2x00_set_field32(&reg, ARCSR2_LENGTH,
360 rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask); 361 GET_DURATION(ACK_SIZE, 55));
361 rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84); 362 rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
362 rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110)); 363
363 rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); 364 rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
364 365 rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
365 rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); 366 rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
367 rt2x00_set_field32(&reg, ARCSR2_LENGTH,
368 GET_DURATION(ACK_SIZE, 110));
369 rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
370 }
366 371
367 rt2x00pci_register_read(rt2x00dev, CSR11, &reg); 372 if (changed & BSS_CHANGED_BASIC_RATES)
368 rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time); 373 rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
369 rt2x00pci_register_write(rt2x00dev, CSR11, reg);
370 374
371 rt2x00pci_register_read(rt2x00dev, CSR12, &reg); 375 if (changed & BSS_CHANGED_ERP_SLOT) {
372 rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL, erp->beacon_int * 16); 376 rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
373 rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16); 377 rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
374 rt2x00pci_register_write(rt2x00dev, CSR12, reg); 378 rt2x00pci_register_write(rt2x00dev, CSR11, reg);
375 379
376 rt2x00pci_register_read(rt2x00dev, CSR18, &reg); 380 rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
377 rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs); 381 rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
378 rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs); 382 rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
379 rt2x00pci_register_write(rt2x00dev, CSR18, reg); 383 rt2x00pci_register_write(rt2x00dev, CSR18, reg);
380 384
381 rt2x00pci_register_read(rt2x00dev, CSR19, &reg); 385 rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
382 rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs); 386 rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
383 rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs); 387 rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
384 rt2x00pci_register_write(rt2x00dev, CSR19, reg); 388 rt2x00pci_register_write(rt2x00dev, CSR19, reg);
389 }
390
391 if (changed & BSS_CHANGED_BEACON_INT) {
392 rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
393 rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
394 erp->beacon_int * 16);
395 rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
396 erp->beacon_int * 16);
397 rt2x00pci_register_write(rt2x00dev, CSR12, reg);
398 }
385} 399}
386 400
387static void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev, 401static void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 1e6a91b8d3df..46ef692e404d 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -327,7 +327,8 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
327} 327}
328 328
329static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, 329static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
330 struct rt2x00lib_erp *erp) 330 struct rt2x00lib_erp *erp,
331 u32 changed)
331{ 332{
332 int preamble_mask; 333 int preamble_mask;
333 u32 reg; 334 u32 reg;
@@ -335,59 +336,73 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
335 /* 336 /*
336 * When short preamble is enabled, we should set bit 0x08 337 * When short preamble is enabled, we should set bit 0x08
337 */ 338 */
338 preamble_mask = erp->short_preamble << 3; 339 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
339 340 preamble_mask = erp->short_preamble << 3;
340 rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg); 341
341 rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x162); 342 rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
342 rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0xa2); 343 rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x162);
343 rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); 344 rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0xa2);
344 rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1); 345 rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
345 rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); 346 rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
346 347 rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
347 rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg); 348
348 rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00); 349 rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
349 rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04); 350 rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
350 rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10)); 351 rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
351 rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); 352 rt2x00_set_field32(&reg, ARCSR2_LENGTH,
352 353 GET_DURATION(ACK_SIZE, 10));
353 rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg); 354 rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
354 rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask); 355
355 rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04); 356 rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
356 rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20)); 357 rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
357 rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); 358 rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
358 359 rt2x00_set_field32(&reg, ARCSR2_LENGTH,
359 rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg); 360 GET_DURATION(ACK_SIZE, 20));
360 rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask); 361 rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
361 rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04); 362
362 rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55)); 363 rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
363 rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); 364 rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
364 365 rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
365 rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg); 366 rt2x00_set_field32(&reg, ARCSR2_LENGTH,
366 rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask); 367 GET_DURATION(ACK_SIZE, 55));
367 rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84); 368 rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
368 rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110)); 369
369 rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); 370 rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
370 371 rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
371 rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); 372 rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
373 rt2x00_set_field32(&reg, ARCSR2_LENGTH,
374 GET_DURATION(ACK_SIZE, 110));
375 rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
376 }
372 377
373 rt2x00pci_register_read(rt2x00dev, CSR11, &reg); 378 if (changed & BSS_CHANGED_BASIC_RATES)
374 rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time); 379 rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
375 rt2x00pci_register_write(rt2x00dev, CSR11, reg); 380
381 if (changed & BSS_CHANGED_ERP_SLOT) {
382 rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
383 rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
384 rt2x00pci_register_write(rt2x00dev, CSR11, reg);
376 385
377 rt2x00pci_register_read(rt2x00dev, CSR12, &reg); 386 rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
378 rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL, erp->beacon_int * 16); 387 rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
379 rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16); 388 rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
380 rt2x00pci_register_write(rt2x00dev, CSR12, reg); 389 rt2x00pci_register_write(rt2x00dev, CSR18, reg);
381 390
382 rt2x00pci_register_read(rt2x00dev, CSR18, &reg); 391 rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
383 rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs); 392 rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
384 rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs); 393 rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
385 rt2x00pci_register_write(rt2x00dev, CSR18, reg); 394 rt2x00pci_register_write(rt2x00dev, CSR19, reg);
395 }
396
397 if (changed & BSS_CHANGED_BEACON_INT) {
398 rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
399 rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
400 erp->beacon_int * 16);
401 rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
402 erp->beacon_int * 16);
403 rt2x00pci_register_write(rt2x00dev, CSR12, reg);
404 }
386 405
387 rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
388 rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
389 rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
390 rt2x00pci_register_write(rt2x00dev, CSR19, reg);
391} 406}
392 407
393static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, 408static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index a161e9e33b73..5843a6d8b627 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -494,24 +494,34 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
494} 494}
495 495
496static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, 496static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
497 struct rt2x00lib_erp *erp) 497 struct rt2x00lib_erp *erp,
498 u32 changed)
498{ 499{
499 u16 reg; 500 u16 reg;
500 501
501 rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg); 502 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
502 rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE, 503 rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg);
503 !!erp->short_preamble); 504 rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
504 rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); 505 !!erp->short_preamble);
506 rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
507 }
505 508
506 rt2500usb_register_write(rt2x00dev, TXRX_CSR11, erp->basic_rates); 509 if (changed & BSS_CHANGED_BASIC_RATES)
510 rt2500usb_register_write(rt2x00dev, TXRX_CSR11,
511 erp->basic_rates);
507 512
508 rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg); 513 if (changed & BSS_CHANGED_BEACON_INT) {
509 rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL, erp->beacon_int * 4); 514 rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
510 rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); 515 rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
516 erp->beacon_int * 4);
517 rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
518 }
511 519
512 rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time); 520 if (changed & BSS_CHANGED_ERP_SLOT) {
513 rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs); 521 rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time);
514 rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs); 522 rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs);
523 rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs);
524 }
515} 525}
516 526
517static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev, 527static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 78e5830c86c2..c7076deaecea 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1159,38 +1159,50 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
1159} 1159}
1160EXPORT_SYMBOL_GPL(rt2800_config_intf); 1160EXPORT_SYMBOL_GPL(rt2800_config_intf);
1161 1161
1162void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp) 1162void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
1163 u32 changed)
1163{ 1164{
1164 u32 reg; 1165 u32 reg;
1165 1166
1166 rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg); 1167 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
1167 rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY, 1168 rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
1168 !!erp->short_preamble); 1169 rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY,
1169 rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE, 1170 !!erp->short_preamble);
1170 !!erp->short_preamble); 1171 rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE,
1171 rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg); 1172 !!erp->short_preamble);
1173 rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
1174 }
1172 1175
1173 rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg); 1176 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
1174 rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL, 1177 rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
1175 erp->cts_protection ? 2 : 0); 1178 rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL,
1176 rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); 1179 erp->cts_protection ? 2 : 0);
1180 rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
1181 }
1177 1182
1178 rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 1183 if (changed & BSS_CHANGED_BASIC_RATES) {
1179 erp->basic_rates); 1184 rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE,
1180 rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); 1185 erp->basic_rates);
1186 rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
1187 }
1181 1188
1182 rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg); 1189 if (changed & BSS_CHANGED_ERP_SLOT) {
1183 rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); 1190 rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
1184 rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); 1191 rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME,
1192 erp->slot_time);
1193 rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
1185 1194
1186 rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg); 1195 rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
1187 rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs); 1196 rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
1188 rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); 1197 rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
1198 }
1189 1199
1190 rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg); 1200 if (changed & BSS_CHANGED_BEACON_INT) {
1191 rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL, 1201 rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
1192 erp->beacon_int * 16); 1202 rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
1193 rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); 1203 erp->beacon_int * 16);
1204 rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
1205 }
1194} 1206}
1195EXPORT_SYMBOL_GPL(rt2800_config_erp); 1207EXPORT_SYMBOL_GPL(rt2800_config_erp);
1196 1208
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 986229c06c19..600c5eb25c41 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -169,7 +169,8 @@ void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
169 const unsigned int filter_flags); 169 const unsigned int filter_flags);
170void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, 170void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
171 struct rt2x00intf_conf *conf, const unsigned int flags); 171 struct rt2x00intf_conf *conf, const unsigned int flags);
172void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp); 172void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
173 u32 changed);
173void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant); 174void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant);
174void rt2800_config(struct rt2x00_dev *rt2x00dev, 175void rt2800_config(struct rt2x00_dev *rt2x00dev,
175 struct rt2x00lib_conf *libconf, 176 struct rt2x00lib_conf *libconf,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 0ae942cb66df..7832a5996a8c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -596,7 +596,8 @@ struct rt2x00lib_ops {
596#define CONFIG_UPDATE_BSSID ( 1 << 3 ) 596#define CONFIG_UPDATE_BSSID ( 1 << 3 )
597 597
598 void (*config_erp) (struct rt2x00_dev *rt2x00dev, 598 void (*config_erp) (struct rt2x00_dev *rt2x00dev,
599 struct rt2x00lib_erp *erp); 599 struct rt2x00lib_erp *erp,
600 u32 changed);
600 void (*config_ant) (struct rt2x00_dev *rt2x00dev, 601 void (*config_ant) (struct rt2x00_dev *rt2x00dev,
601 struct antenna_setup *ant); 602 struct antenna_setup *ant);
602 void (*config) (struct rt2x00_dev *rt2x00dev, 603 void (*config) (struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index db09a641a948..4c7ff765a8bf 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -81,7 +81,8 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
81 81
82void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, 82void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
83 struct rt2x00_intf *intf, 83 struct rt2x00_intf *intf,
84 struct ieee80211_bss_conf *bss_conf) 84 struct ieee80211_bss_conf *bss_conf,
85 u32 changed)
85{ 86{
86 struct rt2x00lib_erp erp; 87 struct rt2x00lib_erp erp;
87 88
@@ -102,7 +103,7 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
102 /* Update global beacon interval time, this is needed for PS support */ 103 /* Update global beacon interval time, this is needed for PS support */
103 rt2x00dev->beacon_int = bss_conf->beacon_int; 104 rt2x00dev->beacon_int = bss_conf->beacon_int;
104 105
105 rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp); 106 rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed);
106} 107}
107 108
108static inline 109static inline
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index dc5c6574aaf4..70c85ac2e53e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -86,7 +86,8 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
86 const u8 *mac, const u8 *bssid); 86 const u8 *mac, const u8 *bssid);
87void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, 87void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
88 struct rt2x00_intf *intf, 88 struct rt2x00_intf *intf,
89 struct ieee80211_bss_conf *conf); 89 struct ieee80211_bss_conf *conf,
90 u32 changed);
90void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, 91void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
91 struct antenna_setup ant); 92 struct antenna_setup ant);
92void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, 93void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 235e037e6509..7862a840984a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -669,8 +669,10 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
669 * When the erp information has changed, we should perform 669 * When the erp information has changed, we should perform
670 * additional configuration steps. For all other changes we are done. 670 * additional configuration steps. For all other changes we are done.
671 */ 671 */
672 if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) 672 if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE |
673 rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); 673 BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BASIC_RATES |
674 BSS_CHANGED_BEACON_INT))
675 rt2x00lib_config_erp(rt2x00dev, intf, bss_conf, changes);
674} 676}
675EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); 677EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
676 678
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 18829b2eccc3..7a35f121e678 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -594,7 +594,8 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
594} 594}
595 595
596static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, 596static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
597 struct rt2x00lib_erp *erp) 597 struct rt2x00lib_erp *erp,
598 u32 changed)
598{ 599{
599 u32 reg; 600 u32 reg;
600 601
@@ -603,28 +604,36 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
603 rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); 604 rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
604 rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); 605 rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
605 606
606 rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg); 607 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
607 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1); 608 rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
608 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE, 609 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
609 !!erp->short_preamble); 610 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
610 rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); 611 !!erp->short_preamble);
612 rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
613 }
611 614
612 rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); 615 if (changed & BSS_CHANGED_BASIC_RATES)
616 rt2x00pci_register_write(rt2x00dev, TXRX_CSR5,
617 erp->basic_rates);
613 618
614 rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg); 619 if (changed & BSS_CHANGED_BEACON_INT) {
615 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 620 rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
616 erp->beacon_int * 16); 621 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
617 rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); 622 erp->beacon_int * 16);
623 rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
624 }
618 625
619 rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg); 626 if (changed & BSS_CHANGED_ERP_SLOT) {
620 rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time); 627 rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
621 rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); 628 rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
629 rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
622 630
623 rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg); 631 rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg);
624 rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs); 632 rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
625 rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); 633 rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
626 rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs); 634 rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
627 rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg); 635 rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
636 }
628} 637}
629 638
630static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, 639static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index df0ef3f70f1e..cc6a72b09f46 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -545,7 +545,8 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
545} 545}
546 546
547static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, 547static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
548 struct rt2x00lib_erp *erp) 548 struct rt2x00lib_erp *erp,
549 u32 changed)
549{ 550{
550 u32 reg; 551 u32 reg;
551 552
@@ -554,28 +555,36 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
554 rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); 555 rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
555 rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); 556 rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
556 557
557 rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg); 558 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
558 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1); 559 rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
559 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE, 560 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
560 !!erp->short_preamble); 561 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
561 rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); 562 !!erp->short_preamble);
563 rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
564 }
562 565
563 rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); 566 if (changed & BSS_CHANGED_BASIC_RATES)
567 rt2x00usb_register_write(rt2x00dev, TXRX_CSR5,
568 erp->basic_rates);
564 569
565 rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg); 570 if (changed & BSS_CHANGED_BEACON_INT) {
566 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 571 rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
567 erp->beacon_int * 16); 572 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
568 rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); 573 erp->beacon_int * 16);
574 rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
575 }
569 576
570 rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg); 577 if (changed & BSS_CHANGED_ERP_SLOT) {
571 rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time); 578 rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
572 rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg); 579 rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
580 rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
573 581
574 rt2x00usb_register_read(rt2x00dev, MAC_CSR8, &reg); 582 rt2x00usb_register_read(rt2x00dev, MAC_CSR8, &reg);
575 rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs); 583 rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
576 rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); 584 rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
577 rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs); 585 rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
578 rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg); 586 rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg);
587 }
579} 588}
580 589
581static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, 590static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,