All of lore.kernel.org
 help / color / mirror / Atom feed
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.