From 0204464329c17ba6d293e1899f71223599a0e582 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Wed, 8 Sep 2010 20:56:32 +0200 Subject: [PATCH] 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 Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 114 +++++++++++--------- drivers/net/wireless/rt2x00/rt2500pci.c | 115 ++++++++++++--------- drivers/net/wireless/rt2x00/rt2500usb.c | 34 +++--- drivers/net/wireless/rt2x00/rt2800lib.c | 60 ++++++----- drivers/net/wireless/rt2x00/rt2800lib.h | 3 +- drivers/net/wireless/rt2x00/rt2x00.h | 3 +- drivers/net/wireless/rt2x00/rt2x00config.c | 5 +- drivers/net/wireless/rt2x00/rt2x00lib.h | 3 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 6 +- drivers/net/wireless/rt2x00/rt61pci.c | 47 +++++---- drivers/net/wireless/rt2x00/rt73usb.c | 47 +++++---- 11 files changed, 256 insertions(+), 181 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index e3005ff5ae9..4b88909275a 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, } static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) + struct rt2x00lib_erp *erp, + u32 changed) { int preamble_mask; u32 reg; @@ -329,59 +330,72 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, /* * When short preamble is enabled, we should set bit 0x08 */ - preamble_mask = erp->short_preamble << 3; - - rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); - rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x1ff); - rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0x13a); - rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); - rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); - rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10)); - rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); - rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); - rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20)); - rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); - rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); - rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55)); - rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); - rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); - rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110)); - rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); - - rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + preamble_mask = erp->short_preamble << 3; + + rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); + rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x1ff); + rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0x13a); + rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); + rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); + rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); + rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); + rt2x00_set_field32(®, ARCSR2_LENGTH, + GET_DURATION(ACK_SIZE, 10)); + rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); + rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); + rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); + rt2x00_set_field32(®, ARCSR2_LENGTH, + GET_DURATION(ACK_SIZE, 20)); + rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); + rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); + rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); + rt2x00_set_field32(®, ARCSR2_LENGTH, + GET_DURATION(ACK_SIZE, 55)); + rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); + rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); + rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); + rt2x00_set_field32(®, ARCSR2_LENGTH, + GET_DURATION(ACK_SIZE, 110)); + rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); + } - rt2x00pci_register_read(rt2x00dev, CSR11, ®); - rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); - rt2x00pci_register_write(rt2x00dev, CSR11, reg); + if (changed & BSS_CHANGED_BASIC_RATES) + rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); - rt2x00pci_register_read(rt2x00dev, CSR12, ®); - rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, erp->beacon_int * 16); - rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16); - rt2x00pci_register_write(rt2x00dev, CSR12, reg); + if (changed & BSS_CHANGED_ERP_SLOT) { + rt2x00pci_register_read(rt2x00dev, CSR11, ®); + rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); + rt2x00pci_register_write(rt2x00dev, CSR11, reg); - rt2x00pci_register_read(rt2x00dev, CSR18, ®); - rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); - rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); - rt2x00pci_register_write(rt2x00dev, CSR18, reg); + rt2x00pci_register_read(rt2x00dev, CSR18, ®); + rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); + rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); + rt2x00pci_register_write(rt2x00dev, CSR18, reg); - rt2x00pci_register_read(rt2x00dev, CSR19, ®); - rt2x00_set_field32(®, CSR19_DIFS, erp->difs); - rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); - rt2x00pci_register_write(rt2x00dev, CSR19, reg); + rt2x00pci_register_read(rt2x00dev, CSR19, ®); + rt2x00_set_field32(®, CSR19_DIFS, erp->difs); + rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); + rt2x00pci_register_write(rt2x00dev, CSR19, reg); + } + + if (changed & BSS_CHANGED_BEACON_INT) { + rt2x00pci_register_read(rt2x00dev, CSR12, ®); + rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, + erp->beacon_int * 16); + rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, + erp->beacon_int * 16); + rt2x00pci_register_write(rt2x00dev, CSR12, reg); + } } static 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 1e6a91b8d3d..46ef692e404 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, } static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) + struct rt2x00lib_erp *erp, + u32 changed) { int preamble_mask; u32 reg; @@ -335,59 +336,73 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, /* * When short preamble is enabled, we should set bit 0x08 */ - preamble_mask = erp->short_preamble << 3; - - rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); - rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x162); - rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0xa2); - rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); - rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); - rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10)); - rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); - rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); - rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20)); - rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); - rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); - rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55)); - rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); - rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); - rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110)); - rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); - - rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + preamble_mask = erp->short_preamble << 3; + + rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); + rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x162); + rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0xa2); + rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); + rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); + rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); + rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); + rt2x00_set_field32(®, ARCSR2_LENGTH, + GET_DURATION(ACK_SIZE, 10)); + rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); + rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); + rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); + rt2x00_set_field32(®, ARCSR2_LENGTH, + GET_DURATION(ACK_SIZE, 20)); + rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); + rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); + rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); + rt2x00_set_field32(®, ARCSR2_LENGTH, + GET_DURATION(ACK_SIZE, 55)); + rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); + rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); + rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); + rt2x00_set_field32(®, ARCSR2_LENGTH, + GET_DURATION(ACK_SIZE, 110)); + rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); + } - rt2x00pci_register_read(rt2x00dev, CSR11, ®); - rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); - rt2x00pci_register_write(rt2x00dev, CSR11, reg); + if (changed & BSS_CHANGED_BASIC_RATES) + rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); + + if (changed & BSS_CHANGED_ERP_SLOT) { + rt2x00pci_register_read(rt2x00dev, CSR11, ®); + rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); + rt2x00pci_register_write(rt2x00dev, CSR11, reg); - rt2x00pci_register_read(rt2x00dev, CSR12, ®); - rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, erp->beacon_int * 16); - rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16); - rt2x00pci_register_write(rt2x00dev, CSR12, reg); + rt2x00pci_register_read(rt2x00dev, CSR18, ®); + rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); + rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); + rt2x00pci_register_write(rt2x00dev, CSR18, reg); - rt2x00pci_register_read(rt2x00dev, CSR18, ®); - rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); - rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); - rt2x00pci_register_write(rt2x00dev, CSR18, reg); + rt2x00pci_register_read(rt2x00dev, CSR19, ®); + rt2x00_set_field32(®, CSR19_DIFS, erp->difs); + rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); + rt2x00pci_register_write(rt2x00dev, CSR19, reg); + } + + if (changed & BSS_CHANGED_BEACON_INT) { + rt2x00pci_register_read(rt2x00dev, CSR12, ®); + rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, + erp->beacon_int * 16); + rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, + erp->beacon_int * 16); + rt2x00pci_register_write(rt2x00dev, CSR12, reg); + } - rt2x00pci_register_read(rt2x00dev, CSR19, ®); - rt2x00_set_field32(®, CSR19_DIFS, erp->difs); - rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); - rt2x00pci_register_write(rt2x00dev, CSR19, reg); } static 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 a161e9e33b7..5843a6d8b62 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, } static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) + struct rt2x00lib_erp *erp, + u32 changed) { u16 reg; - rt2500usb_register_read(rt2x00dev, TXRX_CSR10, ®); - rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, - !!erp->short_preamble); - rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + rt2500usb_register_read(rt2x00dev, TXRX_CSR10, ®); + rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, + !!erp->short_preamble); + rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); + } - rt2500usb_register_write(rt2x00dev, TXRX_CSR11, erp->basic_rates); + if (changed & BSS_CHANGED_BASIC_RATES) + rt2500usb_register_write(rt2x00dev, TXRX_CSR11, + erp->basic_rates); - rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); - rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, erp->beacon_int * 4); - rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); + if (changed & BSS_CHANGED_BEACON_INT) { + rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); + rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, + erp->beacon_int * 4); + rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); + } - rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time); - rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs); - rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs); + if (changed & BSS_CHANGED_ERP_SLOT) { + rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time); + rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs); + rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs); + } } static 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 78e5830c86c..c7076deaece 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, } EXPORT_SYMBOL_GPL(rt2800_config_intf); -void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp) +void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp, + u32 changed) { u32 reg; - rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); - rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, - !!erp->short_preamble); - rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, - !!erp->short_preamble); - rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg); + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); + rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, + !!erp->short_preamble); + rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, + !!erp->short_preamble); + rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg); + } - rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®); - rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, - erp->cts_protection ? 2 : 0); - rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); + if (changed & BSS_CHANGED_ERP_CTS_PROT) { + rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, + erp->cts_protection ? 2 : 0); + rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); + } - rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, - erp->basic_rates); - rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); + if (changed & BSS_CHANGED_BASIC_RATES) { + rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, + erp->basic_rates); + rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); + } - rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); - rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); - rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); + if (changed & BSS_CHANGED_ERP_SLOT) { + rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); + rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, + erp->slot_time); + rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); - rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); - rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); - rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); + rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); + rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); + rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); + } - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, - erp->beacon_int * 16); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + if (changed & BSS_CHANGED_BEACON_INT) { + rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, + erp->beacon_int * 16); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + } } EXPORT_SYMBOL_GPL(rt2800_config_erp); diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 986229c06c1..600c5eb25c4 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, const unsigned int filter_flags); void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, const unsigned int flags); -void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp); +void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp, + u32 changed); void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant); void rt2800_config(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 0ae942cb66d..7832a5996a8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -596,7 +596,8 @@ struct rt2x00lib_ops { #define CONFIG_UPDATE_BSSID ( 1 << 3 ) void (*config_erp) (struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp); + struct rt2x00lib_erp *erp, + u32 changed); void (*config_ant) (struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant); void (*config) (struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index db09a641a94..4c7ff765a8b 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, void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, - struct ieee80211_bss_conf *bss_conf) + struct ieee80211_bss_conf *bss_conf, + u32 changed) { struct rt2x00lib_erp erp; @@ -102,7 +103,7 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, /* Update global beacon interval time, this is needed for PS support */ rt2x00dev->beacon_int = bss_conf->beacon_int; - rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp); + rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed); } static inline diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index dc5c6574aaf..70c85ac2e53 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, const u8 *mac, const u8 *bssid); void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, - struct ieee80211_bss_conf *conf); + struct ieee80211_bss_conf *conf, + u32 changed); void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, struct antenna_setup ant); void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 235e037e650..7862a840984 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, * When the erp information has changed, we should perform * additional configuration steps. For all other changes we are done. */ - if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) - rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); + if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE | + BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BASIC_RATES | + BSS_CHANGED_BEACON_INT)) + rt2x00lib_config_erp(rt2x00dev, intf, bss_conf, changes); } EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 18829b2eccc..7a35f121e67 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, } static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) + struct rt2x00lib_erp *erp, + u32 changed) { u32 reg; @@ -603,28 +604,36 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); - rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); - rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); - rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, - !!erp->short_preamble); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); + rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); + rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, + !!erp->short_preamble); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); + } - rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); + if (changed & BSS_CHANGED_BASIC_RATES) + rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, + erp->basic_rates); - rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, - erp->beacon_int * 16); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + if (changed & BSS_CHANGED_BEACON_INT) { + rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, + erp->beacon_int * 16); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + } - rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®); - rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); - rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); + if (changed & BSS_CHANGED_ERP_SLOT) { + rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®); + rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); + rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); - rt2x00pci_register_read(rt2x00dev, MAC_CSR8, ®); - rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); - rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); - rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); - rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg); + rt2x00pci_register_read(rt2x00dev, MAC_CSR8, ®); + rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); + rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); + rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); + rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg); + } } static 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 df0ef3f70f1..cc6a72b09f4 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, } static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) + struct rt2x00lib_erp *erp, + u32 changed) { u32 reg; @@ -554,28 +555,36 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); - rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); - rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); - rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, - !!erp->short_preamble); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); + rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); + rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, + !!erp->short_preamble); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); + } - rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); + if (changed & BSS_CHANGED_BASIC_RATES) + rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, + erp->basic_rates); - rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, - erp->beacon_int * 16); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); + if (changed & BSS_CHANGED_BEACON_INT) { + rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, + erp->beacon_int * 16); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); + } - rt2x00usb_register_read(rt2x00dev, MAC_CSR9, ®); - rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); - rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg); + if (changed & BSS_CHANGED_ERP_SLOT) { + rt2x00usb_register_read(rt2x00dev, MAC_CSR9, ®); + rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); + rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg); - rt2x00usb_register_read(rt2x00dev, MAC_CSR8, ®); - rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); - rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); - rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); - rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg); + rt2x00usb_register_read(rt2x00dev, MAC_CSR8, ®); + rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); + rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); + rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); + rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg); + } } static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, -- 2.39.5