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);
pgpToGdXZPhu4.pgp
Description: PGP signature