All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 31/32] rt2x00: Correctly initialization and uninitialization of device
@ 2006-04-27 22:03 Ivo van Doorn
  0 siblings, 0 replies; only message in thread
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- 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 --]

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2006-04-27 22:02 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-04-27 22:03 [PATCH 31/32] rt2x00: Correctly initialization and uninitialization of device Ivo van Doorn

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.