>From Ivo van Doorn <[EMAIL PROTECTED]> Optimize the configuration handlers to only run when the current configuration has been changed. This means we need to store the current setting of most configuration options in rt2x00_dev.
Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]> diff -rU3 wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2400pci.c --- wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-07-26 10:55:31.000000000 +0200 +++ wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-07-26 12:49:38.000000000 +0200 @@ -475,6 +475,14 @@ u32 reg; /* + * Only continue when there is something to be done. + */ + if (type == rt2x00dev->interface.type || + (rt2x00dev->interface.monitor_count ^ + GET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR))) + return; + + /* * Apply hardware packet filter. */ rt2x00_register_read(rt2x00dev, RXCSR0, ®); @@ -520,7 +528,13 @@ /* * Update working mode. */ - rt2x00dev->interface.type = type; + if (type != IEEE80211_IF_TYPE_MNTR) + rt2x00dev->interface.type = type; + + if (rt2x00dev->interface.monitor_count) + SET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR); + else + CLEAR_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR); } static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev, @@ -529,6 +543,12 @@ u32 rf1 = rt2x00dev->rf1; u32 rf3 = rt2x00dev->rf3; + /* + * Only continue when there is something to be done. + */ + if (channel == rt2x00dev->rx_params.channel) + return; + INFO("Switching channel. RF1: 0x%08x, RF2: 0x%08x, RF3: 0x%08x.\n", rf1, rf2, rf3); @@ -575,15 +595,31 @@ rt2x00dev->rx_params.channel = channel; /* + * Update rf fields + */ + rt2x00dev->rf1 = rf1; + rt2x00dev->rf2 = rf2; + rt2x00dev->rf3 = rf3; + + /* * Clear false CRC during channel switch. */ rt2x00_register_read(rt2x00dev, CNT0, &rf1); } -static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, u8 txpower) +static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower) { txpower = TXPOWER_TO_DEV(txpower); + + /* + * Only continue when there is something to be done. + */ + if (txpower == rt2x00dev->tx_power) + return; + rt2x00_bbp_write(rt2x00dev, 3, txpower); + + rt2x00dev->tx_power = txpower; } static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev, int antenna) @@ -591,6 +627,12 @@ u8 reg_rx; u8 reg_tx; + /* + * Only continue when there is something to be done. + */ + if (rt2x00dev->rx_params.antenna == antenna) + return; + rt2x00_bbp_read(rt2x00dev, 4, ®_rx); rt2x00_bbp_read(rt2x00dev, 1, ®_tx); @@ -713,6 +755,12 @@ { struct ieee80211_rate *rate; + /* + * Only continue when there is something to be done. + */ + if (rt2x00dev->rx_params.phymode == phymode) + return; + rate = &rt2x00dev->hw.modes[0].rates[ rt2x00dev->hw.modes[0].num_rates - 1]; @@ -1760,6 +1808,9 @@ if (!reg) return IRQ_NONE; + if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) + return IRQ_HANDLED; + /* * Handle interrupts, walk through all bits * and run the tasks, the bits are checked in order of @@ -1982,12 +2033,17 @@ u32 reg; /* - * Some configuration changes require the RX to be disabled. + * Check if we need to disable the radio, + * if this is not the case, at least the RX must be disabled. */ if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - rt2x00_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); - rt2x00_register_write(rt2x00dev, RXCSR0, reg); + if (!conf->radio_enabled) + rt2400pci_disable_radio(rt2x00dev); + else { + rt2x00_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); + rt2x00_register_write(rt2x00dev, RXCSR0, reg); + } } rt2400pci_config_channel(rt2x00dev, @@ -2000,24 +2056,13 @@ /* * Reenable RX only if the radio should be on. */ - if (conf->radio_enabled) { - if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - if (rt2400pci_open(net_dev)) { - ERROR("Failed to enabled radio.\n"); - return; - } - } else { - rt2x00_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); - rt2x00_register_write(rt2x00dev, RXCSR0, reg); - } - } else { - if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - if (rt2400pci_stop(net_dev)) { - ERROR("Failed to disable radio.\n"); - return; - } - } + if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { + rt2x00_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); + rt2x00_register_write(rt2x00dev, RXCSR0, reg); + } else if (conf->radio_enabled) { + if (rt2400pci_enable_radio(rt2x00dev)) + return; } } @@ -2141,10 +2186,20 @@ { struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev); + /* + * Check if we are not busy with the previous + * passive scan request. + */ if (rt2x00dev->scan) return -EBUSY; /* + * Check if the radio is enabled. + */ + if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) + return -EIO; + + /* * Allocate scanning structure to store scanning info. */ rt2x00dev->scan = kmalloc(sizeof(struct scanning), GFP_ATOMIC); @@ -2443,6 +2498,9 @@ struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev)); u32 reg[2] = { 0, 0 }; + if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC)) + return 0; + rt2x00_register_multiread(rt2x00dev, CSR3, ®[0], sizeof(reg)); net_dev->dev_addr[0] = rt2x00_get_field32(reg[0], CSR3_BYTE0); @@ -2454,6 +2512,10 @@ net_dev->addr_len = 6; + if (!is_valid_ether_addr(&net_dev->dev_addr[0])) + return -EINVAL; + + SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC); return 0; } diff -rU3 wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2500pci.c --- wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-07-26 10:56:10.000000000 +0200 +++ wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-07-26 12:50:25.000000000 +0200 @@ -475,6 +475,14 @@ u32 reg; /* + * Only continue when there is something to be done. + */ + if (type == rt2x00dev->interface.type || + (rt2x00dev->interface.monitor_count ^ + GET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR))) + return; + + /* * Apply hardware packet filter. */ rt2x00_register_read(rt2x00dev, RXCSR0, ®); @@ -523,7 +531,13 @@ /* * Update working mode. */ - rt2x00dev->interface.type = type; + if (type != IEEE80211_IF_TYPE_MNTR) + rt2x00dev->interface.type = type; + + if (rt2x00dev->interface.monitor_count) + SET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR); + else + CLEAR_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR); } static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, @@ -533,6 +547,12 @@ u32 rf3 = rt2x00dev->rf3; u32 rf4 = rt2x00dev->rf4; + /* + * Only continue when there is something to be done. + */ + if (channel == rt2x00dev->rx_params.channel) + return; + if (txpower == 0xff) txpower = rt2x00dev->tx_power; txpower = TXPOWER_TO_DEV(txpower); @@ -559,14 +579,14 @@ } } - INFO("Switching channel. RF1: 0x%08x, RF2: 0x%08x, RF3: 0x%08x, " - "RF4: 0x%08x.\n", rf1, rf2, rf3, rf4); - /* * Set TXpower. */ rt2x00_set_field32(&rf3, RF3_TXPOWER, txpower); + INFO("Switching channel. RF1: 0x%08x, RF2: 0x%08x, RF3: 0x%08x, " + "RF4: 0x%08x.\n", rf1, rf2, rf3, rf4); + /* * For RT2525 we should first set the channel to half band higher. */ @@ -611,6 +631,16 @@ rt2x00dev->rx_params.channel = channel; /* + * Update rf fields + */ + rt2x00dev->rf1 = rf1; + rt2x00dev->rf2 = rf2; + rt2x00dev->rf3 = rf3; + rt2x00dev->rf4 = rf4; + + rt2x00dev->tx_power = txpower; + + /* * Clear false CRC during channel switch. */ rt2x00_register_read(rt2x00dev, CNT0, &rf1); @@ -620,8 +650,16 @@ { txpower = TXPOWER_TO_DEV(txpower); + /* + * Only continue when there is something to be done. + */ + if (txpower == rt2x00dev->tx_power) + return; + rt2x00_set_field32(&rt2x00dev->rf3, RF3_TXPOWER, txpower); rt2x00_rf_write(rt2x00dev, rt2x00dev->rf3); + + rt2x00dev->tx_power = txpower; } static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev, int antenna) @@ -630,6 +668,12 @@ u8 reg_rx; u8 reg_tx; + /* + * Only continue when there is something to be done. + */ + if (rt2x00dev->rx_params.antenna == antenna) + return; + rt2x00_register_read(rt2x00dev, BBPCSR1, ®); rt2x00_bbp_read(rt2x00dev, 14, ®_rx); rt2x00_bbp_read(rt2x00dev, 2, ®_tx); @@ -768,6 +812,12 @@ { struct ieee80211_rate *rate; + /* + * Only continue when there is something to be done. + */ + if (rt2x00dev->rx_params.phymode == phymode) + return; + if (phymode == MODE_IEEE80211A && rt2x00_rf(&rt2x00dev->chip, RF5222)) rate = &rt2x00dev->hw.modes[2].rates[ @@ -1896,6 +1946,9 @@ if (!reg) return IRQ_NONE; + if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) + return IRQ_HANDLED; + /* * Handle interrupts, walk through all bits * and run the tasks, the bits are checked in order of @@ -2117,12 +2170,17 @@ u32 reg; /* - * Some configuration changes require the RX to be disabled. + * Check if we need to disable the radio, + * if this is not the case, at least the RX must be disabled. */ if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - rt2x00_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); - rt2x00_register_write(rt2x00dev, RXCSR0, reg); + if (!conf->radio_enabled) + rt2500pci_disable_radio(rt2x00dev); + else { + rt2x00_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); + rt2x00_register_write(rt2x00dev, RXCSR0, reg); + } } rt2500pci_config_channel(rt2x00dev, @@ -2136,24 +2194,13 @@ /* * Reenable RX only if the radio should be on. */ - if (conf->radio_enabled) { - if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - if (rt2500pci_open(net_dev)) { - ERROR("Failed to enabled radio.\n"); - return; - } - } else { - rt2x00_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); - rt2x00_register_write(rt2x00dev, RXCSR0, reg); - } - } else { - if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - if (rt2500pci_stop(net_dev)) { - ERROR("Failed to disable radio.\n"); - return; - } - } + if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { + rt2x00_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); + rt2x00_register_write(rt2x00dev, RXCSR0, reg); + } else if (conf->radio_enabled) { + if (rt2500pci_enable_radio(rt2x00dev)) + return; } } @@ -2273,10 +2320,20 @@ { struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev); + /* + * Check if we are not busy with the previous + * passive scan request. + */ if (rt2x00dev->scan) return -EBUSY; /* + * Check if the radio is enabled. + */ + if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) + return -EIO; + + /* * Allocate scanning structure to store scanning info. */ rt2x00dev->scan = kmalloc(sizeof(struct scanning), GFP_ATOMIC); @@ -2583,6 +2640,9 @@ struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev)); u32 reg[2] = { 0, 0 }; + if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC)) + return 0; + rt2x00_register_multiread(rt2x00dev, CSR3, ®[0], sizeof(reg)); net_dev->dev_addr[0] = rt2x00_get_field32(reg[0], CSR3_BYTE0); @@ -2594,6 +2654,10 @@ net_dev->addr_len = 6; + if (!is_valid_ether_addr(&net_dev->dev_addr[0])) + return -EINVAL; + + SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC); return 0; } diff -rU3 wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2500usb.c --- wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-07-26 10:56:11.000000000 +0200 +++ wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-07-26 12:50:28.000000000 +0200 @@ -325,6 +325,14 @@ u16 reg; /* + * Only continue when there is something to be done. + */ + if (type == rt2x00dev->interface.type || + (rt2x00dev->interface.monitor_count ^ + GET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR))) + return; + + /* * Apply hardware packet filter. */ rt2x00_register_read(rt2x00dev, TXRX_CSR2, ®); @@ -370,7 +378,13 @@ /* * Update working mode. */ - rt2x00dev->interface.type = type; + if (type != IEEE80211_IF_TYPE_MNTR) + rt2x00dev->interface.type = type; + + if (rt2x00dev->interface.monitor_count) + SET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR); + else + CLEAR_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR); } static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev, @@ -380,6 +394,12 @@ u32 rf3 = rt2x00dev->rf3; u32 rf4 = rt2x00dev->rf4; + /* + * Only continue when there is something to be done. + */ + if (channel == rt2x00dev->rx_params.channel) + return; + if (txpower == 0xff) txpower = rt2x00dev->tx_power; txpower = TXPOWER_TO_DEV(txpower); @@ -418,11 +438,14 @@ } } + /* + * Set TXpower. + */ + rt2x00_set_field32_nb(&rf3, RF3_TXPOWER, txpower); + INFO("Switching channel. RF1: 0x%08x, RF2: 0x%08x, RF3: 0x%08x, " "RF4: 0x%08x.\n", rf1, rf2, rf3, rf4); - rt2x00_set_field32_nb(&rf3, RF3_TXPOWER, txpower); - /* * For RT2525E we should first set the channel to half band higher. */ @@ -443,14 +466,34 @@ */ rt2x00dev->rx_params.freq = freq; rt2x00dev->rx_params.channel = channel; + + rt2x00dev->tx_power = txpower; + + /* + * Update rf fields + */ + rt2x00dev->rf1 = rf1; + rt2x00dev->rf2 = rf2; + rt2x00dev->rf3 = rf3; + rt2x00dev->rf4 = rf4; + + rt2x00dev->tx_power = txpower; } static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower) { txpower = TXPOWER_TO_DEV(txpower); + /* + * Only continue when there is something to be done. + */ + if (txpower == rt2x00dev->tx_power) + return; + rt2x00_set_field32_nb(&rt2x00dev->rf3, RF3_TXPOWER, txpower); rt2x00_rf_write(rt2x00dev, rt2x00dev->rf3); + + rt2x00dev->tx_power = txpower; } static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, int antenna) @@ -460,6 +503,12 @@ u16 csr5_reg; u16 csr6_reg; + /* + * Only continue when there is something to be done. + */ + if (rt2x00dev->rx_params.antenna == antenna) + return; + rt2x00_bbp_read(rt2x00dev, 2, ®_tx); rt2x00_bbp_read(rt2x00dev, 14, ®_rx); rt2x00_register_read(rt2x00dev, PHY_CSR5, &csr5_reg); @@ -578,6 +627,12 @@ { struct ieee80211_rate *rate; + /* + * Only continue when there is something to be done. + */ + if (rt2x00dev->rx_params.phymode == phymode) + return; + if (phymode == MODE_IEEE80211A && rt2x00_rf(&rt2x00dev->chip, RF5222)) rate = &rt2x00dev->hw.modes[2].rates[ @@ -1819,12 +1874,17 @@ u16 reg; /* - * Some configuration changes require the RX to be disabled. + * Check if we need to disable the radio, + * if this is not the case, at least the RX must be disabled. */ if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - rt2x00_register_read(rt2x00dev, TXRX_CSR2, ®); - rt2x00_set_field16_nb(®, TXRX_CSR2_DISABLE_RX, 1); - rt2x00_register_write(rt2x00dev, TXRX_CSR2, reg); + if (!conf->radio_enabled) + rt2500usb_disable_radio(rt2x00dev); + else { + rt2x00_register_read(rt2x00dev, TXRX_CSR2, ®); + rt2x00_set_field16_nb(®, TXRX_CSR2_DISABLE_RX, 1); + rt2x00_register_write(rt2x00dev, TXRX_CSR2, reg); + } } rt2500usb_config_channel(rt2x00dev, @@ -1838,24 +1898,13 @@ /* * Reenable RX only if the radio should be on. */ - if (conf->radio_enabled) { - if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - if (rt2500usb_open(net_dev)) { - ERROR("Failed to enabled radio.\n"); - return; - } - } else { - rt2x00_register_read(rt2x00dev, TXRX_CSR2, ®); - rt2x00_set_field16_nb(®, TXRX_CSR2_DISABLE_RX, 0); - rt2x00_register_write(rt2x00dev, TXRX_CSR2, reg); - } - } else { - if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - if (rt2500usb_stop(net_dev)) { - ERROR("Failed to disable radio.\n"); - return; - } - } + if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { + rt2x00_register_read(rt2x00dev, TXRX_CSR2, ®); + rt2x00_set_field16_nb(®, TXRX_CSR2_DISABLE_RX, 0); + rt2x00_register_write(rt2x00dev, TXRX_CSR2, reg); + } else if (conf->radio_enabled) { + if (rt2500usb_enable_radio(rt2x00dev)) + return; } } @@ -1985,10 +2034,20 @@ { struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev); + /* + * Check if we are not busy with the previous + * passive scan request. + */ if (rt2x00dev->scan) return -EBUSY; /* + * Check if the radio is enabled. + */ + if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) + return -EIO; + + /* * Allocate scanning structure to store scanning info. */ rt2x00dev->scan = kmalloc(sizeof(struct scanning), GFP_ATOMIC); @@ -2241,6 +2300,9 @@ usb_get_intfdata(rt2x00dev_usb(rt2x00dev)); u16 eeprom[3] = { 0, 0, 0 }; + if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC)) + return 0; + /* * Read MAC address from EEPROM. */ @@ -2261,6 +2323,10 @@ net_dev->addr_len = 6; + if (!is_valid_ether_addr(&net_dev->dev_addr[0])) + return -EINVAL; + + SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC); return 0; } diff -rU3 wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt61pci.c wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt61pci.c --- wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt61pci.c 2006-07-26 10:56:17.000000000 +0200 +++ wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt61pci.c 2006-07-26 12:50:33.000000000 +0200 @@ -506,6 +506,14 @@ u32 reg; /* + * Only continue when there is something to be done. + */ + if (type == rt2x00dev->interface.type || + (rt2x00dev->interface.monitor_count ^ + GET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR))) + return; + + /* * Apply hardware packet filter. */ rt2x00_register_read(rt2x00dev, TXRX_CSR0, ®); @@ -554,7 +562,13 @@ /* * Update working mode. */ - rt2x00dev->interface.type = type; + if (type != IEEE80211_IF_TYPE_MNTR) + rt2x00dev->interface.type = type; + + if (rt2x00dev->interface.monitor_count) + SET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR); + else + CLEAR_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR); } static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev, @@ -565,6 +579,12 @@ u32 rf3 = 0; u32 rf4 = 0; + /* + * Only continue when there is something to be done. + */ + if (channel == rt2x00dev->rx_params.channel) + return; + if (txpower == 0xff) txpower = rt2x00dev->tx_power; txpower = TXPOWER_TO_DEV(txpower); @@ -735,14 +755,14 @@ } } - INFO("Switching channel. RF1: 0x%08x, RF2: 0x%08x, RF3: 0x%08x, " - "RF4: 0x%08x.\n", rf1, rf2, rf3, rf4); - /* * Set TXpower. */ rt2x00_set_field32(&rf3, RF3_TXPOWER, txpower); + INFO("Switching channel. RF1: 0x%08x, RF2: 0x%08x, RF3: 0x%08x, " + "RF4: 0x%08x.\n", rf1, rf2, rf3, rf4); + /* * Set Frequency offset. */ @@ -782,12 +802,28 @@ */ rt2x00dev->rx_params.freq = freq; rt2x00dev->rx_params.channel = channel; + + rt2x00dev->tx_power = txpower; + + /* + * Update rf fields + */ + rt2x00dev->rf1 = rf1; + rt2x00dev->rf2 = rf2; + rt2x00dev->rf3 = rf3; + rt2x00dev->rf4 = rf4; } static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower) { txpower = TXPOWER_TO_DEV(txpower); + /* + * Only continue when there is something to be done. + */ + if (txpower == rt2x00dev->tx_power) + return; + rt2x00_set_field32(&rt2x00dev->rf3, RF3_TXPOWER, txpower); rt2x00_rf_write(rt2x00dev, rt2x00dev->rf1); @@ -808,6 +844,8 @@ rt2x00_rf_write(rt2x00dev, rt2x00dev->rf2); rt2x00_rf_write(rt2x00dev, rt2x00dev->rf3 & ~cpu_to_le32(0x00000004)); rt2x00_rf_write(rt2x00dev, rt2x00dev->rf4); + + rt2x00dev->tx_power = txpower; } static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev, @@ -819,6 +857,12 @@ u8 reg_r77; u8 frame_type; + /* + * Only continue when there is something to be done. + */ + if (rt2x00dev->rx_params.antenna == antenna) + return; + rt2x00_register_read(rt2x00dev, PHY_CSR0, ®); if (phymode == MODE_IEEE80211A) { @@ -997,6 +1041,12 @@ { struct ieee80211_rate *rate; + /* + * Only continue when there is something to be done. + */ + if (rt2x00dev->rx_params.phymode == phymode) + return; + if (phymode == MODE_IEEE80211A && (rt2x00_rf(&rt2x00dev->chip, RF5225) || rt2x00_rf(&rt2x00dev->chip, RF5325))) @@ -2400,6 +2450,9 @@ if (!reg) return IRQ_NONE; + if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) + return IRQ_HANDLED; + /* * Handle interrupts, walk through all bits * and run the tasks, the bits are checked in order of @@ -2632,12 +2685,17 @@ u32 reg; /* - * Some configuration changes require the RX to be disabled. + * Check if we need to disable the radio, + * if this is not the case, at least the RX must be disabled. */ if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - rt2x00_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1); - rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg); + if (!conf->radio_enabled) + rt61pci_disable_radio(rt2x00dev); + else { + rt2x00_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1); + rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg); + } } rt61pci_config_channel(rt2x00dev, @@ -2651,24 +2709,13 @@ /* * Reenable RX only if the radio should be on. */ - if (conf->radio_enabled) { - if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - if (rt61pci_open(net_dev)) { - ERROR("Failed to enabled radio.\n"); - return; - } - } else { - rt2x00_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); - rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg); - } - } else { - if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - if (rt61pci_stop(net_dev)) { - ERROR("Failed to disable radio.\n"); - return; - } - } + if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { + rt2x00_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); + rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg); + } else if (conf->radio_enabled) { + if (rt61pci_enable_radio(rt2x00dev)) + return; } } @@ -2788,10 +2835,20 @@ { struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev); + /* + * Check if we are not busy with the previous + * passive scan request. + */ if (rt2x00dev->scan) return -EBUSY; /* + * Check if the radio is enabled. + */ + if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) + return -EIO; + + /* * Allocate scanning structure to store scanning info. */ rt2x00dev->scan = kmalloc(sizeof(struct scanning), GFP_ATOMIC); @@ -3143,7 +3200,10 @@ static int rt61pci_init_mac(struct rt2x00_dev *rt2x00dev) { struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev)); - u16 eeprom[3]; + u16 eeprom[3] = { 0, 0, 0 }; + + if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC)) + return 0; /* * Read MAC address from EEPROM. @@ -3165,6 +3225,10 @@ net_dev->addr_len = 6; + if (!is_valid_ether_addr(&net_dev->dev_addr[0])) + return -EINVAL; + + SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC); return 0; } diff -rU3 wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt73usb.c wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt73usb.c --- wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt73usb.c 2006-07-26 10:56:20.000000000 +0200 +++ wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt73usb.c 2006-07-26 12:50:39.000000000 +0200 @@ -327,6 +327,14 @@ u32 reg; /* + * Only continue when there is something to be done. + */ + if (type == rt2x00dev->interface.type || + (rt2x00dev->interface.monitor_count ^ + GET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR))) + return; + + /* * Apply hardware packet filter. */ rt2x00_register_read(rt2x00dev, TXRX_CSR0, ®); @@ -375,7 +383,13 @@ /* * Update working mode. */ - rt2x00dev->interface.type = type; + if (type != IEEE80211_IF_TYPE_MNTR) + rt2x00dev->interface.type = type; + + if (rt2x00dev->interface.monitor_count) + SET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR); + else + CLEAR_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR); } static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev, @@ -386,6 +400,12 @@ u32 rf3 = rt2x00dev->rf3; u32 rf4 = 0; + /* + * Only continue when there is something to be done. + */ + if (channel == rt2x00dev->rx_params.channel) + return; + if (txpower == 0xff) txpower = rt2x00dev->tx_power; txpower = TXPOWER_TO_DEV(txpower); @@ -463,14 +483,14 @@ rt2x00_rf(&rt2x00dev->chip, RF5225)) rf4 |= 0x00010000; - INFO("Switching channel. RF1: 0x%08x, RF2: 0x%08x, RF3: 0x%08x, " - "RF4: 0x%08x.\n", rf1, rf2, rf3, rf4); - /* * Set TXpower. */ rt2x00_set_field32(&rf3, RF3_TXPOWER, txpower); + INFO("Switching channel. RF1: 0x%08x, RF2: 0x%08x, RF3: 0x%08x, " + "RF4: 0x%08x.\n", rf1, rf2, rf3, rf4); + /* * Set Frequency offset. */ @@ -506,12 +526,30 @@ */ rt2x00dev->rx_params.freq = freq; rt2x00dev->rx_params.channel = channel; + + rt2x00dev->tx_power = txpower; + + /* + * Update rf fields + */ + rt2x00dev->rf1 = rf1; + rt2x00dev->rf2 = rf2; + rt2x00dev->rf3 = rf3; + rt2x00dev->rf4 = rf4; + + rt2x00dev->tx_power = txpower; } static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower) { txpower = TXPOWER_TO_DEV(txpower); + /* + * Only continue when there is something to be done. + */ + if (txpower == rt2x00dev->tx_power) + return; + rt2x00_set_field32(&rt2x00dev->rf3, RF3_TXPOWER, txpower); rt2x00_rf_write(rt2x00dev, rt2x00dev->rf1); @@ -528,6 +566,8 @@ rt2x00_rf_write(rt2x00dev, rt2x00dev->rf2); rt2x00_rf_write(rt2x00dev, rt2x00dev->rf3 & ~cpu_to_le32(0x00000004)); rt2x00_rf_write(rt2x00dev, rt2x00dev->rf4); + + rt2x00dev->tx_power = txpower; } static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev, @@ -539,6 +579,12 @@ u8 reg_r77; u8 frame_type; + /* + * Only continue when there is something to be done. + */ + if (rt2x00dev->rx_params.antenna == antenna) + return; + rt2x00_register_read(rt2x00dev, PHY_CSR0, ®); if (phymode == MODE_IEEE80211A) { @@ -711,6 +757,12 @@ { struct ieee80211_rate *rate; + /* + * Only continue when there is something to be done. + */ + if (rt2x00dev->rx_params.phymode == phymode) + return; + if (phymode == MODE_IEEE80211A && (rt2x00_rf(&rt2x00dev->chip, RF5225) || rt2x00_rf(&rt2x00dev->chip, RF5226))) @@ -2133,12 +2185,17 @@ u32 reg; /* - * Some configuration changes require the RX to be disabled. + * Check if we need to disable the radio, + * if this is not the case, at least the RX must be disabled. */ if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - rt2x00_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1); - rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg); + if (!conf->radio_enabled) + rt73usb_disable_radio(rt2x00dev); + else { + rt2x00_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1); + rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg); + } } rt73usb_config_channel(rt2x00dev, @@ -2150,29 +2207,15 @@ rt73usb_config_phymode(rt2x00dev, conf->phymode); /* - * Reenable RX. - */ - /* * Reenable RX only if the radio should be on. */ - if (conf->radio_enabled) { - if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - if (rt73usb_open(net_dev)) { - ERROR("Failed to enabled radio.\n"); - return; - } - } else { - rt2x00_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); - rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg); - } - } else { - if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { - if (rt73usb_stop(net_dev)) { - ERROR("Failed to disable radio.\n"); - return; - } - } + if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) { + rt2x00_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); + rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg); + } else if (conf->radio_enabled) { + if (rt73usb_enable_radio(rt2x00dev)) + return; } } @@ -2302,10 +2345,20 @@ { struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev); + /* + * Check if we are not busy with the previous + * passive scan request. + */ if (rt2x00dev->scan) return -EBUSY; /* + * Check if the radio is enabled. + */ + if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) + return -EIO; + + /* * Allocate scanning structure to store scanning info. */ rt2x00dev->scan = kmalloc(sizeof(struct scanning), GFP_ATOMIC); @@ -2640,6 +2693,9 @@ usb_get_intfdata(rt2x00dev_usb(rt2x00dev)); u16 eeprom[3] = { 0, 0, 0 }; + if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC)) + return 0; + /* * Read MAC address from EEPROM. */ @@ -2660,6 +2716,10 @@ net_dev->addr_len = 6; + if (!is_valid_ether_addr(&net_dev->dev_addr[0])) + return -EINVAL; + + SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC); return 0; } - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html