From: Ivo van Doorn <[EMAIL PROTECTED]>

Fix several hardware initialization and uninitalization
problems by incorrectly flushing workqueues.
Fix the memory leak when freeing the ieee80211_hw structure.
Allow device to connect to 802.11g networks by default
instead of 802.11b.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c  
2006-04-27 22:05:21.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c    
2006-04-27 22:05:52.000000000 +0200
@@ -1719,6 +1719,11 @@ rt2400pci_stop(struct net_device *net_de
        }
 
        /*
+        * Flush out all pending work.
+        */
+       flush_workqueue(rt2x00pci->workqueue);
+
+       /*
         * Free DMA rings.
         */
        rt2400pci_free_rings(rt2x00pci);
@@ -2441,7 +2446,7 @@ rt2400pci_initialize(struct pci_dev *pci
 
        rt2x00pci->workqueue = create_singlethread_workqueue(DRV_NAME);
        if (!rt2x00pci->workqueue)
-               goto exit_iounmap;
+               goto exit;
 
        /*
         * Initialize cofniguration work.
@@ -2457,21 +2462,25 @@ rt2400pci_initialize(struct pci_dev *pci
        if (rt2400pci_init_eeprom(rt2x00pci)
        || rt2400pci_init_mac(rt2x00pci)
        || rt2400pci_init_hw(rt2x00pci))
-               goto exit_destroy_workqueue;
+               goto exit;
 
        /*
         * If required start hardware button polling.
         */
        rt2x00pci_button_start(rt2x00pci, rt2400pci_button_poll);
 
-       return 0;
+       /*
+        * Register hardware.
+        */
+       if (ieee80211_register_hw(net_dev, &rt2x00pci->hw)) {
+               ERROR("Failed to register device.\n");
+               goto exit;
+       }
 
-exit_destroy_workqueue:
-       destroy_workqueue(rt2x00pci->workqueue);
+       return 0;
 
-exit_iounmap:
-       iounmap(rt2x00pci->csr_addr);
-       rt2x00pci->csr_addr = NULL;
+exit:
+       rt2400pci_uninitialize(net_dev);
 
        return -ENODEV;
 }
@@ -2482,26 +2491,39 @@ rt2400pci_uninitialize(struct net_device
        struct rt2x00_pci       *rt2x00pci = ieee80211_dev_hw_data(net_dev);
 
        /*
+        * Unregister hardware.
+        */
+       ieee80211_unregister_hw(net_dev);
+
+       /*
         * Shutdown poll_timer for hardware button.
         */
        rt2x00pci_button_stop(rt2x00pci);
 
        kfree(rt2x00pci->eeprom);
 
+       /*
+        * Release CSR memory.
+        */
        if (likely(rt2x00pci->csr_addr)) {
                iounmap(rt2x00pci->csr_addr);
                rt2x00pci->csr_addr = NULL;
        }
 
+       /*
+        * Free workqueue.
+        */
        if (likely(rt2x00pci->workqueue)) {
-               flush_workqueue(rt2x00pci->workqueue);
                destroy_workqueue(rt2x00pci->workqueue);
                rt2x00pci->workqueue = NULL;
        }
 
+       /*
+        * Free ieee80211_hw memory.
+        */
        if (likely(rt2x00pci->hw.modes)) {
-                       kfree(rt2x00pci->hw.modes->channels);
-                       kfree(rt2x00pci->hw.modes->rates);
+               kfree(rt2x00pci->hw.modes->channels);
+               kfree(rt2x00pci->hw.modes->rates);
                kfree(rt2x00pci->hw.modes);
                rt2x00pci->hw.modes = NULL;
        }
@@ -2514,7 +2536,6 @@ static int
 rt2400pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 {
        struct net_device       *net_dev;
-       struct rt2x00_pci       *rt2x00pci;
        int                     status;
 
        if (unlikely(id->driver_data != RT2460)) {
@@ -2559,19 +2580,9 @@ rt2400pci_probe(struct pci_dev *pci_dev,
                ERROR("Failed to initialize device.\n");
                goto exit_free_device;
        }
-       rt2x00pci = ieee80211_dev_hw_data(net_dev);
-
-       status = ieee80211_register_hw(net_dev, &rt2x00pci->hw);
-       if (status) {
-               ERROR("Failed to register device.\n");
-               goto exit_uninitialize_device;
-       }
 
        return 0;
 
-exit_uninitialize_device:
-       rt2400pci_uninitialize(net_dev);
-
 exit_free_device:
        ieee80211_free_hw(net_dev);
 
@@ -2592,7 +2603,7 @@ rt2400pci_remove(struct pci_dev *pci_dev
 {
        struct net_device       *net_dev = pci_get_drvdata(pci_dev);
 
-       ieee80211_unregister_hw(net_dev);
+       net_dev->stop(net_dev);
 
        rt2400pci_uninitialize(net_dev);
 
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c  
2006-04-27 22:05:21.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c    
2006-04-27 22:05:52.000000000 +0200
@@ -1845,6 +1845,11 @@ rt2500pci_stop(struct net_device *net_de
        }
 
        /*
+        * Flush out all pending work.
+        */
+       flush_workqueue(rt2x00pci->workqueue);
+
+       /*
         * Free DMA rings.
         */
        rt2500pci_free_rings(rt2x00pci);
@@ -2675,22 +2680,22 @@ rt2500pci_init_hw(struct rt2x00_pci *rt2
        }
 
        /*
-        * Intitialize 802.11b
-        * Rates: CCK.
+        * Intitialize 802.11g
+        * Rates: CCK, OFDM.
         * Channels: OFDM.
         */
-       hw->modes[0].mode = MODE_IEEE80211B;
+       hw->modes[0].mode = MODE_IEEE80211G;
        hw->modes[0].num_channels = 14;
-       hw->modes[0].num_rates = 4;
+       hw->modes[0].num_rates = 12;
 
        /*
-        * Intitialize 802.11g
-        * Rates: CCK, OFDM.
+        * Intitialize 802.11b
+        * Rates: CCK.
         * Channels: OFDM.
         */
-       hw->modes[1].mode = MODE_IEEE80211G;
+       hw->modes[1].mode = MODE_IEEE80211B;
        hw->modes[1].num_channels = 14;
-       hw->modes[1].num_rates = 12;
+       hw->modes[1].num_rates = 4;
        hw->modes[1].channels = hw->modes[0].channels;
        hw->modes[1].rates = hw->modes[0].rates;
 
@@ -2747,7 +2752,7 @@ rt2500pci_initialize(struct pci_dev *pci
 
        rt2x00pci->workqueue = create_singlethread_workqueue(DRV_NAME);
        if (!rt2x00pci->workqueue)
-               goto exit_iounmap;
+               goto exit;
 
        /*
         * Initialize cofniguration work.
@@ -2763,21 +2768,25 @@ rt2500pci_initialize(struct pci_dev *pci
        if (rt2500pci_init_eeprom(rt2x00pci)
        || rt2500pci_init_mac(rt2x00pci)
        || rt2500pci_init_hw(rt2x00pci))
-               goto exit_destroy_workqueue;
+               goto exit;
 
        /*
         * If required start hardware button polling.
         */
        rt2x00pci_button_start(rt2x00pci, rt2500pci_button_poll);
 
-       return 0;
+       /*
+        * Register hardware.
+        */
+       if (ieee80211_register_hw(net_dev, &rt2x00pci->hw)) {
+               ERROR("Failed to register device.\n");
+               goto exit;
+       }
 
-exit_destroy_workqueue:
-       destroy_workqueue(rt2x00pci->workqueue);
+       return 0;
 
-exit_iounmap:
-       iounmap(rt2x00pci->csr_addr);
-       rt2x00pci->csr_addr = NULL;
+exit:
+       rt2500pci_uninitialize(net_dev);
 
        return -ENODEV;
 }
@@ -2788,25 +2797,42 @@ rt2500pci_uninitialize(struct net_device
        struct rt2x00_pci       *rt2x00pci = ieee80211_dev_hw_data(net_dev);
 
        /*
+        * Unregister hardware.
+        */
+       ieee80211_unregister_hw(net_dev);
+
+       /*
         * Shutdown poll_timer for hardware button.
         */
        rt2x00pci_button_stop(rt2x00pci);
 
        kfree(rt2x00pci->eeprom);
 
+       /*
+        * Release CSR memory.
+        */
        if (likely(rt2x00pci->csr_addr)) {
                iounmap(rt2x00pci->csr_addr);
                rt2x00pci->csr_addr = NULL;
        }
 
+       /*
+        * Free workqueue.
+        */
        if (likely(rt2x00pci->workqueue)) {
-               flush_workqueue(rt2x00pci->workqueue);
                destroy_workqueue(rt2x00pci->workqueue);
                rt2x00pci->workqueue = NULL;
        }
 
-       kfree(rt2x00pci->hw.modes);
-       rt2x00pci->hw.modes = NULL;
+       /*
+        * Free ieee80211_hw memory.
+        */
+       if (likely(rt2x00pci->hw.modes)) {
+               kfree(rt2x00pci->hw.modes->channels);
+               kfree(rt2x00pci->hw.modes->rates);
+               kfree(rt2x00pci->hw.modes);
+               rt2x00pci->hw.modes = NULL;
+       }
 }
 
 /*
@@ -2816,7 +2842,6 @@ static int
 rt2500pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 {
        struct net_device       *net_dev;
-       struct rt2x00_pci       *rt2x00pci;
        int                     status;
 
        if (unlikely(id->driver_data != RT2560)) {
@@ -2861,19 +2886,9 @@ rt2500pci_probe(struct pci_dev *pci_dev,
                ERROR("Failed to initialize device.\n");
                goto exit_free_device;
        }
-       rt2x00pci = ieee80211_dev_hw_data(net_dev);
-
-       status = ieee80211_register_hw(net_dev, &rt2x00pci->hw);
-       if (status) {
-               ERROR("Failed to register device.\n");
-               goto exit_uninitialize_device;
-       }
 
        return 0;
 
-exit_uninitialize_device:
-       rt2500pci_uninitialize(net_dev);
-
 exit_free_device:
        ieee80211_free_hw(net_dev);
 
@@ -2894,7 +2909,7 @@ rt2500pci_remove(struct pci_dev *pci_dev
 {
        struct net_device       *net_dev = pci_get_drvdata(pci_dev);
 
-       ieee80211_unregister_hw(net_dev);
+       net_dev->stop(net_dev);
 
        rt2500pci_uninitialize(net_dev);
 
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c  
2006-04-27 22:05:21.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c    
2006-04-27 22:05:52.000000000 +0200
@@ -1480,8 +1480,6 @@ static int
 rt2500usb_stop(struct net_device *net_dev)
 {
        struct rt2x00_usb       *rt2x00usb = ieee80211_dev_hw_data(net_dev);
-       struct data_entry       *entry;
-       int                     counter;
        u16                     reg;
 
        CLEAR_FLAG(rt2x00usb, RADIO_ENABLED);
@@ -1498,11 +1496,6 @@ rt2500usb_stop(struct net_device *net_de
         */
        rt2500usb_disable_led(rt2x00usb);
 
-       entry = (struct data_entry*)rt2x00usb->ring[RING_RX].entry;
-       for (counter = 0; counter < rt2x00usb->ring[RING_RX].stats.limit; 
counter++) {
-               usb_kill_urb(entry[counter].urb);
-       }
-
        rt2x00_vendor_request(rt2x00usb, USB_RX_CONTROL,
                USB_VENDOR_REQUEST_OUT, 0x00, 0x00, NULL, 0);
 
@@ -1518,6 +1511,11 @@ rt2500usb_stop(struct net_device *net_de
        }
 
        /*
+        * Flush out all pending work.
+        */
+       flush_workqueue(rt2x00usb->workqueue);
+
+       /*
         * Free DMA rings.
         */
        rt2500usb_free_rings(rt2x00usb);
@@ -2296,22 +2294,23 @@ rt2500usb_init_hw(struct rt2x00_usb *rt2
        }
 
        /*
-        * Intitialize 802.11b
-        * Rates: CCK.
+        * Intitialize 802.11g
+        * Rates: CCK, OFDM.
         * Channels: OFDM.
         */
-       hw->modes[0].mode = MODE_IEEE80211B;
+       hw->modes[0].mode = MODE_IEEE80211G;
        hw->modes[0].num_channels = 14;
-       hw->modes[0].num_rates = 4;
+       hw->modes[0].num_rates = 12;
+
 
        /*
-        * Intitialize 802.11g
-        * Rates: CCK, OFDM.
+        * Intitialize 802.11b
+        * Rates: CCK.
         * Channels: OFDM.
         */
-       hw->modes[1].mode = MODE_IEEE80211G;
+       hw->modes[1].mode = MODE_IEEE80211B;
        hw->modes[1].num_channels = 14;
-       hw->modes[1].num_rates = 12;
+       hw->modes[1].num_rates = 4;
        hw->modes[1].channels = hw->modes[0].channels;
        hw->modes[1].rates = hw->modes[0].rates;
 
@@ -2376,12 +2375,23 @@ rt2500usb_initialize(struct usb_interfac
 
        if (rt2500usb_init_eeprom(rt2x00usb)
        || rt2500usb_init_mac(rt2x00usb)
-       || rt2500usb_init_hw(rt2x00usb)) {
-               destroy_workqueue(rt2x00usb->workqueue);
-               return -ENODEV;
+       || rt2500usb_init_hw(rt2x00usb))
+               goto exit;
+
+       /*
+        * Register hardware.
+        */
+       if (ieee80211_register_hw(net_dev, &rt2x00usb->hw)) {
+               ERROR("Failed to register device.\n");
+               goto exit;
        }
 
        return 0;
+
+exit:
+       rt2500usb_uninitialize(net_dev);
+
+       return -ENODEV;
 }
 
 static void
@@ -2389,16 +2399,30 @@ rt2500usb_uninitialize(struct net_device
 {
        struct rt2x00_usb       *rt2x00usb = ieee80211_dev_hw_data(net_dev);
 
+       /*
+        * Unregister hardware.
+        */
+       ieee80211_unregister_hw(net_dev);
+
        kfree(rt2x00usb->eeprom);
 
+       /*
+        * Free workqueue.
+        */
        if (likely(rt2x00usb->workqueue)) {
-               flush_workqueue(rt2x00usb->workqueue);
                destroy_workqueue(rt2x00usb->workqueue);
                rt2x00usb->workqueue = NULL;
        }
 
-       kfree(rt2x00usb->hw.modes);
-       rt2x00usb->hw.modes = NULL;
+       /*
+        * Free ieee80211_hw memory.
+        */
+       if (likely(rt2x00usb->hw.modes)) {
+               kfree(rt2x00usb->hw.modes->channels);
+               kfree(rt2x00usb->hw.modes->rates);
+               kfree(rt2x00usb->hw.modes);
+               rt2x00usb->hw.modes = NULL;
+       }
 }
 
 /*
@@ -2409,7 +2433,6 @@ rt2500usb_probe(struct usb_interface *us
 {
        struct usb_device       *usb_dev = interface_to_usbdev(usb_intf);
        struct net_device       *net_dev;
-       struct rt2x00_usb       *rt2x00usb;
        int                     status;
 
        if (unlikely(id->driver_info != RT2570)) {
@@ -2433,19 +2456,9 @@ rt2500usb_probe(struct usb_interface *us
                ERROR("Failed to initialize device.\n");
                goto exit_free_device;
        }
-       rt2x00usb = ieee80211_dev_hw_data(net_dev);
-
-       status = ieee80211_register_hw(net_dev, &rt2x00usb->hw);
-       if (status) {
-               ERROR("Failed to register device.\n");
-               goto exit_uninitialize_device;
-       }
 
        return 0;
 
-exit_uninitialize_device:
-       rt2500usb_uninitialize(net_dev);
-
 exit_free_device:
        ieee80211_free_hw(net_dev);
 
@@ -2460,7 +2473,7 @@ rt2500usb_disconnect(struct usb_interfac
 {
        struct net_device       *net_dev = usb_get_intfdata(usb_intf);
 
-       ieee80211_unregister_hw(net_dev);
+       net_dev->stop(net_dev);
 
        rt2500usb_uninitialize(net_dev);
 

Attachment: pgpToGdXZPhu4.pgp
Description: PGP signature

Reply via email to