rt2x00: Correctly initialization and uninitialization of device
Subsystems (3)
PATCH 31/32 rt2x00: Correctly initialization and uninitialization of device
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]>
drivers/net/wireless/d80211/rt2x00/rt2400pci.c +34 -23
@@ -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 *pciif (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_devicestruct 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);
drivers/net/wireless/d80211/rt2x00/rt2500pci.c +46 -31
160 lines not on this page · raw message
drivers/net/wireless/d80211/rt2x00/rt2500usb.c +46 -33
154 lines not on this page · raw message