>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, &reg);
@@ -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, &reg_rx);
        rt2x00_bbp_read(rt2x00dev, 1, &reg_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, &reg);
-               rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
-               rt2x00_register_write(rt2x00dev, RXCSR0, reg);
+               if (!conf->radio_enabled)
+                       rt2400pci_disable_radio(rt2x00dev);
+               else {
+                       rt2x00_register_read(rt2x00dev, RXCSR0, &reg);
+                       rt2x00_set_field32(&reg, 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, &reg);
-                       rt2x00_set_field32(&reg, 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, &reg);
+               rt2x00_set_field32(&reg, 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, &reg[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, &reg);
@@ -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, &reg);
        rt2x00_bbp_read(rt2x00dev, 14, &reg_rx);
        rt2x00_bbp_read(rt2x00dev, 2, &reg_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, &reg);
-               rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
-               rt2x00_register_write(rt2x00dev, RXCSR0, reg);
+               if (!conf->radio_enabled)
+                       rt2500pci_disable_radio(rt2x00dev);
+               else {
+                       rt2x00_register_read(rt2x00dev, RXCSR0, &reg);
+                       rt2x00_set_field32(&reg, 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, &reg);
-                       rt2x00_set_field32(&reg, 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, &reg);
+               rt2x00_set_field32(&reg, 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, &reg[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, &reg);
@@ -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, &reg_tx);
        rt2x00_bbp_read(rt2x00dev, 14, &reg_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, &reg);
-               rt2x00_set_field16_nb(&reg, 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, &reg);
+                       rt2x00_set_field16_nb(&reg, 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, &reg);
-                       rt2x00_set_field16_nb(&reg, 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, &reg);
+               rt2x00_set_field16_nb(&reg, 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, &reg);
@@ -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, &reg);
 
        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, &reg);
-               rt2x00_set_field32(&reg, 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, &reg);
+                       rt2x00_set_field32(&reg, 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, &reg);
-                       rt2x00_set_field32(&reg, 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, &reg);
+               rt2x00_set_field32(&reg, 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, &reg);
@@ -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, &reg);
 
        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, &reg);
-               rt2x00_set_field32(&reg, 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, &reg);
+                       rt2x00_set_field32(&reg, 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, &reg);
-                       rt2x00_set_field32(&reg, 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, &reg);
+               rt2x00_set_field32(&reg, 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

Reply via email to