From 0204464329c17ba6d293e1899f71223599a0e582 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Wed, 8 Sep 2010 20:56:32 +0200 Subject: 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 ++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 50 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2400pci.c') 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, } 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, -- cgit v1.2.2