From: Ivo van Doorn <ivdoorn@gmail.com>
To: netdev@vger.kernel.org
Cc: rt2x00-devel@lfcorreia.dyndns.org
Subject: [PATCH 31/32] rt2x00: Correctly initialization and uninitialization of device
Date: Fri, 28 Apr 2006 00:03:20 +0200 [thread overview]
Message-ID: <200604280003.21404.IvDoorn@gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 12718 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
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 <IvDoorn@gmail.com>
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 #2: Type: application/pgp-signature, Size: 189 bytes --]
reply other threads:[~2006-04-27 22:02 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200604280003.21404.IvDoorn@gmail.com \
--to=ivdoorn@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=rt2x00-devel@lfcorreia.dyndns.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.