Netdev List
 help / color / mirror / Atom feed
* [PATCH 12/32] rt2x00: Add USB ID's
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 1692 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Remove the rt73usb ID that accidently sneaked into
rt2500usb. And add new rt2500usb ID's.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>

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 21:42:29.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:44:33.000000000 +0200
@@ -2192,6 +2192,7 @@ static struct usb_device_id rt2500usb_de
 	{ USB_DEVICE(0x0b05, 0x1707), .driver_info = RT2570},
 	/* Belkin */
 	{ USB_DEVICE(0x050d, 0x7050), .driver_info = RT2570},
+	{ USB_DEVICE(0x050d, 0x7051), .driver_info = RT2570},
 	{ USB_DEVICE(0x050d, 0x705a), .driver_info = RT2570},
 	/* Cisco Systems */
 	{ USB_DEVICE(0x13b1, 0x000d), .driver_info = RT2570},
@@ -2201,7 +2202,6 @@ static struct usb_device_id rt2500usb_de
 	{ USB_DEVICE(0x14b2, 0x3c02), .driver_info = RT2570},
 	/* D-LINK */
 	{ USB_DEVICE(0x2001, 0x3c00), .driver_info = RT2570},
-	{ USB_DEVICE(0x07d1, 0x3c03), .driver_info = RT2570},
 	/* Gigabyte */
 	{ USB_DEVICE(0x1044, 0x8001), .driver_info = RT2570},
 	{ USB_DEVICE(0x1044, 0x8007), .driver_info = RT2570},
@@ -2224,6 +2224,10 @@ static struct usb_device_id rt2500usb_de
 	{ USB_DEVICE(0x0707, 0xee13), .driver_info = RT2570},
 	/* Spairon */
 	{ USB_DEVICE(0x114b, 0x0110), .driver_info = RT2570},
+	/* Trust */
+	{ USB_DEVICE(0x0eb0, 0x9020), .driver_info = RT2570},
+	/* Zinwell */
+	{ USB_DEVICE(0x5a57, 0x0260), .driver_info = RT2570},
 	{0,}
 };
 

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 13/32] rt2x00: Tune link depending on link quality
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 7739 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Add link tuning capabilities, and call this function
every time the rxdone handler has finished.

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 21:42:29.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 21:45:08.000000000 +0200
@@ -618,6 +618,41 @@ rt2400pci_config_rate(struct rt2x00_pci 
 }
 
 /*
+ * Link tuning
+ */
+static void
+rt2400pci_link_tuner(struct rt2x00_pci *rt2x00pci)
+{
+	u8			reg;
+	char			false_cca_delta;
+
+	/*
+	 * Read false CCA counter.
+	 */
+	rt2x00_bbp_read(rt2x00pci, 39, &reg);
+
+	/*
+	 * Determine difference with previous CCA counter.
+	 */
+	false_cca_delta = reg - rt2x00pci->false_cca;
+	rt2x00pci->false_cca = reg;
+
+	/*
+	 * Check if the difference is higher than the
+	 * threshold and if so, tune the link.
+	 */
+	if (false_cca_delta >= 8) {
+		/*
+		 * Read and update RX AGC VGC.
+		 */
+		rt2x00_bbp_read(rt2x00pci, 13, &reg);
+		reg += 2;
+		if (reg < 0x20)
+			rt2x00_bbp_write(rt2x00pci, 13, reg);
+	}
+}
+
+/*
  * TX descriptor initialization
  */
 static void
@@ -779,6 +814,9 @@ rt2400pci_rxdone(void *data)
 
 			memcpy(skb_put(skb, size), entry->data_addr, size);
 
+			ring->params.rx.ssi =
+				rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
+
 			__ieee80211_rx(net_dev, skb, &ring->params.rx);
 		}
 
@@ -786,6 +824,11 @@ rt2400pci_rxdone(void *data)
 
 		rt2x00_ring_index_inc(&rt2x00pci->rx);
 	}
+
+	/*
+	 * Tune link for optimal performance.
+	 */
+	rt2400pci_link_tuner(rt2x00pci);
 }
 
 static void
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h	2006-04-27 21:36:19.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h	2006-04-27 21:45:08.000000000 +0200
@@ -926,6 +926,11 @@ struct rt2x00_pci{
 	struct workqueue_struct		*workqueue;
 
 	/*
+	 * False CCA count.
+	 */
+	int					false_cca;
+
+	/*
 	 * EEPROM bus width.
 	 */
 	u8					eeprom_width;
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 21:42:29.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 21:45:08.000000000 +0200
@@ -661,6 +661,51 @@ rt2500pci_config_rate(struct rt2x00_pci 
 }
 
 /*
+ * Link tuning
+ */
+static void
+rt2500pci_link_tuner(struct rt2x00_pci *rt2x00pci, char rssi)
+{
+	u32			reg;
+	u8			reg_r17;
+
+	/*
+	 * Don't perform any tuning during scan.
+	 */
+	if (rt2x00pci->scan)
+		return;
+
+	rt2x00_register_read(rt2x00pci, CSR0, &reg);
+	rt2x00_bbp_read(rt2x00pci, 17, &reg_r17);
+
+	if (reg < RT2560_VERSION_D)
+		goto dynamic_cca_tune;
+
+	if (rssi < 40) {
+		if (reg_r17 >= 0x41)
+			rt2x00_bbp_write(rt2x00pci, 17, reg_r17);
+		return;
+	} else if (rssi >= 62) {
+		if (reg_r17 != 0x50)
+			rt2x00_bbp_write(rt2x00pci, 17, 0x50);
+		return;
+	} else if (reg_r17 >= 0x41) {
+		rt2x00_bbp_write(rt2x00pci, 17, reg_r17);
+		return;
+	}
+
+dynamic_cca_tune:
+	rt2x00_register_read(rt2x00pci, CNT3, &reg);
+
+	reg = rt2x00_get_field32(reg, CNT3_FALSE_CCA);
+
+	if (reg > 512 && reg_r17 < 0x40)
+		rt2x00_bbp_write(rt2x00pci, 17, ++reg_r17);
+	else if (reg < 100 && reg_r17 > 0x32)
+		rt2x00_bbp_write(rt2x00pci, 17, --reg_r17);
+}
+
+/*
  * TX descriptor initialization
  */
 static void
@@ -819,6 +864,14 @@ rt2500pci_rxdone(void *data)
 	struct sk_buff		*skb;
 	struct rxd		*rxd;
 	u16			size;
+	u8			rssi_count;
+	char			total_rssi;
+
+	/*
+	 * Initialize variable for average RSSI calculation.
+	 */
+	rssi_count = 0;
+	total_rssi = 0;
 
 	while (1) {
 		entry = rt2x00_get_data_entry(ring);
@@ -843,12 +896,24 @@ rt2500pci_rxdone(void *data)
 
 			memcpy(skb_put(skb, size), entry->data_addr, size);
 
+			ring->params.rx.ssi =
+				rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
+
 			__ieee80211_rx(net_dev, skb, &ring->params.rx);
+
+			rssi_count++;
+			total_rssi += ring->params.rx.ssi;
 		}
 		rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
 
 		rt2x00_ring_index_inc(&rt2x00pci->rx);
 	}
+
+	/*
+	 * Tune link for optimal performance.
+	 */
+	if (total_rssi && rssi_count)
+		rt2500pci_link_tuner(rt2x00pci, total_rssi / rssi_count);
 }
 
 static void
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 21:44:33.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:45:08.000000000 +0200
@@ -485,6 +485,68 @@ rt2500usb_config_rate(struct rt2x00_usb 
 }
 
 /*
+ * Link tuning
+ */
+static void
+rt2500usb_link_tuner(struct rt2x00_usb *rt2x00usb, char rssi)
+{
+	u16			reg;
+	u8			reg_r17;
+	u8			up_bound;
+	u8			low_bound;
+
+	/*
+	 * Don't perform any tuning during scan.
+	 */
+	if (rt2x00usb->scan)
+		return;
+
+	low_bound = 0x32;
+	if (rssi >= 43)
+		up_bound = 0x40;
+	else
+		up_bound = 0x40 - (43 - rssi);
+	if (up_bound < low_bound)
+		up_bound = low_bound;
+
+	if (rssi > 75) {
+		rt2x00_bbp_write(rt2x00usb, 24, 0x70);
+		rt2x00_bbp_write(rt2x00usb, 25, 0x40);
+		rt2x00_bbp_write(rt2x00usb, 61, 0x6d);
+	} else {
+		rt2x00_bbp_write(rt2x00usb, 24, 0x80);
+		rt2x00_bbp_write(rt2x00usb, 25, 0x50);
+		rt2x00_bbp_write(rt2x00usb, 61, 0x60);
+	}
+
+	rt2x00_bbp_read(rt2x00usb, 17, &reg_r17);
+
+	if (rssi > 80) {
+		if (reg_r17 != 0x60)
+			rt2x00_bbp_write(rt2x00usb, 17, 0x60);
+		return;
+	} else if (rssi >= 62) {
+		if (reg_r17 != 0x48)
+			rt2x00_bbp_write(rt2x00usb, 17, 0x48);
+		return;
+	} else if (rssi >= 46) {
+		if (reg_r17 != 0x41)
+			rt2x00_bbp_write(rt2x00usb, 17, 0x41);
+		return;
+	} else if (reg_r17 > up_bound) {
+		rt2x00_bbp_write(rt2x00usb, 17, up_bound);
+		return;
+	}
+
+	rt2x00_register_read(rt2x00usb, STA_CSR3, &reg);
+
+	if (reg > 512 && reg_r17 < up_bound)
+		rt2x00_bbp_write(rt2x00usb, 17, ++reg_r17);
+	else if (reg < 100 && reg_r17 > low_bound)
+		rt2x00_bbp_write(rt2x00usb, 17, --reg_r17);
+}
+
+/*
  * TX descriptor initialization
  */
 static void
@@ -636,6 +698,14 @@ rt2500usb_rxdone(void *data)
 	struct sk_buff		*skb;
 	struct rxd		*rxd;
 	u16			size;
+	u8			rssi_count;
+	char			total_rssi;
+
+	/*
+	 * Initialize variable for average RSSI calculation.
+	 */
+	rssi_count = 0;
+	total_rssi = 0;
 
 	while (1) {
 		entry = rt2x00_get_data_entry(ring);
@@ -670,13 +740,25 @@ rt2500usb_rxdone(void *data)
 
 			memcpy(skb_put(skb, size), entry->data_addr, size);
 
+			ring->params.rx.ssi =
+				rt2x00_get_field32(rxd->word1, RXD_W1_RSSI);
+
 			__ieee80211_rx(net_dev, skb, &ring->params.rx);
+
+			rssi_count++;
+			total_rssi += ring->params.rx.ssi;
 		}
 
 		usb_submit_urb(entry->urb, GFP_ATOMIC);
 
 		rt2x00_ring_index_inc(ring);
 	}
+
+	/*
+	 * Tune link for optimal performance.
+	 */
+	if (total_rssi && rssi_count)
+		rt2500usb_link_tuner(rt2x00usb, total_rssi / rssi_count);
 }
 
 static void

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 14/32] rt2x00: Allocate eeprom memory
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 5873 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Make the EEPROM array in rt2x00_pci and rt2x00_usb a pointer,
and allocate the memory seperately. This is needed for make
the structures more generic for all rt2x00 pci or usb modules.

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 21:45:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 21:47:22.000000000 +0200
@@ -1831,7 +1831,6 @@ rt2400pci_init_eeprom(struct rt2x00_pci 
 	u32			reg;
 	u16			value;
 	u16			eeprom;
-	int			counter;
 
 	/*
 	 * 1 - Detect EEPROM width.
@@ -1886,8 +1885,12 @@ rt2400pci_init_eeprom(struct rt2x00_pci 
 	/*
 	 * 7 - Read BBP data from EEPROM and store in private structure.
 	 */
+	rt2x00pci->eeprom = kzalloc(EEPROM_BBP_SIZE * sizeof(u16), GFP_KERNEL);
+	if (!rt2x00pci->eeprom) 
+		return -ENOMEM;
+
 	rt2x00_eeprom_multiread(rt2x00pci, EEPROM_BBP_START,
-		&rt2x00pci->eeprom, EEPROM_BBP_SIZE * sizeof(u16));
+		rt2x00pci->eeprom, EEPROM_BBP_SIZE * sizeof(u16));
 
 	return 0;
 }
@@ -2197,6 +2200,8 @@ rt2400pci_uninitialize(struct net_device
 	del_timer_sync(&rt2x00pci->poll_timer);
 #endif /* CONFIG_RT2400PCI_BUTTON */
 
+	kfree(rt2x00pci->eeprom);
+
 	if (likely(rt2x00pci->csr_addr)) {
 		iounmap(rt2x00pci->csr_addr);
 		rt2x00pci->csr_addr = NULL;
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h	2006-04-27 21:45:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h	2006-04-27 21:47:22.000000000 +0200
@@ -945,7 +945,7 @@ struct rt2x00_pci{
 	/*
 	 * EEPROM BBP data.
 	 */
-	u16					eeprom[EEPROM_BBP_SIZE];
+	u16					*eeprom;
 
 	/*
 	 * Low level statistics which will have
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 21:45:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 21:47:22.000000000 +0200
@@ -1939,7 +1939,6 @@ rt2500pci_init_eeprom(struct rt2x00_pci 
 	u32			reg;
 	u16			value;
 	u16			eeprom;
-	int			counter;
 
 	/*
 	 * 1 - Detect EEPROM width.
@@ -1998,8 +1997,12 @@ rt2500pci_init_eeprom(struct rt2x00_pci 
 	/*
 	 * 7 - Read BBP data from EEPROM and store in private structure.
 	 */
+	rt2x00pci->eeprom = kzalloc(EEPROM_BBP_SIZE * sizeof(u16), GFP_KERNEL);
+	if (!rt2x00pci->eeprom)
+		return -ENOMEM;
+
 	rt2x00_eeprom_multiread(rt2x00pci, EEPROM_BBP_START,
-		&rt2x00pci->eeprom, EEPROM_BBP_SIZE * sizeof(u16));
+		rt2x00pci->eeprom, EEPROM_BBP_SIZE * sizeof(u16));
 
 	return 0;
 }
@@ -2495,6 +2498,8 @@ rt2500pci_uninitialize(struct net_device
 	del_timer_sync(&rt2x00pci->poll_timer);
 #endif /* CONFIG_RT2500PCI_BUTTON */
 
+	kfree(rt2x00pci->eeprom);
+
 	if (likely(rt2x00pci->csr_addr)) {
 		iounmap(rt2x00pci->csr_addr);
 		rt2x00pci->csr_addr = NULL;
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h	2006-04-27 21:43:27.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h	2006-04-27 21:47:22.000000000 +0200
@@ -1215,7 +1215,7 @@ struct rt2x00_pci{
 	/*
 	 * EEPROM BBP data.
 	 */
-	u16					eeprom[EEPROM_BBP_SIZE];
+	u16					*eeprom;
 
 	/*
 	 * Low level statistics which will have
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 21:45:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:47:22.000000000 +0200
@@ -1657,9 +1657,12 @@ rt2500usb_init_eeprom(struct rt2x00_usb 
 	/*
 	 * 5 - Read BBP data from EEPROM and store in private structure.
 	 */
-	memset(&rt2x00usb->eeprom, 0x00, sizeof(rt2x00usb->eeprom));
+	rt2x00usb->eeprom = kzalloc(EEPROM_BBP_SIZE * sizeof(u16), GFP_KERNEL);
+	if (!rt2x00usb->eeprom) 
+		return -ENOMEM;
+
 	rt2x00_eeprom_multiread(rt2x00usb, EEPROM_BBP_START,
-		&rt2x00usb->eeprom[0], EEPROM_BBP_SIZE);
+		rt2x00usb->eeprom, EEPROM_BBP_SIZE * sizeof(u16));
 
 	return 0;
 }
@@ -2116,6 +2119,8 @@ rt2500usb_uninitialize(struct net_device
 {
 	struct rt2x00_usb	*rt2x00usb = ieee80211_dev_hw_data(net_dev);
 
+	kfree(rt2x00usb->eeprom);
+
 	if (rt2x00usb->scan) {
 		rt2x00usb->scan->cancelled = 1;
 		complete_all(&rt2x00usb->scan->completion);
@@ -2129,7 +2134,7 @@ rt2500usb_uninitialize(struct net_device
 
 		kfree(rt2x00usb->hw.modes);
 		rt2x00usb->hw.modes = NULL;
-	}
+}
 
 /*
  * USB driver handlers.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h	2006-04-27 21:43:27.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h	2006-04-27 21:47:22.000000000 +0200
@@ -727,7 +727,7 @@ struct rt2x00_usb{
 	/*
 	 * EEPROM BBP data.
 	 */
-	u16					eeprom[EEPROM_BBP_SIZE];
+	u16					*eeprom;
 
 	/*
 	 * Low level statistics which will have

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 15/32] rt2x00: Move rx_params to correct location
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 15891 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Store rx_params seperately outside the ring structure.
This is more safer and required because of some changes
in the way the rings are stored in the structure in the following
patches.

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 21:47:22.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 21:47:52.000000000 +0200
@@ -475,8 +475,8 @@ rt2400pci_config_channel(struct rt2x00_p
 	/*
 	 * Update active info for RX.
 	 */
-	rt2x00pci->rx.params.rx.freq = freq;
-	rt2x00pci->rx.params.rx.channel = channel;
+	rt2x00pci->rx_params.freq = freq;
+	rt2x00pci->rx_params.channel = channel;
 
 	/*
 	 * Clear false CRC during channel switch.
@@ -534,7 +534,7 @@ rt2400pci_config_antenna(struct rt2x00_p
 	/*
 	 * Update active info for RX.
 	 */
-	rt2x00pci->rx.params.rx.antenna = antenna;
+	rt2x00pci->rx_params.antenna = antenna;
 }
 
 static void
@@ -814,10 +814,10 @@ rt2400pci_rxdone(void *data)
 
 			memcpy(skb_put(skb, size), entry->data_addr, size);
 
-			ring->params.rx.ssi =
+			rt2x00pci->rx_params.ssi =
 				rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
 
-			__ieee80211_rx(net_dev, skb, &ring->params.rx);
+			__ieee80211_rx(net_dev, skb, &rt2x00pci->rx_params);
 		}
 
 		rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
@@ -981,8 +981,8 @@ rt2400pci_alloc_ring(
 	/*
 	 * Initialize ring parameters.
 	 */
-	ring->params.tx.cw_min = 5;	/* cw_min: 2^5 = 32. */
-	ring->params.tx.cw_max = 10;	/* cw_max: 2^10 = 1024. */
+	ring->tx_params.cw_min = 5;	/* cw_min: 2^5 = 32. */
+	ring->tx_params.cw_max = 10;	/* cw_max: 2^10 = 1024. */
 
 	rt2x00_ring_index_clear(ring);
 
@@ -1374,7 +1374,7 @@ rt2400pci_tx(struct net_device *net_dev,
 	 * queue. This is the alternative since we cannot
 	 * set the CWmin and CWmax per descriptor.
 	 */
-	rt2400pci_config_cw(rt2x00pci, &ring->params.tx);
+	rt2400pci_config_cw(rt2x00pci, &ring->tx_params);
 	rt2x00_register_write(rt2x00pci, TXCSR0, reg);
 
 	return 0;
@@ -1544,7 +1544,7 @@ rt2400pci_config_update(void *data)
 	/*
 	 * Update active info for RX.
 	 */
-	rt2x00pci->rx.params.rx.phymode = conf->phymode;
+	rt2x00pci->rx_params.phymode = conf->phymode;
 }
 
 static int
@@ -1599,7 +1599,7 @@ rt2400pci_scan(void *data)
 	 * Switch channel and update active info for RX.
 	 */
 	if (rt2x00pci->scan->state == IEEE80211_SCAN_START) {
-		rt2x00pci->rx.params.rx.phymode =
+		rt2x00pci->rx_params.phymode =
 			rt2x00pci->scan->conf.scan_phymode;
 
 		rt2400pci_config_channel(rt2x00pci,
@@ -1610,7 +1610,7 @@ rt2400pci_scan(void *data)
 		rt2400pci_config_txpower(rt2x00pci,
 			rt2x00pci->scan->conf.scan_power_level);
 	} else {
-		rt2x00pci->rx.params.rx.phymode =
+		rt2x00pci->rx_params.phymode =
 			rt2x00pci->scan->conf.running_phymode;
 
 		rt2400pci_config_channel(rt2x00pci,
@@ -1726,7 +1726,7 @@ rt2400pci_conf_tx(struct net_device *net
 	else
 		return -EINVAL;
 
-	memcpy(&ring->params, params, sizeof(*params));
+	memcpy(&ring->tx_params, params, sizeof(*params));
 
 	/*
 	 * TODO: We can't use different cw_min and cw_max variables
@@ -1737,14 +1737,14 @@ rt2400pci_conf_tx(struct net_device *net
 	 * RT2400 registers require to know the bit number 'n'.
 	 */
 	if (params->cw_min)
-		ring->params.tx.cw_min = HIGHEST_BIT16(params->cw_min) + 1;
+		ring->tx_params.cw_min = HIGHEST_BIT16(params->cw_min) + 1;
 	else
-		ring->params.tx.cw_min = 5; /* cw_min: 2^5 = 32. */
+		ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */
 
 	if (params->cw_max)
-		ring->params.tx.cw_max = HIGHEST_BIT16(params->cw_max) + 1;
+		ring->tx_params.cw_max = HIGHEST_BIT16(params->cw_max) + 1;
 	else
-		ring->params.tx.cw_max = 10; /* cw_min: 2^10 = 1024. */
+		ring->tx_params.cw_max = 10; /* cw_min: 2^10 = 1024. */
 
 	return 0;
 }
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h	2006-04-27 21:47:22.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h	2006-04-27 21:47:52.000000000 +0200
@@ -926,6 +926,11 @@ struct rt2x00_pci{
 	struct workqueue_struct		*workqueue;
 
 	/*
+	 * RX ring parameters.
+	 */
+	struct ieee80211_rx_status		rx_params;
+
+	/*
 	 * False CCA count.
 	 */
 	int					false_cca;
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 21:47:22.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 21:47:52.000000000 +0200
@@ -510,8 +510,8 @@ rt2500pci_config_channel(struct rt2x00_p
 	/*
 	 * Update active info for RX.
 	 */
-	rt2x00pci->rx.params.rx.freq = freq;
-	rt2x00pci->rx.params.rx.channel = channel;
+	rt2x00pci->rx_params.freq = freq;
+	rt2x00pci->rx_params.channel = channel;
 
 	/*
 	 * Clear false CRC during channel switch.
@@ -589,7 +589,7 @@ rt2500pci_config_antenna(struct rt2x00_p
 	/*
 	 * Update active info for RX.
 	 */
-	rt2x00pci->rx.params.rx.antenna = antenna;
+	rt2x00pci->rx_params.antenna = antenna;
 }
 
 static void
@@ -733,16 +733,16 @@ rt2500pci_write_tx_desc(
 	rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
 
 	if (control->queue == IEEE80211_TX_QUEUE_DATA0) {
-		params = &rt2x00pci->prio.params.tx;
+		params = &rt2x00pci->prio.tx_params;
 		rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
 	} else if (control->queue == IEEE80211_TX_QUEUE_DATA1) {
-		params = &rt2x00pci->tx.params.tx;
+		params = &rt2x00pci->tx.tx_params;
 		rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
 	} else if (IEEE80211_TX_QUEUE_AFTER_BEACON) {
-		params = &rt2x00pci->atim.params.tx;
+		params = &rt2x00pci->atim.tx_params;
 		rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
 	} else if (IEEE80211_TX_QUEUE_BEACON) {
-		params = &rt2x00pci->beacon.params.tx;
+		params = &rt2x00pci->beacon.tx_params;
 		rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 1);
 	}
 
@@ -896,13 +896,13 @@ rt2500pci_rxdone(void *data)
 
 			memcpy(skb_put(skb, size), entry->data_addr, size);
 
-			ring->params.rx.ssi =
+			rt2x00pci->rx_params.ssi =
 				rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
 
-			__ieee80211_rx(net_dev, skb, &ring->params.rx);
+			__ieee80211_rx(net_dev, skb, &rt2x00pci->rx_params);
 
 			rssi_count++;
-			total_rssi += ring->params.rx.ssi;
+			total_rssi += rt2x00pci->rx_params.ssi;
 		}
 		rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
 
@@ -1066,9 +1066,9 @@ rt2500pci_alloc_ring(
 	/*
 	 * Initialize ring parameters.
 	 */
-	ring->params.tx.aifs = 2;
-	ring->params.tx.cw_min = 5;	/* cw_min: 2^5 = 32. */
-	ring->params.tx.cw_max = 10;	/* cw_max: 2^10 = 1024. */
+	ring->tx_params.aifs = 2;
+	ring->tx_params.cw_min = 5;	/* cw_min: 2^5 = 32. */
+	ring->tx_params.cw_max = 10;	/* cw_max: 2^10 = 1024. */
 
 	rt2x00_ring_index_clear(ring);
 
@@ -1657,7 +1657,7 @@ rt2500pci_config_update(void *data)
 	/*
 	 * Update active info for RX.
 	 */
-	rt2x00pci->rx.params.rx.phymode = conf->phymode;
+	rt2x00pci->rx_params.phymode = conf->phymode;
 }
 
 static int
@@ -1712,7 +1712,7 @@ rt2500pci_scan(void *data)
 	 * Switch channel and update active info for RX.
 	 */
 	if (rt2x00pci->scan->state == IEEE80211_SCAN_START) {
-		rt2x00pci->rx.params.rx.phymode =
+		rt2x00pci->rx_params.phymode =
 			rt2x00pci->scan->conf.scan_phymode;
 	
 		rt2500pci_config_channel(rt2x00pci,
@@ -1721,7 +1721,7 @@ rt2500pci_scan(void *data)
 			rt2x00pci->scan->conf.scan_freq,
 			rt2x00pci->scan->conf.scan_power_level);
 	} else {
-		rt2x00pci->rx.params.rx.phymode =
+		rt2x00pci->rx_params.phymode =
 			rt2x00pci->scan->conf.running_phymode;
 	
 		rt2500pci_config_channel(rt2x00pci,
@@ -1835,24 +1835,24 @@ rt2500pci_conf_tx(struct net_device *net
 	else
 		return -EINVAL;
 
-	memcpy(&ring->params, params, sizeof(*params));
+	memcpy(&ring->tx_params, params, sizeof(*params));
 
 	/*
 	 * The passed variables are stored as real value ((2^n)-1).
 	 * RT2400 registers require to know the bit number 'n'.
 	 */
 	if (params->cw_min)
-		ring->params.tx.cw_min = HIGHEST_BIT16(params->cw_min) + 1;
+		ring->tx_params.cw_min = HIGHEST_BIT16(params->cw_min) + 1;
 	else
-		ring->params.tx.cw_min = 5; /* cw_min: 2^5 = 32. */
+		ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */
 
 	if (params->cw_max)
-		ring->params.tx.cw_max = HIGHEST_BIT16(params->cw_max) + 1;
+		ring->tx_params.cw_max = HIGHEST_BIT16(params->cw_max) + 1;
 	else
-		ring->params.tx.cw_max = 10; /* cw_min: 2^10 = 1024. */
+		ring->tx_params.cw_max = 10; /* cw_min: 2^10 = 1024. */
 
 	if (!params->aifs)
-		ring->params.tx.aifs = 2;
+		ring->tx_params.aifs = 2;
 
 	return 0;
 }
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h	2006-04-27 21:47:22.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h	2006-04-27 21:47:52.000000000 +0200
@@ -1196,6 +1196,11 @@ struct rt2x00_pci{
 	struct workqueue_struct		*workqueue;
 
 	/*
+	 * RX ring parameters.
+	 */
+	struct ieee80211_rx_status		rx_params;
+
+	/*
 	 * Alignment.
 	 */
 	u16					__pad;
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 21:47:22.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:47:52.000000000 +0200
@@ -435,7 +435,7 @@ rt2500usb_config_antenna(struct rt2x00_u
 	/*
 	 * Update active info for RX.
 	 */
-	rt2x00usb->rx.params.rx.antenna = antenna;
+	rt2x00usb->rx_params.antenna = antenna;
 }
 
 static void
@@ -573,16 +573,16 @@ rt2500usb_write_tx_desc(
 	rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
 
 	if (control->queue == IEEE80211_TX_QUEUE_DATA0) {
-		params = &rt2x00usb->prio.params.tx;
+		params = &rt2x00usb->prio.tx_params;
 		rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
 	} else if (control->queue == IEEE80211_TX_QUEUE_DATA1) {
-		params = &rt2x00usb->tx.params.tx;
+		params = &rt2x00usb->tx.tx_params;
 		rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
 	} else if (IEEE80211_TX_QUEUE_AFTER_BEACON) {
-		params = &rt2x00usb->atim.params.tx;
+		params = &rt2x00usb->atim.tx_params;
 		rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
 	} else if (IEEE80211_TX_QUEUE_BEACON) {
-		params = &rt2x00usb->beacon.params.tx;
+		params = &rt2x00usb->beacon.tx_params;
 		rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 1);
 	}
 
@@ -740,13 +740,13 @@ rt2500usb_rxdone(void *data)
 
 			memcpy(skb_put(skb, size), entry->data_addr, size);
 
-			ring->params.rx.ssi =
+			rt2x00usb->rx_params.ssi =
 				rt2x00_get_field32(rxd->word1, RXD_W1_RSSI);
 
-			__ieee80211_rx(net_dev, skb, &ring->params.rx);
+			__ieee80211_rx(net_dev, skb, &rt2x00usb->rx_params);
 
 			rssi_count++;
-			total_rssi += ring->params.rx.ssi;
+			total_rssi += rt2x00usb->rx_params.ssi;
 		}
 
 		usb_submit_urb(entry->urb, GFP_ATOMIC);
@@ -855,9 +855,9 @@ rt2500usb_alloc_ring(
 	/*
 	 * Initialize ring parameters.
 	 */
-	ring->params.tx.aifs = 2;
-	ring->params.tx.cw_min = 5;	/* cw_min: 2^5 = 32. */
-	ring->params.tx.cw_max = 10;	/* cw_max: 2^10 = 1024. */
+	ring->tx_params.aifs = 2;
+	ring->tx_params.cw_min = 5;	/* cw_min: 2^5 = 32. */
+	ring->tx_params.cw_max = 10;	/* cw_max: 2^10 = 1024. */
 
 	rt2x00_ring_index_clear(ring);
 
@@ -1394,7 +1394,7 @@ rt2500usb_config_update(void *data)
 	/*
 	 * Update active info for RX.
 	 */
-	rt2x00usb->rx.params.rx.phymode = conf->phymode;
+	rt2x00usb->rx_params.phymode = conf->phymode;
 }
 
 static int
@@ -1450,7 +1450,7 @@ rt2500usb_scan(void *data)
 	 * Switch channel and update active info for RX.
 	 */
 	if (rt2x00usb->scan->state == IEEE80211_SCAN_START) {
-		rt2x00usb->rx.params.rx.phymode =
+		rt2x00usb->rx_params.phymode =
 			rt2x00usb->scan->conf.scan_phymode;
 	
 		rt2500usb_config_channel(rt2x00usb,
@@ -1459,7 +1459,7 @@ rt2500usb_scan(void *data)
 			rt2x00usb->scan->conf.scan_freq,
 			rt2x00usb->scan->conf.scan_power_level);
 	} else {
-		rt2x00usb->rx.params.rx.phymode =
+		rt2x00usb->rx_params.phymode =
 			rt2x00usb->scan->conf.running_phymode;
 	
 		rt2500usb_config_channel(rt2x00usb,
@@ -1558,24 +1558,24 @@ rt2500usb_conf_tx(struct net_device *net
 	else
 		return -EINVAL;
 
-	memcpy(&ring->params, params, sizeof(*params));
+	memcpy(&ring->tx_params, params, sizeof(*params));
 
 	/*
 	 * The passed variables are stored as real value ((2^n)-1).
 	 * RT2400 registers require to know the bit number 'n'.
 	 */
 	if (params->cw_min)
-		ring->params.tx.cw_min = HIGHEST_BIT16(params->cw_min) + 1;
+		ring->tx_params.cw_min = HIGHEST_BIT16(params->cw_min) + 1;
 	else
-		ring->params.tx.cw_min = 5; /* cw_min: 2^5 = 32. */
+		ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */
 
 	if (params->cw_max)
-		ring->params.tx.cw_max = HIGHEST_BIT16(params->cw_max) + 1;
+		ring->tx_params.cw_max = HIGHEST_BIT16(params->cw_max) + 1;
 	else
-		ring->params.tx.cw_max = 10; /* cw_min: 2^10 = 1024. */
+		ring->tx_params.cw_max = 10; /* cw_min: 2^10 = 1024. */
 
 	if (!params->aifs)
-		ring->params.tx.aifs = 2;
+		ring->tx_params.aifs = 2;
 
 	return 0;
 }
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h	2006-04-27 21:47:22.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h	2006-04-27 21:47:52.000000000 +0200
@@ -714,6 +714,11 @@ struct rt2x00_usb{
 	struct workqueue_struct		*workqueue;
 
 	/*
+	 * RX ring parameters.
+	 */
+	struct ieee80211_rx_status		rx_params;
+
+	/*
 	 * Alignment.
 	 */
 	u8					__pad1;
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h	2006-04-27 21:39:24.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h	2006-04-27 21:47:52.000000000 +0200
@@ -465,19 +465,9 @@ struct data_ring{
 	struct ieee80211_tx_queue_stats_data	stats;
 
 	/*
-	 * Queue parameters.
-	 * We can safely put the following structures inside
-	 * the same union since a ring is either TX or RX
-	 * so they will never be used at the same time.
-	 * The ieee80211_rx_status structures is stored here, when
-	 * configuration changes have been passed to us, we can
-	 * change it to show the active configuration. And received
-	 * frames will always have the correct settings.
-	 */
-	union {
-		struct ieee80211_rx_status		rx;
-		struct ieee80211_tx_queue_params	tx;
-	}					params;
+	 * TX Queue parameters.
+	 */
+	struct ieee80211_tx_queue_params	tx_params;
 
 	/*
 	 * Base address for data ring.

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 16/32] rt2x00: Make sure TX rings are empty when scanning
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 15118 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Improve the waiting when a skb buffer needs to be send
before the channel switch. This also makes sure no
pending packets are still on the TX ring while making the
channel switch.

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 21:47:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 21:48:21.000000000 +0200
@@ -838,7 +838,6 @@ rt2400pci_txdone(void *data)
 	struct rt2x00_pci	*rt2x00pci = (struct rt2x00_pci*)ring->dev;
 	struct net_device	*net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
 	struct data_entry	*entry;
-	struct skb_cb		*cb;
 	struct txd		*txd;
 	int			tx_status;
 	int			ack;
@@ -851,13 +850,6 @@ rt2400pci_txdone(void *data)
 		|| !rt2x00_get_field32(txd->word0, TXD_W0_VALID))
 			break;
 
-		/*
-		 * Check if this frame was send for the scan routine.
-		 */
-		cb = (struct skb_cb*)&entry->skb->cb;
-		if (rt2x00pci->scan && cb->scan_complete)
-			complete(&rt2x00pci->scan->completion);
-
 		ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
 
 		/*
@@ -896,6 +888,18 @@ rt2400pci_txdone(void *data)
 
 		rt2x00_ring_index_done_inc(ring);
 	} while (!rt2x00_ring_empty(ring));
+
+	/*
+	 * Check if we are waiting on an empty queue
+	 * to start scanning.
+	 */
+	if (rt2x00pci->scan
+	&& rt2x00_ring_empty(&rt2x00pci->tx)
+	&& rt2x00_ring_empty(&rt2x00pci->atim)
+	&& rt2x00_ring_empty(&rt2x00pci->prio)) {
+		rt2x00pci->scan->status = SCANNING_READY;
+		complete(&rt2x00pci->scan->completion);
+	}
 }
 
 static irqreturn_t
@@ -1517,6 +1521,14 @@ rt2400pci_stop(struct net_device *net_de
 	rt2x00_register_write(rt2x00pci, CSR8, reg);
 
 	/*
+	 * Cancel scanning.
+	 */
+	if (rt2x00pci->scan) {
+		rt2x00pci->scan->status = SCANNING_CANCELLED;
+		complete_all(&rt2x00pci->scan->completion);
+	}
+
+	/*
 	 * Free DMA rings.
 	 */
 	rt2400pci_free_rings(rt2x00pci);
@@ -1564,35 +1576,23 @@ static void
 rt2400pci_scan(void *data)
 {
 	struct rt2x00_pci	*rt2x00pci = data;
-	struct net_device	*net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
-	struct skb_cb		*cb;
 
 	if (unlikely(!rt2x00pci->scan))
 		return;
 
 	/*
-	 * Check if we have to send a packet before the
-	 * channel switch.
+	 * Before we can start switch the channel for scanning
+	 * we need to wait untill all TX rings are empty to
+	 * guarentee that all frames are send on the correct channel.
 	 */
-	if (rt2x00pci->scan->conf.skb) {
-		cb = (struct skb_cb*)&rt2x00pci->scan->conf.skb->cb;
-		cb->scan_complete = 1;
-
-		if (rt2400pci_tx(net_dev, rt2x00pci->scan->conf.skb,
-			rt2x00pci->scan->conf.tx_control))
-			goto exit;
-
-		/*
-		 * Wait for the frame to be correctly transmitted.
-		 */
+	if (rt2x00pci->scan->status != SCANNING_READY)
 		wait_for_completion(&rt2x00pci->scan->completion);
-	}
 
 	/*
 	 * Check if this scan has been cancelled while
 	 * work was still scheduled.
 	 */
-	if (rt2x00pci->scan->cancelled)
+	if (rt2x00pci->scan->status == SCANNING_CANCELLED)
 		goto exit;
 
 	/*
@@ -1633,9 +1633,24 @@ rt2400pci_passive_scan(struct net_device
 {
 	struct rt2x00_pci	*rt2x00pci = ieee80211_dev_hw_data(net_dev);
 
+	if (rt2x00pci->scan)
+		return -EBUSY;
+
+	/*
+	 * Allocate scanning structure to store scanning info.
+	 */
 	rt2x00pci->scan = kmalloc(sizeof(struct scanning), GFP_ATOMIC);
 	if (!rt2x00pci->scan)
-		return 0;
+		return -ENOMEM;
+
+	/*
+	 * Check if we have to send a packet before the
+	 * channel switch.
+	 */
+	if (conf->skb) {
+		if (rt2400pci_tx(net_dev, conf->skb, conf->tx_control))
+			goto exit;
+	}
 
 	/*
 	 * Initialize Scanning structure.
@@ -1646,14 +1661,21 @@ rt2400pci_passive_scan(struct net_device
 
 	rt2x00pci->scan->state = state;
 
-	rt2x00pci->scan->cancelled = 0;
+	rt2x00pci->scan->status = 0;
 
 	/*
 	 * Queue work.
 	 */
-	queue_work(rt2x00pci->workqueue, &rt2x00pci->scan_work);
+	if (!queue_work(rt2x00pci->workqueue, &rt2x00pci->scan_work))
+		goto exit;
 
 	return 0;
+
+exit:
+	kfree(rt2x00pci->scan);
+	rt2x00pci->scan = NULL;
+
+	return -EIO;
 }
 
 static int
@@ -2207,11 +2229,6 @@ rt2400pci_uninitialize(struct net_device
 		rt2x00pci->csr_addr = NULL;
 	}
 
-	if (rt2x00pci->scan) {
-		rt2x00pci->scan->cancelled = 1;
-		complete_all(&rt2x00pci->scan->completion);
-	}
-
 	if (likely(rt2x00pci->workqueue)) {
 		flush_workqueue(rt2x00pci->workqueue);
 		destroy_workqueue(rt2x00pci->workqueue);
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 21:47:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 21:48:21.000000000 +0200
@@ -923,7 +923,6 @@ rt2500pci_txdone(void *data)
 	struct rt2x00_pci	*rt2x00pci = (struct rt2x00_pci*)ring->dev;
 	struct net_device	*net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
 	struct data_entry	*entry;
-	struct skb_cb		*cb;
 	struct txd		*txd;
 	int			tx_status;
 	int			ack;
@@ -936,13 +935,6 @@ rt2500pci_txdone(void *data)
 		|| !rt2x00_get_field32(txd->word0, TXD_W0_VALID))
 			break;
 
-		/*
-		 * Check if this frame was send for the scan routine.
-		 */
-		cb = (struct skb_cb*)&entry->skb->cb;
-		if (rt2x00pci->scan && cb->scan_complete)
-			complete(&rt2x00pci->scan->completion);
-
 		ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
 
 		/*
@@ -981,6 +973,18 @@ rt2500pci_txdone(void *data)
 
 		rt2x00_ring_index_done_inc(ring);
 	} while (!rt2x00_ring_empty(ring));
+
+	/*
+	 * Check if we are waiting on an empty queue
+	 * to start scanning.
+	 */
+	if (rt2x00pci->scan
+	&& rt2x00_ring_empty(&rt2x00pci->tx)
+	&& rt2x00_ring_empty(&rt2x00pci->atim)
+	&& rt2x00_ring_empty(&rt2x00pci->prio)) {
+		rt2x00pci->scan->status = SCANNING_READY;
+		complete(&rt2x00pci->scan->completion);
+	}
 }
 
 static irqreturn_t
@@ -1630,6 +1634,14 @@ rt2500pci_stop(struct net_device *net_de
 	rt2x00_register_write(rt2x00pci, CSR8, reg);
 
 	/*
+	 * Cancel scanning.
+	 */
+	if (rt2x00pci->scan) {
+		rt2x00pci->scan->status = SCANNING_CANCELLED;
+		complete_all(&rt2x00pci->scan->completion);
+	}
+
+	/*
 	 * Free DMA rings.
 	 */
 	rt2500pci_free_rings(rt2x00pci);
@@ -1677,35 +1689,23 @@ static void
 rt2500pci_scan(void *data)
 {
 	struct rt2x00_pci	*rt2x00pci = data;
-	struct net_device	*net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
-	struct skb_cb		*cb;
 
 	if (unlikely(!rt2x00pci->scan))
 		return;
 
 	/*
-	 * Check if we have to send a packet before the
-	 * channel switch.
+	 * Before we can start switch the channel for scanning
+	 * we need to wait untill all TX rings are empty to
+	 * guarentee that all frames are send on the correct channel.
 	 */
-	if (rt2x00pci->scan->conf.skb) {
-		cb = (struct skb_cb*)&rt2x00pci->scan->conf.skb->cb;
-		cb->scan_complete = 1;
-
-		if (rt2500pci_tx(net_dev, rt2x00pci->scan->conf.skb,
-			rt2x00pci->scan->conf.tx_control))
-			goto exit;
-
-		/*
-		 * Wait for the frame to be correctly transmitted.
-		 */
+	if (rt2x00pci->scan->status != SCANNING_READY)
 		wait_for_completion(&rt2x00pci->scan->completion);
-	}
 
 	/*
 	 * Check if this scan has been cancelled while
 	 * work was still scheduled.
 	 */
-	if (rt2x00pci->scan->cancelled)
+	if (rt2x00pci->scan->status == SCANNING_CANCELLED)
 		goto exit;
 
 	/*
@@ -1742,9 +1742,24 @@ rt2500pci_passive_scan(struct net_device
 {
 	struct rt2x00_pci	*rt2x00pci = ieee80211_dev_hw_data(net_dev);
 
+	if (rt2x00pci->scan)
+		return -EBUSY;
+
+	/*
+	 * Allocate scanning structure to store scanning info.
+	 */
 	rt2x00pci->scan = kmalloc(sizeof(struct scanning), GFP_ATOMIC);
 	if (!rt2x00pci->scan)
-		return 0;
+		return -ENOMEM;
+
+	/*
+	 * Check if we have to send a packet before the
+	 * channel switch.
+	 */
+	if (conf->skb) {
+		if (rt2500pci_tx(net_dev, conf->skb, conf->tx_control))
+			goto exit;
+	}
 
 	/*
 	 * Initialize Scanning structure.
@@ -1755,14 +1770,21 @@ rt2500pci_passive_scan(struct net_device
 
 	rt2x00pci->scan->state = state;
 
-	rt2x00pci->scan->cancelled = 0;
+	rt2x00pci->scan->status = 0;
 
 	/*
 	 * Queue work.
 	 */
-	queue_work(rt2x00pci->workqueue, &rt2x00pci->scan_work);
+	if (!queue_work(rt2x00pci->workqueue, &rt2x00pci->scan_work))
+		goto exit;
 
 	return 0;
+
+exit:
+	kfree(rt2x00pci->scan);
+	rt2x00pci->scan = NULL;
+
+	return -EIO;
 }
 
 static int
@@ -2505,20 +2527,15 @@ rt2500pci_uninitialize(struct net_device
 		rt2x00pci->csr_addr = NULL;
 	}
 
-	if (rt2x00pci->scan) {
-		rt2x00pci->scan->cancelled = 1;
-		complete_all(&rt2x00pci->scan->completion);
-	}
-
 	if (likely(rt2x00pci->workqueue)) {
 		flush_workqueue(rt2x00pci->workqueue);
 		destroy_workqueue(rt2x00pci->workqueue);
 		rt2x00pci->workqueue = NULL;
 	}
 
-		kfree(rt2x00pci->hw.modes);
-		rt2x00pci->hw.modes = NULL;
-	}
+	kfree(rt2x00pci->hw.modes);
+	rt2x00pci->hw.modes = NULL;
+}
 
 /*
  * PCI driver handlers.
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 21:47:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:48:21.000000000 +0200
@@ -769,7 +769,6 @@ rt2500usb_txdone(void *data)
 	struct net_device	*net_dev = usb_get_intfdata(
 						rt2x00usb->usb_intf);
 	struct data_entry	*entry;
-	struct skb_cb		*cb;
 	struct txd		*txd;
 	int			ack;
 
@@ -777,13 +776,6 @@ rt2500usb_txdone(void *data)
 		entry = rt2x00_get_data_entry_done(ring);
 		txd = entry->desc_addr;
 
-		/*
-		 * Check if this frame was send for the scan routine.
-		 */
-		cb = (struct skb_cb*)&entry->skb->cb;
-		if (rt2x00usb->scan && cb->scan_complete)
-			complete(&rt2x00usb->scan->completion);
-
 		ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
 	
 		/*
@@ -815,6 +807,18 @@ rt2500usb_txdone(void *data)
 	
 		rt2x00_ring_index_done_inc(entry->ring);
 	} while (!rt2x00_ring_empty(ring));
+
+	/*
+	 * Check if we are waiting on an empty queue
+	 * to start scanning.
+	 */
+	if (rt2x00usb->scan
+	&& rt2x00_ring_empty(&rt2x00usb->tx)
+	&& rt2x00_ring_empty(&rt2x00usb->atim)
+	&& rt2x00_ring_empty(&rt2x00usb->prio)) {
+		rt2x00usb->scan->status = SCANNING_READY;
+		complete(&rt2x00usb->scan->completion);
+	}
 }
 
 static void
@@ -1368,6 +1372,14 @@ rt2500usb_stop(struct net_device *net_de
 	rt2x00_register_write(rt2x00usb, MAC_CSR14, 0x2121);
 
 	/*
+	 * Cancel scanning.
+	 */
+	if (rt2x00usb->scan) {
+		rt2x00usb->scan->status = SCANNING_CANCELLED;
+		complete_all(&rt2x00usb->scan->completion);
+	}
+
+	/*
 	 * Free DMA rings.
 	 */
 	rt2500usb_free_rings(rt2x00usb);
@@ -1414,36 +1426,23 @@ static void
 rt2500usb_scan(void *data)
 {
 	struct rt2x00_usb	*rt2x00usb = data;
-	struct net_device	*net_dev =
-		usb_get_intfdata(rt2x00usb->usb_intf);
-	struct skb_cb		*cb;
 
 	if (unlikely(!rt2x00usb->scan))
 		return;
 
 	/*
-	 * Check if we have to send a packet before the
-	 * channel switch.
+	 * Before we can start switch the channel for scanning
+	 * we need to wait untill all TX rings are empty to
+	 * guarentee that all frames are send on the correct channel.
 	 */
-	if (rt2x00usb->scan->conf.skb) {
-		cb = (struct skb_cb*)&rt2x00usb->scan->conf.skb->cb;
-		cb->scan_complete = 1;
-
-		if (rt2500usb_tx(net_dev, rt2x00usb->scan->conf.skb,
-			rt2x00usb->scan->conf.tx_control))
-			goto exit;
-
-		/*
-		 * Wait for the frame to be correctly transmitted.
-		 */
+	if (rt2x00usb->scan->status != SCANNING_READY)
 		wait_for_completion(&rt2x00usb->scan->completion);
-	}
 
 	/*
 	 * Check if this scan has been cancelled while
 	 * work was still scheduled.
 	 */
-	if (rt2x00usb->scan->cancelled)
+	if (rt2x00usb->scan->status == SCANNING_CANCELLED)
 		goto exit;
 
 	/*
@@ -1480,9 +1479,24 @@ rt2500usb_passive_scan(struct net_device
 {
 	struct rt2x00_usb	*rt2x00usb = ieee80211_dev_hw_data(net_dev);
 
+	if (rt2x00usb->scan)
+		return -EBUSY;
+
+	/*
+	 * Allocate scanning structure to store scanning info.
+	 */
 	rt2x00usb->scan = kmalloc(sizeof(struct scanning), GFP_ATOMIC);
 	if (!rt2x00usb->scan)
-		return 0;
+		return -ENOMEM;
+
+	/*
+	 * Check if we have to send a packet before the
+	 * channel switch.
+	 */
+	if (conf->skb) {
+		if (rt2500usb_tx(net_dev, conf->skb, conf->tx_control))
+			goto exit;
+	}
 
 	/*
 	 * Initialize Scanning structure.
@@ -1493,14 +1507,21 @@ rt2500usb_passive_scan(struct net_device
 
 	rt2x00usb->scan->state = state;
 
-	rt2x00usb->scan->cancelled = 0;
+	rt2x00usb->scan->status = 0;
 
 	/*
 	 * Queue work.
 	 */
-	queue_work(rt2x00usb->workqueue, &rt2x00usb->scan_work);
+	if (!queue_work(rt2x00usb->workqueue, &rt2x00usb->scan_work))
+		goto exit;
 
 	return 0;
+
+exit:
+	kfree(rt2x00usb->scan);
+	rt2x00usb->scan = NULL;
+
+	return -EIO;
 }
 
 static int
@@ -2121,19 +2142,14 @@ rt2500usb_uninitialize(struct net_device
 
 	kfree(rt2x00usb->eeprom);
 
-	if (rt2x00usb->scan) {
-		rt2x00usb->scan->cancelled = 1;
-		complete_all(&rt2x00usb->scan->completion);
-	}
-
 	if (likely(rt2x00usb->workqueue)) {
 		flush_workqueue(rt2x00usb->workqueue);
 		destroy_workqueue(rt2x00usb->workqueue);
 		rt2x00usb->workqueue = NULL;
 	}
 
-		kfree(rt2x00usb->hw.modes);
-		rt2x00usb->hw.modes = NULL;
+	kfree(rt2x00usb->hw.modes);
+	rt2x00usb->hw.modes = NULL;
 }
 
 /*
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h	2006-04-27 21:47:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h	2006-04-27 21:48:21.000000000 +0200
@@ -428,15 +428,6 @@ rt2x00_rf(const struct _rt2x00_chip *chi
 }
 
 /*
- * Data to be placed in the skb->cb array.
- * therefor this structure may not exceed the 40 bytes.
- */
-struct skb_cb{
-	int					scan_complete;
-} __attribute__ ((packed));
-
-
-/*
  * data_ring
  * Data rings are used by the device to send and receive packets.
  * The data_addr is the base address of the data memory.
@@ -589,7 +580,9 @@ struct scanning{
 	/*
 	 * Flag to see if this scan has been cancelled.
 	 */
-	short					cancelled;
+	short					status;
+#define SCANNING_READY				0x0001
+#define SCANNING_CANCELLED			0x0002
 } __attribute__ ((packed));
 
 

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 17/32] rt2x00: Put net_device structure in data_ring
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 10234 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Change the structure stored in the data_ring structure
from the rt2x00_pci or rt2x00_usb to net_device.
This allows for better type checking, and the net_dev
is more often used in the interrupt handlers.

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 21:48:21.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 21:49:08.000000000 +0200
@@ -760,10 +760,8 @@ rt2400pci_write_tx_desc(
 static void
 rt2400pci_beacondone(void *data)
 {
-	struct data_ring	*ring = (struct data_ring*)data;
-	struct rt2x00_pci	*rt2x00pci = (struct rt2x00_pci*)ring->dev;
-	struct net_device	*net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
-	struct sk_buff		*skb;
+	struct data_ring		*ring = (struct data_ring*)data;
+	struct sk_buff			*skb;
 	struct ieee80211_tx_control	beacon;
 
 	memset(&beacon, 0x00, sizeof(beacon));
@@ -771,11 +769,11 @@ rt2400pci_beacondone(void *data)
 	/*
 	 * TODO: What value should be passed as bss_idx?
 	 */
-	skb = ieee80211_beacon_get(net_dev, 0, &beacon);
+	skb = ieee80211_beacon_get(ring->net_dev, 0, &beacon);
 	if (!skb)
 		return;
 
-	rt2400pci_beacon_update(net_dev, skb, &beacon);
+	rt2400pci_beacon_update(ring->net_dev, skb, &beacon);
 
 	dev_kfree_skb_any(skb);
 }
@@ -784,8 +782,8 @@ static void
 rt2400pci_rxdone(void *data)
 {
 	struct data_ring	*ring = (struct data_ring*)data;
-	struct rt2x00_pci	*rt2x00pci = (struct rt2x00_pci*)ring->dev;
-	struct net_device	*net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
+	struct rt2x00_pci	*rt2x00pci =
+		ieee80211_dev_hw_data(ring->net_dev);
 	struct data_entry	*entry;
 	struct sk_buff		*skb;
 	struct rxd		*rxd;
@@ -817,7 +815,8 @@ rt2400pci_rxdone(void *data)
 			rt2x00pci->rx_params.ssi =
 				rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
 
-			__ieee80211_rx(net_dev, skb, &rt2x00pci->rx_params);
+			__ieee80211_rx(ring->net_dev,
+				skb, &rt2x00pci->rx_params);
 		}
 
 		rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
@@ -835,8 +834,8 @@ static void
 rt2400pci_txdone(void *data)
 {
 	struct data_ring	*ring = (struct data_ring*)data;
-	struct rt2x00_pci	*rt2x00pci = (struct rt2x00_pci*)ring->dev;
-	struct net_device	*net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
+	struct rt2x00_pci	*rt2x00pci =
+		ieee80211_dev_hw_data(ring->net_dev);
 	struct data_entry	*entry;
 	struct txd		*txd;
 	int			tx_status;
@@ -881,7 +880,8 @@ rt2400pci_txdone(void *data)
 		entry->tx_status.retry_count = rt2x00_get_field32(
 			txd->word0, TXD_W0_RETRY_COUNT);
 
-		ieee80211_tx_status(net_dev, entry->skb, &entry->tx_status);
+		ieee80211_tx_status(ring->net_dev,
+			entry->skb, &entry->tx_status);
 
 		rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
 		entry->skb = NULL;
@@ -975,7 +975,7 @@ rt2400pci_alloc_ring(
 	/*
 	 *Set device structure.
 	 */
-	ring->dev = rt2x00pci;
+	ring->net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
 
 	/*
 	 * Initialize work structure for deferred work.
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 21:48:21.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 21:49:08.000000000 +0200
@@ -834,10 +834,8 @@ rt2500pci_write_tx_desc(
 static void
 rt2500pci_beacondone(void *data)
 {
-	struct data_ring	*ring = (struct data_ring*)data;
-	struct rt2x00_pci	*rt2x00pci = (struct rt2x00_pci*)ring->dev;
-	struct net_device	*net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
-	struct sk_buff		*skb;
+	struct data_ring		*ring = (struct data_ring*)data;
+	struct sk_buff			*skb;
 	struct ieee80211_tx_control	beacon;
 
 	memset(&beacon, 0x00, sizeof(beacon));
@@ -845,11 +843,11 @@ rt2500pci_beacondone(void *data)
 	/*
 	 * TODO: What value should be passed as bss_idx?
 	 */
-	skb = ieee80211_beacon_get(net_dev, 0, &beacon);
+	skb = ieee80211_beacon_get(ring->net_dev, 0, &beacon);
 	if (!skb)
 		return;
 
-	rt2500pci_beacon_update(net_dev, skb, &beacon);
+	rt2500pci_beacon_update(ring->net_dev, skb, &beacon);
 
 	dev_kfree_skb_any(skb);
 }
@@ -858,8 +856,8 @@ static void
 rt2500pci_rxdone(void *data)
 {
 	struct data_ring	*ring = (struct data_ring*)data;
-	struct rt2x00_pci	*rt2x00pci = (struct rt2x00_pci*)ring->dev;
-	struct net_device	*net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
+	struct rt2x00_pci	*rt2x00pci =
+		ieee80211_dev_hw_data(ring->net_dev);
 	struct data_entry	*entry;
 	struct sk_buff		*skb;
 	struct rxd		*rxd;
@@ -899,7 +897,8 @@ rt2500pci_rxdone(void *data)
 			rt2x00pci->rx_params.ssi =
 				rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
 
-			__ieee80211_rx(net_dev, skb, &rt2x00pci->rx_params);
+			__ieee80211_rx(ring->net_dev,
+				skb, &rt2x00pci->rx_params);
 
 			rssi_count++;
 			total_rssi += rt2x00pci->rx_params.ssi;
@@ -920,8 +919,8 @@ static void
 rt2500pci_txdone(void *data)
 {
 	struct data_ring	*ring = (struct data_ring*)data;
-	struct rt2x00_pci	*rt2x00pci = (struct rt2x00_pci*)ring->dev;
-	struct net_device	*net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
+	struct rt2x00_pci	*rt2x00pci =
+		ieee80211_dev_hw_data(ring->net_dev);
 	struct data_entry	*entry;
 	struct txd		*txd;
 	int			tx_status;
@@ -966,7 +965,8 @@ rt2500pci_txdone(void *data)
 		entry->tx_status.retry_count = rt2x00_get_field32(
 			txd->word0, TXD_W0_RETRY_COUNT);
 
-		ieee80211_tx_status(net_dev, entry->skb, &entry->tx_status);
+		ieee80211_tx_status(ring->net_dev,
+			entry->skb, &entry->tx_status);
 
 		rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
 		entry->skb = NULL;
@@ -1060,7 +1060,7 @@ rt2500pci_alloc_ring(
 	/*
 	 *Set device structure.
 	 */
-	ring->dev = rt2x00pci;
+	ring->net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
 
 	/*
 	 * Initialize work structure for deferred work.
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 21:48:21.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:49:08.000000000 +0200
@@ -666,11 +666,8 @@ rt2500usb_write_tx_desc(
 static void
 rt2500usb_beacondone(void *data)
 {
-	struct data_ring	*ring = (struct data_ring*)data;
-	struct rt2x00_usb	*rt2x00usb = (struct rt2x00_usb*)ring->dev;
-	struct net_device	*net_dev = usb_get_intfdata(
-						rt2x00usb->usb_intf);
-	struct sk_buff		*skb;
+	struct data_ring		*ring = (struct data_ring*)data;
+	struct sk_buff			*skb;
 	struct ieee80211_tx_control	beacon;
 
 	memset(&beacon, 0x00, sizeof(beacon));
@@ -678,11 +675,11 @@ rt2500usb_beacondone(void *data)
 	/*
 	 * TODO: What value should be passed as bss_idx?
 	 */
-	skb = ieee80211_beacon_get(net_dev, 0, &beacon);
+	skb = ieee80211_beacon_get(ring->net_dev, 0, &beacon);
 	if (!skb)
 		return;
 
-	rt2500usb_beacon_update(net_dev, skb, &beacon);
+	rt2500usb_beacon_update(ring->net_dev, skb, &beacon);
 
 	dev_kfree_skb_any(skb);
 }
@@ -691,9 +688,8 @@ static void
 rt2500usb_rxdone(void *data)
 {
 	struct data_ring	*ring = (struct data_ring*)data;
-	struct rt2x00_usb	*rt2x00usb = (struct rt2x00_usb*)ring->dev;
-	struct net_device	*net_dev = usb_get_intfdata(
-						rt2x00usb->usb_intf);
+	struct rt2x00_usb	*rt2x00usb =
+		ieee80211_dev_hw_data(ring->net_dev);
 	struct data_entry	*entry;
 	struct sk_buff		*skb;
 	struct rxd		*rxd;
@@ -743,7 +739,8 @@ rt2500usb_rxdone(void *data)
 			rt2x00usb->rx_params.ssi =
 				rt2x00_get_field32(rxd->word1, RXD_W1_RSSI);
 
-			__ieee80211_rx(net_dev, skb, &rt2x00usb->rx_params);
+			__ieee80211_rx(ring->net_dev,
+				skb, &rt2x00usb->rx_params);
 
 			rssi_count++;
 			total_rssi += rt2x00usb->rx_params.ssi;
@@ -765,9 +762,8 @@ static void
 rt2500usb_txdone(void *data)
 {
 	struct data_ring	*ring = (struct data_ring*)data;
-	struct rt2x00_usb	*rt2x00usb = (struct rt2x00_usb*)ring->dev;
-	struct net_device	*net_dev = usb_get_intfdata(
-						rt2x00usb->usb_intf);
+	struct rt2x00_usb	*rt2x00usb =
+		ieee80211_dev_hw_data(ring->net_dev);
 	struct data_entry	*entry;
 	struct txd		*txd;
 	int			ack;
@@ -801,7 +797,8 @@ rt2500usb_txdone(void *data)
 		rt2x00_bbp_read(rt2x00usb, 0,
 			(u8*)&entry->tx_status.ack_signal);
 	
-		ieee80211_tx_status(net_dev, entry->skb, &entry->tx_status);
+		ieee80211_tx_status(ring->net_dev,
+			entry->skb, &entry->tx_status);
 	
 		entry->skb = NULL;
 	
@@ -825,7 +822,8 @@ static void
 rt2500usb_interrupt(struct urb *urb, struct pt_regs *regs)
 {
 	struct data_ring	*ring = (struct data_ring*)urb->context;
-	struct rt2x00_usb	*rt2x00usb = (struct rt2x00_usb*)ring->dev;
+	struct rt2x00_usb	*rt2x00usb =
+		ieee80211_dev_hw_data(ring->net_dev);
 
 	queue_work(rt2x00usb->workqueue, &ring->irq_work);
 }
@@ -849,7 +847,7 @@ rt2500usb_alloc_ring(
 	/*
 	 *Set device structure.
 	 */
-	ring->dev = rt2x00usb;
+	ring->net_dev = usb_get_intfdata(rt2x00usb->usb_intf);
 
 	/*
 	 * Initialize work structure for deferred work.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h	2006-04-27 21:48:21.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h	2006-04-27 21:49:08.000000000 +0200
@@ -436,9 +436,9 @@ rt2x00_rf(const struct _rt2x00_chip *chi
  */
 struct data_ring{
 	/*
-	 * Pointer to device structure.
+	 * net_device where this ring belongs to.
 	 */
-	void					*dev;
+	struct net_device			*net_dev;
 
 	/*
 	 * Work structure for bottom half interrupt handling.

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 18/32] rt2x00: Make sure device has reached requested state while suspend/resume
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 17190 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Add the *_set_state functions which makes sure
the device is switching state to awake or sleep.
Fix bad behaviour in the suspend routine,
and disable the radio before suspending.

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 21:49:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 21:49:59.000000000 +0200
@@ -653,6 +653,44 @@ rt2400pci_link_tuner(struct rt2x00_pci *
 }
 
 /*
+ * Device state switch.
+ * This will put the device to sleep, or awake it.
+ */
+static int
+rt2400pci_set_state(struct rt2x00_pci *rt2x00pci, enum dev_state state)
+{
+	u32			reg;
+	int			counter;
+	char			put_to_sleep;
+
+	put_to_sleep = (state != STATE_AWAKE);
+
+	rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
+	rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
+	rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, state);
+	rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, state);
+	rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, put_to_sleep);
+	rt2x00_register_write(rt2x00pci, PWRCSR1, reg);
+
+	/*
+	 * Device is not guarenteed to be in the requested state yet.
+	 * We must wait untill the register indicates that the
+	 * device has entered the correct state.
+	 */
+	for (counter = 0; counter < REGISTER_BUSY_COUNT; counter++) {
+		rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
+		if ((rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE) == state)
+		&& (rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE) == state))
+			return 0;
+		msleep(10);
+	}
+
+	NOTICE("Device failed to %s.\n" , put_to_sleep ? "suspend" : "resume");
+
+	return -EBUSY;
+}
+
+/*
  * TX descriptor initialization
  */
 static void
@@ -1190,6 +1228,9 @@ rt2400pci_init_registers(struct rt2x00_p
 {
 	u32		reg;
 
+	if (rt2400pci_set_state(rt2x00pci, STATE_AWAKE))
+		return -EBUSY;
+
 	rt2x00_register_write(rt2x00pci, PWRCSR0, cpu_to_le32(0x3f3b3100));
 
 	rt2x00_register_write(rt2x00pci, PSCSR0, cpu_to_le32(0x00020002));
@@ -2342,57 +2383,42 @@ rt2400pci_remove(struct pci_dev *pci_dev
 }
 
 #ifdef CONFIG_PM
-static int rt2400pci_resume(struct pci_dev *pci_dev);
-
 static int
 rt2400pci_suspend(struct pci_dev *pci_dev, pm_message_t state)
 {
 	struct net_device	*net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_pci	*rt2x00pci = ieee80211_dev_hw_data(net_dev);
-	int			counter;
-	u32			reg;
 
 	NOTICE("Going to sleep.\n");
 
-	if (ieee80211_netif_oper(net_dev, NETIF_DETACH))
-		return -EBUSY;
-
-	rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
-	rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
-	rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, 1);
-	rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, 1);
-	rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, 1);
-	rt2x00_register_write(rt2x00pci, PWRCSR1, reg);
-
 	/*
-	 * Device is not guarenteed to be asleep yet.
-	 * We must wait untill the register indicates
-	 * device has been correctly put to sleep.
+	 * If radio was enabled, stop radio and
+	 * set the resume flag to the radio will be enabled
+	 * when resuming.
 	 */
-	for (counter = 0; counter < REGISTER_BUSY_COUNT; counter++) {
-		rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
-		if ((rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE) == 1)
-		&& (rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE) == 1))
-			break;
-		NOTICE("Waiting for device to sleep.\n");
-		msleep(10);
+	if (GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+		if (net_dev->stop(net_dev))
+			return -EBUSY;
+		SET_FLAG(rt2x00pci, RADIO_RESUME);
 	}
 
-	if (counter == REGISTER_BUSY_COUNT)
-		goto exit;
-
-	if (pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1)
-	|| pci_save_state(pci_dev)
-	|| pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)))
-		goto exit;
-
-	return 0;
+	/*
+	 * Set device mode to sleep for power management.
+	 */
+	if (rt2400pci_set_state(rt2x00pci, STATE_SLEEP))
+		return -EBUSY;
 
-exit:
-	ERROR("Failed to suspend device.\n");
+	/*
+	 * Uninitialize hardware.
+	 */
+	rt2400pci_uninitialize(net_dev);
 
-	rt2400pci_resume(pci_dev);
-	return -EIO;
+	/*
+	 * Disable PCI.
+	 */
+	pci_save_state(pci_dev);
+	pci_disable_device(pci_dev);
+	return pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
 }
 
 static int
@@ -2400,25 +2426,44 @@ rt2400pci_resume(struct pci_dev *pci_dev
 {
 	struct net_device	*net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_pci	*rt2x00pci = ieee80211_dev_hw_data(net_dev);
-	u32			reg;
 
 	NOTICE("Waking up.\n");
 
+	/*
+	 * Enable PCI.
+	 */
 	if (pci_set_power_state(pci_dev, PCI_D0)
-	|| pci_restore_state(pci_dev)
-	|| pci_enable_wake(pci_dev, PCI_D0, 0)) {
+	|| pci_enable_device(pci_dev)
+	|| pci_restore_state(pci_dev)) {
 		ERROR("Failed to resume device.\n");
 		return -EIO;
 	}
 
-	rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
-	rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
-	rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, 3);
-	rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, 3);
-	rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, 0);
-	rt2x00_register_write(rt2x00pci, PWRCSR1, reg);
+	/*
+	 * Initialize hardware.
+	 */
+	if (rt2400pci_initialize(pci_dev, net_dev)) {
+		ERROR("Failed to initialize device.\n");
+		return -ENOMEM;
+	}
 
-	return ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+	/*
+	 * Set device mode to awake.
+	 */
+	if (rt2400pci_set_state(rt2x00pci, STATE_AWAKE))
+		return -EBUSY;
+
+	/*
+	 * Only enable radio when it was enabled
+	 * when we suspended.
+	 */
+	if (GET_FLAG(rt2x00pci, RADIO_RESUME)) {
+		if (net_dev->open(net_dev))
+			return -EBUSY;
+		CLEAR_FLAG(rt2x00pci, RADIO_RESUME);
+	}
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 
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 21:49:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 21:49:59.000000000 +0200
@@ -706,6 +706,44 @@ dynamic_cca_tune:
 }
 
 /*
+ * Device state switch.
+ * This will put the device to sleep, or awake it.
+ */
+static int
+rt2500pci_set_state(struct rt2x00_pci *rt2x00pci, enum dev_state state)
+{
+	u32			reg;
+	int			counter;
+	char			put_to_sleep;
+
+	put_to_sleep = (state != STATE_AWAKE);
+
+	rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
+	rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
+	rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, state);
+	rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, state);
+	rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, put_to_sleep);
+	rt2x00_register_write(rt2x00pci, PWRCSR1, reg);
+
+	/*
+	 * Device is not guarenteed to be in the requested state yet.
+	 * We must wait untill the register indicates that the
+	 * device has entered the correct state.
+	 */
+	for (counter = 0; counter < REGISTER_BUSY_COUNT; counter++) {
+		rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
+		if ((rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE) == state)
+		&& (rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE) == state))
+			return 0;
+		msleep(10);
+	}
+
+	NOTICE("Device failed to %s.\n" , put_to_sleep ? "suspend" : "resume");
+
+	return -EBUSY;
+}
+
+/*
  * TX descriptor initialization
  */
 static void
@@ -1272,6 +1310,9 @@ rt2500pci_init_registers(struct rt2x00_p
 {
 	u32		reg;
 
+	if (rt2500pci_set_state(rt2x00pci, STATE_AWAKE))
+		return -EBUSY;
+
 	rt2x00_register_write(rt2x00pci, PWRCSR0, cpu_to_le32(0x3f3b3100));
 
 	rt2x00_register_write(rt2x00pci, PSCSR0, cpu_to_le32(0x00020002));
@@ -2636,57 +2677,42 @@ rt2500pci_remove(struct pci_dev *pci_dev
 }
 
 #ifdef CONFIG_PM
-static int rt2500pci_resume(struct pci_dev *pci_dev);
-
 static int
 rt2500pci_suspend(struct pci_dev *pci_dev, pm_message_t state)
 {
 	struct net_device	*net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_pci	*rt2x00pci = ieee80211_dev_hw_data(net_dev);
-	int			counter;
-	u32			reg;
 
 	NOTICE("Going to sleep.\n");
 
-	if (ieee80211_netif_oper(net_dev, NETIF_DETACH))
-		return -EBUSY;
-
-	rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
-	rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
-	rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, 1);
-	rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, 1);
-	rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, 1);
-	rt2x00_register_write(rt2x00pci, PWRCSR1, reg);
-
 	/*
-	 * Device is not guarenteed to be asleep yet.
-	 * We must wait untill the register indicates
-	 * device has been correctly put to sleep.
+	 * If radio was enabled, stop radio and
+	 * set the resume flag to the radio will be enabled
+	 * when resuming.
 	 */
-	for (counter = 0; counter < REGISTER_BUSY_COUNT; counter++) {
-		rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
-		if ((rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE) == 1)
-		&& (rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE) == 1))
-			break;
-		NOTICE("Waiting for device to sleep.\n");
-		msleep(10);
+	if (GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+		if (net_dev->stop(net_dev))
+			return -EBUSY;
+		SET_FLAG(rt2x00pci, RADIO_RESUME);
 	}
 
-	if (counter == REGISTER_BUSY_COUNT)
-		goto exit;
-
-	if (pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1)
-	|| pci_save_state(pci_dev)
-	|| pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)))
-		goto exit;
-
-	return 0;
+	/*
+	 * Set device mode to sleep for power management.
+	 */
+	if (rt2500pci_set_state(rt2x00pci, STATE_SLEEP))
+		return -EBUSY;
 
-exit:
-	ERROR("Failed to suspend device.\n");
+	/*
+	 * Uninitialize hardware.
+	 */
+	rt2500pci_uninitialize(net_dev);
 
-	rt2500pci_resume(pci_dev);
-	return -EIO;
+	/*
+	 * Disable PCI.
+	 */
+	pci_save_state(pci_dev);
+	pci_disable_device(pci_dev);
+	return pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
 }
 
 static int
@@ -2694,25 +2720,44 @@ rt2500pci_resume(struct pci_dev *pci_dev
 {
 	struct net_device	*net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_pci	*rt2x00pci = ieee80211_dev_hw_data(net_dev);
-	u32			reg;
 
 	NOTICE("Waking up.\n");
 
+	/*
+	 * Enable PCI.
+	 */
 	if (pci_set_power_state(pci_dev, PCI_D0)
-	|| pci_restore_state(pci_dev)
-	|| pci_enable_wake(pci_dev, PCI_D0, 0)) {
+	|| pci_enable_device(pci_dev)
+	|| pci_restore_state(pci_dev)) {
 		ERROR("Failed to resume device.\n");
 		return -EIO;
 	}
 
-	rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
-	rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
-	rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, 3);
-	rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, 3);
-	rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, 0);
-	rt2x00_register_write(rt2x00pci, PWRCSR1, reg);
+	/*
+	 * Initialize hardware.
+	 */
+	if (rt2500pci_initialize(pci_dev, net_dev)) {
+		ERROR("Failed to initialize device.\n");
+		return -ENOMEM;
+	}
 
-	return ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+	/*
+	 * Set device mode to awake.
+	 */
+	if (rt2500pci_set_state(rt2x00pci, STATE_AWAKE))
+		return -EBUSY;
+
+	/*
+	 * Only enable radio when it was enabled
+	 * when we suspended.
+	 */
+	if (GET_FLAG(rt2x00pci, RADIO_RESUME)) {
+		if (net_dev->open(net_dev))
+			return -EBUSY;
+		CLEAR_FLAG(rt2x00pci, RADIO_RESUME);
+	}
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 
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 21:49:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:49:59.000000000 +0200
@@ -547,6 +547,46 @@ rt2500usb_link_tuner(struct rt2x00_usb *
 }
 
 /*
+ * Device state switch.
+ * This will put the device to sleep, or awake it.
+ */
+static int
+rt2500usb_set_state(struct rt2x00_usb *rt2x00usb, enum dev_state state)
+{
+	u16			reg;
+	int			counter;
+	char			put_to_sleep;
+
+	put_to_sleep = (state != STATE_AWAKE);
+
+	rt2x00_register_read(rt2x00usb, MAC_CSR17, &reg);
+	rt2x00_set_field16_nb(&reg, MAC_CSR17_SET_STATE, 1);
+	rt2x00_set_field16_nb(&reg, MAC_CSR17_BBP_DESIRE_STATE, state);
+	rt2x00_set_field16_nb(&reg, MAC_CSR17_RF_DESIRE_STATE, state);
+	rt2x00_set_field16_nb(&reg, MAC_CSR17_PUT_TO_SLEEP, put_to_sleep);
+	rt2x00_register_write(rt2x00usb, MAC_CSR17, reg);
+
+	/*
+	 * Device is not guarenteed to be in the requested state yet.
+	 * We must wait untill the register indicates that the
+	 * device has entered the correct state.
+	 */
+	for (counter = 0; counter < REGISTER_BUSY_COUNT; counter++) {
+		rt2x00_register_read(rt2x00usb, MAC_CSR17, &reg);
+		if ((rt2x00_get_field16_nb(
+			reg, MAC_CSR17_BBP_CURR_STATE) == state)
+		&& (rt2x00_get_field16_nb(
+			reg, MAC_CSR17_RF_CURR_STATE) == state))
+			return 0;
+		msleep(10);
+	}
+
+	NOTICE("Device failed to %s.\n" , put_to_sleep ? "suspend" : "resume");
+
+	return -EBUSY;
+}
+
+/*
  * TX descriptor initialization
  */
 static void
@@ -1082,6 +1122,9 @@ rt2500usb_init_registers(struct rt2x00_u
 {
 	u16			reg;
 
+	if (rt2500usb_set_state(rt2x00usb, STATE_AWAKE))
+		return -EBUSY;
+
 	rt2x00_vendor_request(rt2x00usb, USB_DEVICE_MODE,
 		USB_VENDOR_REQUEST_OUT, USB_MODE_TEST, 0x00, NULL, 0);
 	rt2x00_vendor_request(rt2x00usb, USB_SINGLE_WRITE,
@@ -2221,44 +2264,42 @@ rt2500usb_disconnect(struct usb_interfac
 }
 
 #ifdef CONFIG_PM
-static int rt2500usb_resume(struct usb_interface *usb_intf);
-
 static int
 rt2500usb_suspend(struct usb_interface *usb_intf, pm_message_t state)
 {
 	struct net_device	*net_dev = usb_get_intfdata(usb_intf);
 	struct rt2x00_usb	*rt2x00usb = ieee80211_dev_hw_data(net_dev);
-	int			counter;
-	u16			reg;
 
 	NOTICE("Going to sleep.\n");
 
-	if (ieee80211_netif_oper(net_dev, NETIF_DETACH))
+	/*
+	 * If radio was enabled, stop radio and
+	 * set the resume flag to the radio will be enabled
+	 * when resuming.
+	 */
+	if (GET_FLAG(rt2x00usb, RADIO_ENABLED)) {
+		if (net_dev->stop(net_dev))
+			return -EBUSY;
+		SET_FLAG(rt2x00usb, RADIO_RESUME);
+	}
+
+	/*
+	 * Set device mode to sleep for power management.
+	 */
+	if (rt2500usb_set_state(rt2x00usb, STATE_SLEEP))
 		return -EBUSY;
 
-	rt2x00_register_read(rt2x00usb, MAC_CSR17, &reg);
-	rt2x00_set_field16_nb(&reg, MAC_CSR17_SET_STATE, 1);
-	rt2x00_set_field16_nb(&reg, MAC_CSR17_BBP_DESIRE_STATE, 1);
-	rt2x00_set_field16_nb(&reg, MAC_CSR17_RF_DESIRE_STATE, 1);
-	rt2x00_set_field16_nb(&reg, MAC_CSR17_PUT_TO_SLEEP, 1);
-	rt2x00_register_write(rt2x00usb, MAC_CSR17, reg);
+	/*
+	 * Uninitialize hardware.
+	 */
+	rt2500usb_uninitialize(net_dev);
 
 	/*
-	 * Device is not guarenteed to be asleep yet.
-	 * We must wait untill the register indicates
-	 * device has been correctly put to sleep.
+	 * Decrease usbdev refcount.
 	 */
-	for (counter = 0; counter < REGISTER_BUSY_COUNT; counter++) {
-		rt2x00_register_read(rt2x00usb, MAC_CSR17, &reg);
-		if ((rt2x00_get_field16_nb(reg, MAC_CSR17_BBP_CURR_STATE) == 1)
-		&& (rt2x00_get_field16_nb(reg, MAC_CSR17_RF_CURR_STATE) == 1))
-	return 0;
-		NOTICE("Waiting for device to sleep.\n");
-		msleep(10);
-	}
+	usb_put_dev(interface_to_usbdev(usb_intf));
 
-	rt2500usb_resume(usb_intf);
-	return -EIO;
+	return 0;
 }
 
 static int
@@ -2266,18 +2307,39 @@ rt2500usb_resume(struct usb_interface *u
 {
 	struct net_device	*net_dev = usb_get_intfdata(usb_intf);
 	struct rt2x00_usb	*rt2x00usb = ieee80211_dev_hw_data(net_dev);
-	u16			reg;
 
 	NOTICE("Waking up.\n");
 
-	rt2x00_register_read(rt2x00usb, MAC_CSR17, &reg);
-	rt2x00_set_field16_nb(&reg, MAC_CSR17_SET_STATE, 1);
-	rt2x00_set_field16_nb(&reg, MAC_CSR17_BBP_DESIRE_STATE, 3);
-	rt2x00_set_field16_nb(&reg, MAC_CSR17_RF_DESIRE_STATE, 3);
-	rt2x00_set_field16_nb(&reg, MAC_CSR17_PUT_TO_SLEEP, 0);
-	rt2x00_register_write(rt2x00usb, MAC_CSR17, reg);
+	/*
+	 * Increase usbdev refcount.
+	 */
+	usb_get_dev(interface_to_usbdev(usb_intf));
 
-	return ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+	/*
+	 * Initialize hardware.
+	 */
+	if (rt2500usb_initialize(usb_intf, net_dev)) {
+		ERROR("Failed to initialize device.\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * Set device mode to awake.
+	 */
+	if (rt2500usb_set_state(rt2x00usb, STATE_AWAKE))
+		return -EBUSY;
+
+	/*
+	 * Only enable radio when it was enabled
+	 * when we suspended.
+	 */
+	if (GET_FLAG(rt2x00usb, RADIO_RESUME)) {
+		if (net_dev->open(net_dev))
+			return -EBUSY;
+		CLEAR_FLAG(rt2x00usb, RADIO_RESUME);
+	}
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 19/32] rt2x00: Fix panics in interrupt handlers
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 3624 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Fix panics when the interrupt handlers are being
run while the ring is empty.
During the interrupt handling break the loop
correctly when an error has been detected,
more work is being done after the loop.

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 21:49:59.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 21:50:36.000000000 +0200
@@ -844,7 +844,7 @@ rt2400pci_rxdone(void *data)
 		&& !rt2x00_get_field32(rxd->word0, RXD_W0_PHYSICAL_ERROR)) {
 			skb = dev_alloc_skb(size + NET_IP_ALIGN);
 			if (!skb)
-				return;
+				break;
 
 			skb_reserve(skb, NET_IP_ALIGN);
 
@@ -859,7 +859,7 @@ rt2400pci_rxdone(void *data)
 
 		rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
 
-		rt2x00_ring_index_inc(&rt2x00pci->rx);
+		rt2x00_ring_index_inc(ring);
 	}
 
 	/*
@@ -879,7 +879,7 @@ rt2400pci_txdone(void *data)
 	int			tx_status;
 	int			ack;
 
-	do {
+	 while (!rt2x00_ring_empty(ring)) {
 		entry = rt2x00_get_data_entry_done(ring);
 		txd = entry->desc_addr;
 
@@ -925,7 +925,7 @@ rt2400pci_txdone(void *data)
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(ring);
-	} while (!rt2x00_ring_empty(ring));
+	}
 
 	/*
 	 * Check if we are waiting on an empty queue
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 21:49:59.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 21:50:36.000000000 +0200
@@ -926,7 +926,7 @@ rt2500pci_rxdone(void *data)
 		&& !rt2x00_get_field32(rxd->word0, RXD_W0_PHYSICAL_ERROR)) {
 			skb = dev_alloc_skb(size + NET_IP_ALIGN);
 			if (!skb)
-				return;
+				break;
 
 			skb_reserve(skb, NET_IP_ALIGN);
 
@@ -943,7 +943,7 @@ rt2500pci_rxdone(void *data)
 		}
 		rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
 
-		rt2x00_ring_index_inc(&rt2x00pci->rx);
+		rt2x00_ring_index_inc(ring);
 	}
 
 	/*
@@ -964,7 +964,7 @@ rt2500pci_txdone(void *data)
 	int			tx_status;
 	int			ack;
 
-	do {
+	 while (!rt2x00_ring_empty(ring)) {
 		entry = rt2x00_get_data_entry_done(ring);
 		txd = entry->desc_addr;
 
@@ -1010,7 +1010,7 @@ rt2500pci_txdone(void *data)
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(ring);
-	} while (!rt2x00_ring_empty(ring));
+	}
 
 	/*
 	 * Check if we are waiting on an empty queue
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 21:49:59.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:50:36.000000000 +0200
@@ -808,7 +808,7 @@ rt2500usb_txdone(void *data)
 	struct txd		*txd;
 	int			ack;
 
-	do {
+	 while (!rt2x00_ring_empty(ring)) {
 		entry = rt2x00_get_data_entry_done(ring);
 		txd = entry->desc_addr;
 
@@ -843,7 +843,7 @@ rt2500usb_txdone(void *data)
 		entry->skb = NULL;
 	
 		rt2x00_ring_index_done_inc(entry->ring);
-	} while (!rt2x00_ring_empty(ring));
+	}
 
 	/*
 	 * Check if we are waiting on an empty queue

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 20/32] rt2x00: byte ordering correctness
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 3998 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Fix various little/big endian conversions.
rt2500pci should use cpu_to_le32 and rt2500usb should not.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>

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 21:50:36.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 21:51:11.000000000 +0200
@@ -441,7 +441,7 @@ rt2500pci_config_channel(struct rt2x00_p
 	txpower = (txpower > 31) ? 31 : txpower;
 
 	if (rt2x00_rf(&rt2x00pci->chip, RF2525E) && channel == 14)
-		rf4 |= 0x00000010;
+		rf4 |= cpu_to_le32(0x00000010);
 
 	if (rt2x00_rf(&rt2x00pci->chip, RF5222)) {
 		if (channel < 14) {
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 21:50:36.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:51:11.000000000 +0200
@@ -324,20 +324,20 @@ rt2500usb_config_channel(struct rt2x00_u
 
 	if (rt2x00_rf(&rt2x00usb->chip, RF5222)) {
 		if (channel < 14) {
-			rf1 = cpu_to_le32(0x00022020);
-			rf4 = cpu_to_le32(0x00000a0b);
+			rf1 = 0x00022020;
+			rf4 = 0x00000a0b;
 		} else if (channel == 14) {
-			rf1 = cpu_to_le32(0x00022010);
-			rf4 = cpu_to_le32(0x00000a1b);
+			rf1 = 0x00022010;
+			rf4 = 0x00000a1b;
 		} else if (channel < 64) {
-			rf1 = cpu_to_le32(0x00022010);
-			rf4 = cpu_to_le32(0x00000a1f);
+			rf1 = 0x00022010;
+			rf4 = 0x00000a1f;
 		} else if (channel < 140) {
-			rf1 = cpu_to_le32(0x00022010);
-			rf4 = cpu_to_le32(0x00000a0f);
+			rf1 = 0x00022010;
+			rf4 = 0x00000a0f;
 		} else if (channel < 161) {
-			rf1 = cpu_to_le32(0x00022020);
-			rf4 = cpu_to_le32(0x00000a07);
+			rf1 = 0x00022020;
+			rf4 = 0x00000a07;
 		}
 	}
 
@@ -1829,7 +1829,7 @@ rt2500usb_init_hw_channels(struct rt2x00
 		};
 
 		for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
-			channels[counter].val = cpu_to_le32(vals[counter]);
+			channels[counter].val = vals[counter];
 	} else if (rt2x00_rf(&rt2x00usb->chip, RF2523)
 	|| rt2x00_rf(&rt2x00usb->chip, RF2524)
 	|| rt2x00_rf(&rt2x00usb->chip, RF2525)) {
@@ -1841,8 +1841,7 @@ rt2500usb_init_hw_channels(struct rt2x00
 		};
 
 		for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
-				channels[counter].val =
-				cpu_to_le32(vals[counter] | rf2_base);
+			channels[counter].val = vals[counter] | rf2_base;
 	} else if (rt2x00_rf(&rt2x00usb->chip, RF2525E)) {
 		u32 vals[] = {
 			0x0000089a, 0x0000089e, 0x0000089e, 0x000008a2,
@@ -1852,7 +1851,7 @@ rt2500usb_init_hw_channels(struct rt2x00
 		};
 
 		for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
-			channels[counter].val = cpu_to_le32(vals[counter]);
+			channels[counter].val = vals[counter];
 	} else if (rt2x00_rf(&rt2x00usb->chip, RF5222)) {
 		static u32 vals[] = {
 			0x00001136, 0x0000113a, 0x0000113e, 0x00001182,
@@ -1868,7 +1867,7 @@ rt2500usb_init_hw_channels(struct rt2x00
 		};
 
 		for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
-			channels[counter].val = cpu_to_le32(vals[counter]);
+			channels[counter].val = vals[counter];
 		}
 
 		/*
@@ -1895,9 +1894,9 @@ rt2500usb_init_hw_channels(struct rt2x00
 	 */
 	for (counter = 0; counter < ARRAY_SIZE(rf); counter++) {
 		if (rt2x00_rf(&rt2x00usb->chip, rf[counter].chip)) {
-			rt2x00usb->rf1 = cpu_to_le32(rf[counter].val[0]);
-			rt2x00usb->rf3 = cpu_to_le32(rf[counter].val[1]);
-			rt2x00usb->rf4 = cpu_to_le32(rf[counter].val[2]);
+			rt2x00usb->rf1 = rf[counter].val[0];
+			rt2x00usb->rf3 = rf[counter].val[1];
+			rt2x00usb->rf4 = rf[counter].val[2];
 		}
 	}
 }

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 21/32] rt2x00: PRIO ring should be treated as regular TX ring
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 3215 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Remove PRIO_ENTRIES define, the prio ring
should be treated as a regular TX ring.

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 21:50:36.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 21:52:01.000000000 +0200
@@ -1145,7 +1145,7 @@ rt2400pci_allocate_rings(struct rt2x00_p
 		ATIM_ENTRIES, MGMT_FRAME_SIZE, sizeof(struct txd))
 	|| rt2400pci_alloc_ring(
 		rt2x00pci, &rt2x00pci->prio, rt2400pci_txdone,
-		PRIO_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd))
+		TX_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd))
 	|| rt2400pci_alloc_ring(
 		rt2x00pci, &rt2x00pci->beacon, rt2400pci_beacondone,
 		BEACON_ENTRIES, MGMT_FRAME_SIZE, sizeof(struct txd))) {
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 21:51:11.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 21:52:01.000000000 +0200
@@ -1227,7 +1227,7 @@ rt2500pci_allocate_rings(struct rt2x00_p
 		ATIM_ENTRIES, MGMT_FRAME_SIZE, sizeof(struct txd))
 	|| rt2500pci_alloc_ring(
 		rt2x00pci, &rt2x00pci->prio, rt2500pci_txdone,
-		PRIO_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd))
+		TX_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd))
 	|| rt2500pci_alloc_ring(
 		rt2x00pci, &rt2x00pci->beacon, rt2500pci_beacondone,
 		BEACON_ENTRIES, MGMT_FRAME_SIZE, sizeof(struct txd))) {
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 21:51:11.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:52:01.000000000 +0200
@@ -996,7 +996,7 @@ rt2500usb_allocate_rings(struct rt2x00_u
 		ATIM_ENTRIES, MGMT_FRAME_SIZE, sizeof(struct txd))
 	|| rt2500usb_alloc_ring(
 		rt2x00usb, &rt2x00usb->prio, &rt2500usb_txdone,
-		PRIO_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd))
+		TX_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd))
 	|| rt2500usb_alloc_ring(
 		rt2x00usb, &rt2x00usb->beacon, &rt2500usb_beacondone,
 		BEACON_ENTRIES, MGMT_FRAME_SIZE, sizeof(struct txd))) {
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h	2006-04-27 21:49:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h	2006-04-27 21:52:01.000000000 +0200
@@ -90,7 +90,6 @@ static int rt2x00_debug_level = 0;
 #define RX_ENTRIES			12
 #define TX_ENTRIES			12
 #define ATIM_ENTRIES			1
-#define PRIO_ENTRIES			6
 #define BEACON_ENTRIES			1
 
 /*

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 22/32] rt2x00: Allocate ring structures in single array
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 406 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Allocate all ring structures seperately and
as an array of rings. This will make the
rt2x00_pci and rt2x00_usb structures more generic
for all rt2x00 modules.
Use seperate function to convert a dscape ring ID
to the address of the actual ring.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>

Available on server:

http://mendiosus.nl/rt2x00/rt2x00-22-rings.diff

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 23/32] rt2x00: Make correct cast in USB interrupt
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 1760 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

The USB interrupt handler receives the entry
in the ring and not the ring itself.
Also check if the status indicates an error
before queueing the work.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>

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 21:53:13.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:54:33.000000000 +0200
@@ -856,11 +856,14 @@ rt2500usb_txdone(void *data)
 static void
 rt2500usb_interrupt(struct urb *urb, struct pt_regs *regs)
 {
-	struct data_ring	*ring = (struct data_ring*)urb->context;
+	struct data_entry	*entry = (struct data_entry*)urb->context;
 	struct rt2x00_usb	*rt2x00usb =
-		ieee80211_dev_hw_data(ring->net_dev);
+		ieee80211_dev_hw_data(entry->ring->net_dev);
 
-	queue_work(rt2x00usb->workqueue, &ring->irq_work);
+	if (urb->status)
+		return;
+
+	queue_work(rt2x00usb->workqueue, &entry->ring->irq_work);
 }
 
 /*
@@ -1064,7 +1067,6 @@ rt2500usb_init_txring(struct rt2x00_usb 
 	}
 }
 
-
 static int
 rt2500usb_init_rings(struct rt2x00_usb *rt2x00usb)
 {
@@ -1798,7 +1800,7 @@ rt2500usb_init_hw_channels(struct rt2x00
 		for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
 			channels[counter].val = vals[counter] | rf2_base;
 	} else if (rt2x00_rf(&rt2x00usb->chip, RF2525E)) {
-		u32 vals[] = {
+		static u32 vals[] = {
 			0x0000089a, 0x0000089e, 0x0000089e, 0x000008a2,
 			0x000008a2, 0x000008a6, 0x000008a6, 0x000008aa,
 			0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2,

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 26/32] rt2x00: Move all USB and PCI common data into seperate headers
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 364 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Now that rt2x00_pci and rt2x00_usb structures in the various
headers are generic enough, add 2 header files rt2x00pci and rt2x00usb
and make them contain all common information of the PCI or USB modules.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>

Available on server:

http://mendiosus.nl/rt2x00/rt2x00-26-dev.diff

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 24/32] rt2x00: Use correct desc_addr and data_addr
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 7557 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

USB buffer don't have a seperate descriptor ring and data ring.
The location of the descriptor area and data area depends
on the type of ring. Add functions to determine the correct
location and use these instead of the invalid desc_addr and data_addr
pointers.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>

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 21:54:33.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:55:14.000000000 +0200
@@ -740,7 +740,7 @@ rt2500usb_rxdone(void *data)
 
 	while (1) {
 		entry = rt2x00_get_data_entry(ring);
-		rxd = entry->desc_addr;
+		rxd = rt2x00usb_rxdesc_addr(entry);
 
 		/*
 		* There has been a problem. Ignore packet.
@@ -769,7 +769,8 @@ rt2500usb_rxdone(void *data)
 
 			skb_reserve(skb, NET_IP_ALIGN);
 
-			memcpy(skb_put(skb, size), entry->data_addr, size);
+			memcpy(skb_put(skb, size),
+				rt2x00usb_rxdata_addr(entry), size);
 
 			rt2x00usb->rx_params.ssi =
 				rt2x00_get_field32(rxd->word1, RXD_W1_RSSI);
@@ -805,7 +806,7 @@ rt2500usb_txdone(void *data)
 
 	 while (!rt2x00_ring_empty(ring)) {
 		entry = rt2x00_get_data_entry_done(ring);
-		txd = entry->desc_addr;
+		txd = rt2x00usb_txdesc_addr(entry);
 
 		ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
 	
@@ -937,16 +938,14 @@ rt2500usb_alloc_ring(
 			entry[counter].urb = usb_alloc_urb(0, GFP_KERNEL);
 		else
 			entry[counter].urb = NULL;
-		if (entry[counter].urb == NULL)
+		if (!entry[counter].urb)
 			status = -ENOMEM;
 		entry[counter].skb = NULL;
-		entry[counter].desc_addr = ring->data_addr
-			+ (counter * ring->desc_size);
 		entry[counter].data_addr = ring->data_addr
-			+ (ring->stats.limit * ring->desc_size)
+			+ (counter * ring->desc_size)
 			+ (counter * ring->data_size);
 		entry[counter].data_dma = ring->data_dma
-			+ (ring->stats.limit * ring->desc_size)
+			+ (counter * ring->desc_size)
 			+ (counter * ring->data_size);
 	}
 
@@ -959,7 +958,7 @@ rt2500usb_free_ring(struct rt2x00_usb *r
 	struct	data_entry	*entry;
 	u8			counter;
 
-	if (ring->entry)
+	if (!ring->entry)
 		goto exit;
 
 	entry = (struct data_entry*)ring->entry;
@@ -1091,9 +1090,9 @@ rt2500usb_init_registers(struct rt2x00_u
 		return -EBUSY;
 
 	rt2x00_vendor_request(rt2x00usb, USB_DEVICE_MODE,
-		USB_VENDOR_REQUEST_OUT, USB_MODE_TEST, 0x00, NULL, 0);
+		USB_VENDOR_REQUEST_OUT, 0x00, USB_MODE_TEST, NULL, 0);
 	rt2x00_vendor_request(rt2x00usb, USB_SINGLE_WRITE,
-		USB_VENDOR_REQUEST_OUT, 0x0308, 0x00f0, NULL, 0);
+		USB_VENDOR_REQUEST_OUT, 0x0308, 0xf0, NULL, 0);
 
 	rt2x00_register_write(rt2x00usb, TXRX_CSR2, 0x0001);
 	rt2x00_register_write(rt2x00usb, MAC_CSR13, 0x1111);
@@ -1242,9 +1241,9 @@ rt2500usb_tx(struct net_device *net_dev,
 		return NET_RX_DROP;
 
 	entry = rt2x00_get_data_entry(ring);
-	txd = entry->desc_addr;
+	txd = rt2x00usb_txdesc_addr(entry);
 
-	memcpy(entry->data_addr, skb->data, skb->len);
+	memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
 	rt2500usb_write_tx_desc(rt2x00usb, txd, skb, control);
 	entry->skb = skb;
 
@@ -1621,8 +1620,9 @@ rt2500usb_beacon_update(struct net_devic
 	 */
 	control->queue = IEEE80211_TX_QUEUE_BEACON;
 
-	memcpy(entry->data_addr, skb->data, skb->len);
-	rt2500usb_write_tx_desc(rt2x00usb, entry->desc_addr, skb, control);
+	memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
+	rt2500usb_write_tx_desc(rt2x00usb,
+		rt2x00usb_txdesc_addr(entry), skb, control);
 
 	usb_fill_bulk_urb(
 		entry->urb,
@@ -1658,6 +1658,14 @@ rt2500usb_init_eeprom(struct rt2x00_usb 
 	rt2x00_set_chip(&rt2x00usb->chip, RT2570,
 		rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE));
 
+	if (!rt2x00_rf(&rt2x00usb->chip, RF2522)
+	&& !rt2x00_rf(&rt2x00usb->chip, RF2523)
+	&& !rt2x00_rf(&rt2x00usb->chip, RF2524)
+	&& !rt2x00_rf(&rt2x00usb->chip, RF2525)
+	&& !rt2x00_rf(&rt2x00usb->chip, RF2525E)
+	&& !rt2x00_rf(&rt2x00usb->chip, RF5222))
+		return -ENODEV;
+
 	/*
 	 * 3 - Identify default antenna configuration.
 	 * Ralink devices have have antenna options for both TX as RX.
@@ -1691,26 +1699,27 @@ rt2500usb_init_mac(struct rt2x00_usb *rt
 {
 	struct net_device	*net_dev = usb_get_intfdata(
 						rt2x00usb->usb_intf);
-	u16			reg[3] = {0, 0, 0};
+	u16			eeprom[3] = {0, 0, 0};
 
 	/*
 	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_eeprom_multiread(rt2x00usb, EEPROM_MAC_ADDR, &reg[0], 6);
+	rt2x00_eeprom_multiread(rt2x00usb, EEPROM_MAC_ADDR, &eeprom[0], 6);
 
-	net_dev->dev_addr[0] = rt2x00_get_field16(reg[0], MAC_CSR2_BYTE0);
-	net_dev->dev_addr[1] = rt2x00_get_field16(reg[0], MAC_CSR2_BYTE1);
-	net_dev->dev_addr[2] = rt2x00_get_field16(reg[1], MAC_CSR3_BYTE2);
-	net_dev->dev_addr[3] = rt2x00_get_field16(reg[1], MAC_CSR3_BYTE3);
-	net_dev->dev_addr[4] = rt2x00_get_field16(reg[2], MAC_CSR4_BYTE4);
-	net_dev->dev_addr[5] = rt2x00_get_field16(reg[2], MAC_CSR4_BYTE5);
+	net_dev->dev_addr[0] = rt2x00_get_field16(eeprom[0], MAC_CSR2_BYTE0);
+	net_dev->dev_addr[1] = rt2x00_get_field16(eeprom[0], MAC_CSR2_BYTE1);
+	net_dev->dev_addr[2] = rt2x00_get_field16(eeprom[1], MAC_CSR3_BYTE2);
+	net_dev->dev_addr[3] = rt2x00_get_field16(eeprom[1], MAC_CSR3_BYTE3);
+	net_dev->dev_addr[4] = rt2x00_get_field16(eeprom[2], MAC_CSR4_BYTE4);
+	net_dev->dev_addr[5] = rt2x00_get_field16(eeprom[2], MAC_CSR4_BYTE5);
 
 	net_dev->addr_len = 6;
 
 	/*
 	 * Write MAC address to register.
 	 */
-	rt2x00_register_multiwrite(rt2x00usb, MAC_CSR2, &reg[0], sizeof(reg));
+	rt2x00_register_multiwrite(rt2x00usb, MAC_CSR2,
+		&eeprom[0], sizeof(reg));
 
 	return 0;
 }
@@ -1730,7 +1739,7 @@ rt2500usb_init_hw_channels(struct rt2x00
 		{ RF2523,	{ 0x00022010, 0x000e0111, 0x00000a1b } },
 		{ RF2524,	{ 0x00032020, 0x00000101, 0x00000a1b } },
 		{ RF2525,	{ 0x00022020, 0x00060111, 0x00000a1b } },
-		{ RF2525E,	{ 0x00022020, 0x00060111, 0x00000000 } },
+		{ RF2525E,	{ 0x00022010, 0x00060111, 0x00000000 } },
 		{ RF5222,	{ 0x00000000, 0x00000101, 0x00000000 } }
 	};
 
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h	2006-04-27 21:53:13.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h	2006-04-27 21:55:14.000000000 +0200
@@ -683,6 +683,36 @@ struct data_entry{
 } __attribute__ ((packed));
 
 /*
+ * The location of the descriptor is variating and depends
+ * on the fact if it is a TX or RX ring and the length of the packet.
+ * We need some small handlers to properly access the descriptors.
+ */
+static inline void*
+rt2x00usb_rxdata_addr(struct data_entry *entry)
+{
+	return entry->data_addr;
+}
+
+static inline void*
+rt2x00usb_rxdesc_addr(struct data_entry *entry)
+{
+	return entry->data_addr +
+		(entry->urb->actual_length - entry->ring->desc_size);
+}
+
+static inline void*
+rt2x00usb_txdata_addr(struct data_entry *entry)
+{
+	return entry->data_addr + entry->ring->desc_size;
+}
+
+static inline void*
+rt2x00usb_txdesc_addr(struct data_entry *entry)
+{
+	return entry->data_addr;
+}
+
+/*
  * Device specific structure.
  */
 struct rt2x00_usb{

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 25/32] rt2x00: Add flag handlers
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 12734 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Add flag handlers to set the state and capabilities of
the driver.

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 21:53:13.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 21:56:05.000000000 +0200
@@ -1099,7 +1099,7 @@ rt2400pci_allocate_rings(struct rt2x00_p
 		return -ENOMEM;
 	}
 
-	rt2x00pci->atim_available = 1;
+	SET_FLAG(rt2x00pci, ATIM_AVAILABLE);
 
 	if (rt2400pci_alloc_ring(
 		rt2x00pci, &rt2x00pci->ring[RING_RX], rt2400pci_rxdone,
@@ -1549,6 +1549,8 @@ rt2400pci_open(struct net_device *net_de
 	rt2x00_set_field32(&reg, CSR8_RXDONE, 0);
 	rt2x00_register_write(rt2x00pci, CSR8, reg);
 
+	SET_FLAG(rt2x00pci, RADIO_ENABLED);
+
 	return 0;
 
 exit_fail:
@@ -1563,6 +1565,8 @@ rt2400pci_stop(struct net_device *net_de
 	struct rt2x00_pci	*rt2x00pci = ieee80211_dev_hw_data(net_dev);
 	u32			reg;
 
+	CLEAR_FLAG(rt2x00pci, RADIO_ENABLED);
+
 	rt2x00_register_write(rt2x00pci, PWRCSR0, 0);
 
 	/*
@@ -1972,16 +1976,11 @@ rt2400pci_init_eeprom(struct rt2x00_pci 
 	rt2x00pci->led_mode = rt2x00_get_field16(eeprom,
 				EEPROM_ANTENNA_LED_MODE);
 
-#ifdef CONFIG_RT2400PCI_BUTTON
 	/*
 	 * 6 - Detect if this device has an hardware controlled radio.
-	 * If this device is not hardware controlled, disable polling timer.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-		rt2x00pci->button_status = BUTTON_STATUS_OFF;
-	else
-		rt2x00pci->button_status = BUTTON_STATUS_UNAVAILABLE;
-#endif /* CONFIG_RT2400PCI_BUTTON */
+		SET_FLAG(rt2x00pci, HARDWARE_BUTTON);
 
 	/*
 	 * 7 - Read BBP data from EEPROM and store in private structure.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h	2006-04-27 21:53:13.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h	2006-04-27 21:56:05.000000000 +0200
@@ -868,6 +868,11 @@ struct data_entry{
  * Device specific structure.
  */
 struct rt2x00_pci{
+	/*
+	 * Device flags.
+	 */
+	unsigned int				flags;
+
 #ifdef CONFIG_RT2400PCI_BUTTON
 	/*
 	 * ACPI device for generation of ACPI events.
@@ -935,8 +940,6 @@ struct rt2x00_pci{
 	 */
 	int					false_cca;
 
-	int					atim_available;
-
 	/*
 	 * EEPROM bus width.
 	 */
@@ -987,7 +990,7 @@ rt2x00pci_get_ring(struct rt2x00_pci *rt
 {
 	u8					atim;
 
-	atim = rt2x00pci->atim_available;
+	atim = GET_FLAG(rt2x00pci, ATIM_AVAILABLE);
 
 	/*
 	 * Check if the rings have been allocated.
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 21:53:13.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 21:56:05.000000000 +0200
@@ -1180,7 +1180,7 @@ rt2500pci_allocate_rings(struct rt2x00_p
 		return -ENOMEM;
 	}
 
-	rt2x00pci->atim_available = 1;
+	SET_FLAG(rt2x00pci, ATIM_AVAILABLE);
 
 	if (rt2500pci_alloc_ring(
 		rt2x00pci, &rt2x00pci->ring[RING_RX], rt2500pci_rxdone,
@@ -1657,6 +1657,8 @@ rt2500pci_open(struct net_device *net_de
 	rt2x00_set_field32(&reg, CSR8_RXDONE, 0);
 	rt2x00_register_write(rt2x00pci, CSR8, reg);
 
+	SET_FLAG(rt2x00pci, RADIO_ENABLED);
+
 	return 0;
 
 exit_fail:
@@ -1671,6 +1673,8 @@ rt2500pci_stop(struct net_device *net_de
 	struct rt2x00_pci	*rt2x00pci = ieee80211_dev_hw_data(net_dev);
 	u32			reg;
 
+	CLEAR_FLAG(rt2x00pci, RADIO_ENABLED);
+
 	rt2x00_register_write(rt2x00pci, PWRCSR0, 0);
 
 	/*
@@ -1929,7 +1933,7 @@ rt2500pci_conf_tx(struct net_device *net
 
 	/*
 	 * The passed variables are stored as real value ((2^n)-1).
-	 * RT2400 registers require to know the bit number 'n'.
+	 * RT2500 registers require to know the bit number 'n'.
 	 */
 	if (params->cw_min)
 		ring->tx_params.cw_min = HIGHEST_BIT16(params->cw_min) + 1;
@@ -2075,16 +2079,11 @@ rt2500pci_init_eeprom(struct rt2x00_pci 
 	rt2x00pci->led_mode = rt2x00_get_field16(eeprom,
 				EEPROM_ANTENNA_LED_MODE);
 
-#ifdef CONFIG_RT2500PCI_BUTTON
 	/*
 	 * 6 - Detect if this device has an hardware controlled radio.
-	 * If this device is not hardware controlled, disable polling timer.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-		rt2x00pci->button_status = BUTTON_STATUS_OFF;
-	else
-		rt2x00pci->button_status = BUTTON_STATUS_UNAVAILABLE;
-#endif /* CONFIG_RT2500PCI_BUTTON */
+		SET_FLAG(rt2x00pci, HARDWARE_BUTTON);
 
 	/*
 	 * 7 - Read BBP data from EEPROM and store in private structure.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h	2006-04-27 21:53:13.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h	2006-04-27 21:56:05.000000000 +0200
@@ -1137,6 +1137,11 @@ struct data_entry{
  * Device specific structure.
  */
 struct rt2x00_pci{
+	/*
+	 * Device flags.
+	 */
+	unsigned int				flags;
+
 #ifdef CONFIG_RT2500PCI_BUTTON
 	/*
 	 * ACPI device for generation of ACPI events.
@@ -1200,8 +1205,6 @@ struct rt2x00_pci{
 	 */
 	struct ieee80211_rx_status		rx_params;
 
-	u16					atim_available;
-
 	/*
 	 * EEPROM bus width.
 	 */
@@ -1252,7 +1255,7 @@ rt2x00pci_get_ring(struct rt2x00_pci *rt
 {
 	u8					atim;
 
-	atim = rt2x00pci->atim_available;
+	atim = GET_FLAG(rt2x00pci, ATIM_AVAILABLE);
 
 	/*
 	 * Check if the rings have been allocated.
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 21:55:14.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:56:05.000000000 +0200
@@ -742,10 +742,14 @@ rt2500usb_rxdone(void *data)
 		entry = rt2x00_get_data_entry(ring);
 		rxd = rt2x00usb_rxdesc_addr(entry);
 
+		if (GET_FLAG(entry, ENTRY_OWNER_NIC))
+			break;
+
 		/*
-		* There has been a problem. Ignore packet.
-		*/
+		 * There has been a problem. Ignore packet.
+		 */
 		if (entry->urb->status) {
+			SET_FLAG(entry, ENTRY_OWNER_NIC);
 			usb_submit_urb(entry->urb, GFP_ATOMIC);
 			rt2x00_ring_index_inc(ring);
 			continue;
@@ -782,6 +786,7 @@ rt2500usb_rxdone(void *data)
 			total_rssi += rt2x00usb->rx_params.ssi;
 		}
 
+		SET_FLAG(entry, ENTRY_OWNER_NIC);
 		usb_submit_urb(entry->urb, GFP_ATOMIC);
 
 		rt2x00_ring_index_inc(ring);
@@ -808,6 +813,9 @@ rt2500usb_txdone(void *data)
 		entry = rt2x00_get_data_entry_done(ring);
 		txd = rt2x00usb_txdesc_addr(entry);
 
+		if (GET_FLAG(entry, ENTRY_OWNER_NIC))
+			break;
+
 		ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
 	
 		/*
@@ -861,6 +869,9 @@ rt2500usb_interrupt(struct urb *urb, str
 	struct rt2x00_usb	*rt2x00usb =
 		ieee80211_dev_hw_data(entry->ring->net_dev);
 
+	if (!GET_FLAG(rt2x00usb, RADIO_ENABLED))
+		return;
+
 	if (urb->status)
 		return;
 
@@ -989,7 +1000,7 @@ rt2500usb_allocate_rings(struct rt2x00_u
 		return -ENOMEM;
 	}
 
-	rt2x00usb->atim_available = 1;
+	SET_FLAG(rt2x00usb, ATIM_AVAILABLE);
 
 	if (rt2500usb_alloc_ring(
 		rt2x00usb, &rt2x00usb->ring[RING_RX], &rt2500usb_rxdone,
@@ -1049,6 +1060,7 @@ rt2500usb_init_rxring(struct rt2x00_usb 
 			ring->entry_size + ring->desc_size,
 			rt2500usb_interrupt,
 			&entry[counter]);
+		SET_FLAG(&entry[counter], ENTRY_OWNER_NIC | ENTRY_TYPE_RX);
 		usb_submit_urb(entry[counter].urb, GFP_ATOMIC);
 	}
 }
@@ -1063,6 +1075,7 @@ rt2500usb_init_txring(struct rt2x00_usb 
 	for (counter = 0; counter < ring->stats.limit; counter++) {
 		entry[counter].urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 		entry[counter].urb->transfer_dma = entry[counter].data_dma;
+		CLEAR_FLAGS(&entry[counter]);
 	}
 }
 
@@ -1223,6 +1236,8 @@ rt2500usb_tx(struct net_device *net_dev,
 	struct sk_buff *skb, struct ieee80211_tx_control *control)
 {
 	struct rt2x00_usb	*rt2x00usb = ieee80211_dev_hw_data(net_dev);
+	struct usb_devive	*usb_dev =
+		interface_to_usbdev(rt2x00usb->usb_intf);
 	struct data_ring	*ring;
 	struct data_entry	*entry;
 	struct txd		*txd;
@@ -1247,6 +1262,7 @@ rt2500usb_tx(struct net_device *net_dev,
 	rt2500usb_write_tx_desc(rt2x00usb, txd, skb, control);
 	entry->skb = skb;
 
+	SET_FLAG(entry, ENTRY_OWNER_NIC);
 	usb_fill_bulk_urb(
 		entry->urb,
 		usb_dev,
@@ -1320,6 +1336,8 @@ rt2500usb_open(struct net_device *net_de
 	rt2x00_set_field16_nb(&reg, TXRX_CSR2_DISABLE_RX, 0);
 	rt2x00_register_write(rt2x00usb, TXRX_CSR2, reg);
 
+	SET_FLAG(rt2x00usb, RADIO_ENABLED);
+
 	return 0;
 
 exit_fail:
@@ -1336,6 +1354,8 @@ rt2500usb_stop(struct net_device *net_de
 	int			counter;
 	u16			reg;
 
+	CLEAR_FLAG(rt2x00usb, RADIO_ENABLED);
+
 	/*
 	 * Cancel RX.
 	 */
@@ -1609,6 +1629,8 @@ rt2500usb_beacon_update(struct net_devic
 	struct sk_buff *skb, struct ieee80211_tx_control *control)
 {
 	struct rt2x00_usb	*rt2x00usb = ieee80211_dev_hw_data(net_dev);
+	struct usb_devive	*usb_dev =
+		interface_to_usbdev(rt2x00usb->usb_intf);
 	struct data_entry	*entry;
 
 	entry = rt2x00_get_data_entry(&rt2x00usb->ring[RING_BEACON]);
@@ -1624,6 +1646,7 @@ rt2500usb_beacon_update(struct net_devic
 	rt2500usb_write_tx_desc(rt2x00usb,
 		rt2x00usb_txdesc_addr(entry), skb, control);
 
+	SET_FLAG(entry, ENTRY_OWNER_NIC);
 	usb_fill_bulk_urb(
 		entry->urb,
 		usb_dev,
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h	2006-04-27 21:55:14.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h	2006-04-27 21:56:05.000000000 +0200
@@ -648,6 +648,13 @@ struct rxd{
  */
 struct data_entry{
 	/*
+	 * Status flag.
+	 */
+	unsigned int			flags;
+#define ENTRY_OWNER_NIC			0x00000001
+#define ENTRY_TYPE_RX			0x00000002
+
+	/*
 	 * Ring we belong to.
 	 */
 	struct data_ring		*ring;
@@ -717,6 +724,11 @@ rt2x00usb_txdesc_addr(struct data_entry 
  */
 struct rt2x00_usb{
 	/*
+	 * Device flags.
+	 */
+	unsigned int				flags;
+
+	/*
 	 * PCI device structure.
 	 */
 	struct usb_interface			*usb_intf;
@@ -748,8 +760,6 @@ struct rt2x00_usb{
 	 */
 	struct ieee80211_rx_status		rx_params;
 
-	u8					atim_available;
-
 	/*
 	 * Alignment.
 	 */
@@ -798,7 +808,7 @@ rt2x00usb_get_ring(struct rt2x00_usb *rt
 {
 	u8					atim;
 
-	atim = rt2x00usb->atim_available;
+	atim = GET_FLAG(rt2x00usb, ATIM_AVAILABLE);
 
 	/*
 	 * Check if the rings have been allocated.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h	2006-04-27 21:52:01.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h	2006-04-27 21:56:05.000000000 +0200
@@ -93,6 +93,32 @@ static int rt2x00_debug_level = 0;
 #define BEACON_ENTRIES			1
 
 /*
+ * Flag handlers
+ */
+#define SET_FLAG(__dev, __flag)		( (__dev)->flags |= (__flag) )
+#define GET_FLAG(__dev, __flag)		( !!((__dev)->flags & (__flag)) )
+#define CLEAR_FLAG(__dev, __flag)	( (__dev)->flags &= ~(__flag) )
+#define CLEAR_FLAGS(__dev)		( (__dev)->flags = 0 )
+
+/*
+ * Device flags
+ */
+#define INTERFACE_INITIALIZED			0x00000001
+#define INTERFACE_PROMISC			0x00000002
+#define FIRMWARE_FAILED				0x00000004
+#define FIRMWARE_LOADED				0x00000008
+#define RADIO_ENABLED				0x00000010
+#define RADIO_RESUME				0x00000020
+#define ATIM_AVAILABLE				0x00000040
+#define FRAME_TYPE				0x00000080
+#define EXTERNAL_LNA				0x00000100
+#define EXTERNAL_LNA_A				0x00000200
+#define EXTERNAL_LNA_BG				0x00000400
+#define RF_SEQUENCE				0x00000800
+#define DOUBLE_ANTENNA				0x00001000
+#define HARDWARE_BUTTON				0x00002000
+
+/*
  * TX result flags.
  */
 enum TX_STATUS {

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 27/32] rt2x00: Put Hardware button in generic header
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 14042 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Put the hardware button handling as much as possible
in the new generic header for PCI.
The individial .c files should now only contain
the polling function to check the state of the hardware button.

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 21:57:18.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 22:03:48.000000000 +0200
@@ -38,10 +38,6 @@
 #include <net/iw_handler.h>
 #include <net/d80211.h>
 
-#ifdef CONFIG_RT2400PCI_BUTTON
-#include <acpi/acpi_bus.h>
-#endif /* CONFIG_RT2400PCI_BUTTON */
-
 #include <asm/io.h>
 
 /*
@@ -364,6 +360,24 @@ rt2x00_eeprom_multiread(
 		rt2x00_eeprom_read(rt2x00pci, word + counter, data++);
 }
 
+#ifdef CONFIG_RT2400PCI_BUTTON
+/*
+ * Hardware button poll handler.
+ */
+static void
+rt2400pci_button_poll(unsigned long data)
+{
+	struct rt2x00_pci	*rt2x00pci = (struct rt2x00_pci*)data;
+	u32			reg;
+
+	rt2x00_register_read(rt2x00pci, GPIOCSR, &reg);
+	rt2x00pci_button_status(
+		rt2x00pci, rt2x00_get_field32(reg, GPIOCSR_BIT0));
+}
+#else /* CONFIG_RT2400PCI_BUTTON */
+static void rt2400pci_button_poll(struct rt2x00_pci *rt2x00pci){}
+#endif /* CONFIG_RT2400PCI_BUTTON */
+
 /*
  * Configuration handlers.
  */
@@ -2258,24 +2272,10 @@ rt2400pci_initialize(struct pci_dev *pci
 	|| rt2400pci_init_hw(rt2x00pci))
 		goto exit_destroy_workqueue;
 
-#ifdef CONFIG_RT2400PCI_BUTTON
-	strcpy(acpi_device_class(&rt2x00pci->acpi_dev), DRV_NAME "_button");
-	strcpy(acpi_device_bid(&rt2x00pci->acpi_dev), DRV_NAME);
-	strcpy(acpi_device_name(&rt2x00pci->acpi_dev), DRV_NAME);
-
-	init_timer(&rt2x00pci->poll_timer);
-
-	if (rt2x00_poll_delay
-	&& rt2x00pci->button_status != BUTTON_STATUS_UNAVAILABLE) {
-		rt2x00pci->button_status = rt2400pci_poll(rt2x00pci);
-		rt2x00pci->poll_delay = rt2x00_poll_delay * (HZ / 10);
-		rt2x00pci->poll_timer.function = rt2400pci_poll_expire;
-		rt2x00pci->poll_timer.data = (unsigned long)rt2x00pci;
-		rt2x00pci->poll_timer.expires =
-			jiffies + rt2x00pci->poll_delay;
-		add_timer(&rt2x00pci->poll_timer);
-	};
-#endif /* CONFIG_RT2400PCI_BUTTON */
+	/*
+	 * If required start hardware button polling.
+	 */
+	rt2x00pci_button_start(rt2x00pci, rt2400pci_button_poll);
 
 	return 0;
 
@@ -2294,13 +2294,10 @@ rt2400pci_uninitialize(struct net_device
 {
 	struct rt2x00_pci	*rt2x00pci = ieee80211_dev_hw_data(net_dev);
 
-#ifdef CONFIG_RT2400PCI_BUTTON
 	/*
 	 * Shutdown poll_timer for hardware button.
 	 */
-	rt2x00pci->button_status = BUTTON_STATUS_UNAVAILABLE;
-	del_timer_sync(&rt2x00pci->poll_timer);
-#endif /* CONFIG_RT2400PCI_BUTTON */
+	rt2x00pci_button_stop(rt2x00pci);
 
 	kfree(rt2x00pci->eeprom);
 
@@ -2506,40 +2503,6 @@ rt2400pci_resume(struct pci_dev *pci_dev
 }
 #endif /* CONFIG_PM */
 
-#ifdef CONFIG_RT2400PCI_BUTTON
-static int
-rt2400pci_poll(struct rt2x00_pci *rt2x00pci)
-{
-	u32			reg;
-
-	rt2x00_register_read(rt2x00pci, GPIOCSR, &reg);
-	return rt2x00_get_field32(reg, GPIOCSR_BIT0);
-}
-
-static void
-rt2400pci_poll_expire(unsigned long data)
-{
-	struct rt2x00_pci	*rt2x00pci = (struct rt2x00_pci*)data;
-	u16			status;
-
-	status = rt2400pci_poll(rt2x00pci);
-
-	if (rt2x00pci->button_status != BUTTON_STATUS_UNAVAILABLE)
-		return;
-
-	if (status != rt2x00pci->button_status) {
-		rt2x00pci->button_status = status;
-		acpi_bus_generate_event(&rt2x00pci->acpi_dev,
-			ACPI_TYPE_EVENT, rt2x00pci->button_status);
-	}
-
-	rt2x00pci->poll_timer.expires = jiffies + rt2x00pci->poll_delay;
-
-	if (rt2x00pci->button_status != BUTTON_STATUS_UNAVAILABLE)
-		add_timer(&rt2x00pci->poll_timer);
-}
-#endif /* CONFIG_RT2400PCI_BUTTON */
-
 /*
  * RT2400pci module information.
  */
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h	2006-04-27 21:57:18.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h	2006-04-27 22:03:48.000000000 +0200
@@ -863,21 +863,4 @@ static int rt2400pci_beacon_update(struc
 	struct sk_buff *skb, struct ieee80211_tx_control *control);
 static int rt2400pci_tx_last_beacon(struct net_device *net_dev);
 
-/*
- * HW button support structures and variables.
- * The delay between each poll is set by the module parameter.
- */
-#ifdef CONFIG_RT2400PCI_BUTTON
-/*
- * Module parameter.
- */
-static int rt2x00_poll_delay = 100;
-
-/*
- * Declaration of several required functions.
- */
-static int rt2400pci_poll(struct rt2x00_pci *rt2x00pci);
-static void rt2400pci_poll_expire(unsigned long data);
-#endif /* CONFIG_RT2400PCI_BUTTON */
-
 #endif /* RT2400PCI_H */
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 21:57:18.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 22:03:48.000000000 +0200
@@ -38,10 +38,6 @@
 #include <net/iw_handler.h>
 #include <net/d80211.h>
 
-#ifdef CONFIG_RT2500PCI_BUTTON
-#include <acpi/acpi_bus.h>
-#endif /* CONFIG_RT2500PCI_BUTTON */
-
 #include <asm/io.h>
 
 /*
@@ -364,6 +360,24 @@ rt2x00_eeprom_multiread(
 		rt2x00_eeprom_read(rt2x00pci, word + counter, data++);
 }
 
+#ifdef CONFIG_RT2500PCI_BUTTON
+/*
+ * Hardware button poll handler.
+ */
+static void
+rt2500pci_button_poll(unsigned long data)
+{
+	struct rt2x00_pci	*rt2x00pci = (struct rt2x00_pci*)data;
+	u32			reg;
+
+	rt2x00_register_read(rt2x00pci, GPIOCSR, &reg);
+	rt2x00pci_button_status(
+		rt2x00pci, rt2x00_get_field32(reg, GPIOCSR_BIT0));
+}
+#else /* CONFIG_RT2500PCI_BUTTON */
+static void rt2500pci_button_poll(struct rt2x00_pci *rt2x00pci){}
+#endif /* CONFIG_RT2500PCI_BUTTON */
+
 /*
  * Configuration handlers.
  */
@@ -2547,24 +2561,10 @@ rt2500pci_initialize(struct pci_dev *pci
 	|| rt2500pci_init_hw(rt2x00pci))
 		goto exit_destroy_workqueue;
 
-#ifdef CONFIG_RT2500PCI_BUTTON
-	strcpy(acpi_device_class(&rt2x00pci->acpi_dev), DRV_NAME "_button");
-	strcpy(acpi_device_bid(&rt2x00pci->acpi_dev), DRV_NAME);
-	strcpy(acpi_device_name(&rt2x00pci->acpi_dev), DRV_NAME);
-
-	init_timer(&rt2x00pci->poll_timer);
-
-	if (rt2x00_poll_delay
-	&& rt2x00pci->button_status != BUTTON_STATUS_UNAVAILABLE) {
-		rt2x00pci->button_status = rt2500pci_poll(rt2x00pci);
-		rt2x00pci->poll_delay = rt2x00_poll_delay * (HZ / 10);
-		rt2x00pci->poll_timer.function = rt2500pci_poll_expire;
-		rt2x00pci->poll_timer.data = (unsigned long)rt2x00pci;
-		rt2x00pci->poll_timer.expires =
-			jiffies + rt2x00pci->poll_delay;
-		add_timer(&rt2x00pci->poll_timer);
-	};
-#endif /* CONFIG_RT2500PCI_BUTTON */
+	/*
+	 * If required start hardware button polling.
+	 */
+	rt2x00pci_button_start(rt2x00pci, rt2500pci_button_poll);
 
 	return 0;
 
@@ -2583,13 +2583,10 @@ rt2500pci_uninitialize(struct net_device
 {
 	struct rt2x00_pci	*rt2x00pci = ieee80211_dev_hw_data(net_dev);
 
-#ifdef CONFIG_RT2500PCI_BUTTON
 	/*
 	 * Shutdown poll_timer for hardware button.
 	 */
-	rt2x00pci->button_status = BUTTON_STATUS_UNAVAILABLE;
-	del_timer_sync(&rt2x00pci->poll_timer);
-#endif /* CONFIG_RT2500PCI_BUTTON */
+	rt2x00pci_button_stop(rt2x00pci);
 
 	kfree(rt2x00pci->eeprom);
 
@@ -2791,40 +2788,6 @@ rt2500pci_resume(struct pci_dev *pci_dev
 }
 #endif /* CONFIG_PM */
 
-#ifdef CONFIG_RT2500PCI_BUTTON
-static int
-rt2500pci_poll(struct rt2x00_pci *rt2x00pci)
-{
-	u32			reg;
-
-	rt2x00_register_read(rt2x00pci, GPIOCSR, &reg);
-	return rt2x00_get_field32(reg, GPIOCSR_BIT0);
-}
-
-static void
-rt2500pci_poll_expire(unsigned long data)
-{
-	struct rt2x00_pci	*rt2x00pci = (struct rt2x00_pci*)data;
-	u16			status;
-
-	status = rt2500pci_poll(rt2x00pci);
-
-	if (rt2x00pci->button_status != BUTTON_STATUS_UNAVAILABLE)
-		return;
-
-	if (status != rt2x00pci->button_status) {
-		rt2x00pci->button_status = status;
-		acpi_bus_generate_event(&rt2x00pci->acpi_dev,
-			ACPI_TYPE_EVENT, rt2x00pci->button_status);
-	}
-
-	rt2x00pci->poll_timer.expires = jiffies + rt2x00pci->poll_delay;
-
-	if (rt2x00pci->button_status != BUTTON_STATUS_UNAVAILABLE)
-		add_timer(&rt2x00pci->poll_timer);
-}
-#endif /* CONFIG_RT2500PCI_BUTTON */
-
 /*
  * RT2500pci module information.
  */
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h	2006-04-27 21:57:18.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h	2006-04-27 22:03:48.000000000 +0200
@@ -1132,21 +1132,4 @@ static int rt2500pci_beacon_update(struc
 	struct sk_buff *skb, struct ieee80211_tx_control *control);
 static int rt2500pci_tx_last_beacon(struct net_device *net_dev);
 
-/*
- * HW button support structures and variables.
- * The delay between each poll is set by the module parameter.
- */
-#ifdef CONFIG_RT2500PCI_BUTTON
-/*
- * Module parameter.
- */
-static int rt2x00_poll_delay = 100;
-
-/*
- * Declaration of several required functions.
- */
-static int rt2500pci_poll(struct rt2x00_pci *rt2x00pci);
-static void rt2500pci_poll_expire(unsigned long data);
-#endif /* CONFIG_RT2500PCI_BUTTON */
-
 #endif /* RT2500PCI_H */
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h	2006-04-27 22:00:04.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h	2006-04-27 22:03:48.000000000 +0200
@@ -45,6 +45,37 @@
 #define EEPROM_READ_OPCODE		0x06
 
 /*
+ * HW button structure.
+ */
+#ifdef CONFIG_RT2X00_BUTTON
+#include <acpi/acpi_bus.h>
+
+struct rt2x00_button{
+	/*
+	 * ACPI device for generation of ACPI events.
+	 */
+	struct acpi_device			acpi_dev;
+
+	/*
+	 * Timer for register polling.
+	 */
+	struct timer_list			poll_timer;
+
+	/*
+	 * Timer delay.
+	 */
+	short					poll_delay;
+
+	/*
+	 * Current status of button.
+	 */
+	short					button_status:1;
+	short					active_poll:1;
+	short					__pad:14;
+} __attribute__ ((packed));
+#endif /* CONFIG_RT2X00_BUTTON */
+
+/*
  * data_entry
  * The data ring is a list of data entries.
  * Each entry holds a reference to the descriptor
@@ -92,28 +123,7 @@ struct rt2x00_pci{
 	struct pci_dev				*pci_dev;
 
 #ifdef CONFIG_RT2X00_BUTTON
-	/*
-	 * ACPI device for generation of ACPI events.
-	 */
-	struct acpi_device			acpi_dev;
-
-	/*
-	 * Timer for register polling.
-	 */
-	struct timer_list			poll_timer;
-
-	/*
-	 * Timer delay.
-	 */
-	u16					poll_delay;
-
-	/*
-	 * Current status of button.
-	 */
-	u16					button_status;
-#define BUTTON_STATUS_UNAVAILABLE		2
-#define BUTTON_STATUS_ON			1
-#define BUTTON_STATUS_OFF			0
+	struct rt2x00_button			button;
 #endif /* CONFIG_RT2X00_BUTTON */
 
 	/*
@@ -257,4 +267,85 @@ rt2x00pci_get_ring(struct rt2x00_pci *rt
 	return NULL;
 }
 
+/*
+ * HW button variables & functions.
+ * The delay between each poll is set by the module parameter.
+ */
+#ifdef CONFIG_RT2X00_BUTTON
+/*
+ * Module parameter.
+ */
+static short rt2x00_poll_delay = 0;
+
+static inline void
+rt2x00pci_button_status(struct rt2x00_pci *rt2x00pci, char status)
+{
+	struct rt2x00_button	*button = &rt2x00pci->button;
+
+	if (!button->active_poll)
+		return;
+
+	if (status != button->button_status) {
+		button->button_status = status;
+		acpi_bus_generate_event(
+			&button->acpi_dev, ACPI_TYPE_EVENT, status);
+	}
+
+	button->poll_timer.expires = jiffies + button->poll_delay;
+
+	if (button->active_poll)
+		add_timer(&button->poll_timer);
+}
+
+static inline void
+rt2x00pci_button_start(struct rt2x00_pci *rt2x00pci,
+	void (*handler)(unsigned long data))
+{
+	struct rt2x00_button	*button = &rt2x00pci->button;
+
+	/*
+	 * Only enable polling when the user has
+	 * set the poll delay module parameter,
+	 * and the device contains a hardware button.
+	 */
+	if(!GET_FLAG(rt2x00pci, HARDWARE_BUTTON) || !rt2x00_poll_delay)
+		return;
+
+	strcpy(acpi_device_class(&button->acpi_dev), DRV_NAME "_button");
+	strcpy(acpi_device_bid(&button->acpi_dev), DRV_NAME);
+	strcpy(acpi_device_name(&button->acpi_dev), DRV_NAME);
+
+	init_timer(&button->poll_timer);
+
+	button->poll_delay = rt2x00_poll_delay * (HZ / 10);
+	button->button_status = 0;
+	button->active_poll = 1;
+
+	button->poll_timer.function = handler;
+	button->poll_timer.data = (unsigned long)rt2x00pci;
+	button->poll_timer.expires = jiffies + button->poll_delay;
+
+	add_timer(&button->poll_timer);
+}
+
+static inline void
+rt2x00pci_button_stop(struct rt2x00_pci *rt2x00pci)
+{
+	/*
+	 * Shutdown poll_timer for hardware button,
+	 * make sure only to disable polling when
+	 * it was enabled in the first place.
+	 */
+	if(!rt2x00pci->button.active_poll)
+		return;
+
+	rt2x00pci->button.active_poll = 0;
+	del_timer_sync(&rt2x00pci->button.poll_timer);
+}
+#else /* CONFIG_RT2X00_BUTTON */
+static inline void rt2x00pci_button_start(struct rt2x00_pci *rt2x00pci,
+	int (*handler)(struct rt2x00_pci *rt2x00pci)){}
+static inline void rt2x00pci_button_stop(struct rt2x00_pci *rt2x00pci){}
+#endif /* CONFIG_RT2X00_BUTTON */
+
 #endif /* RT2X00PCI_H */

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 28/32] rt2x00: Support TXRX led handling
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 11843 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Create more advanced led handling, enable txrx activity
by switching on and off the led at interrupt time.

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:03:48.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 22:04:19.000000000 +0200
@@ -669,6 +669,57 @@ rt2400pci_link_tuner(struct rt2x00_pci *
 }
 
 /*
+ * LED functions.
+ */
+static void
+rt2400pci_enable_led(struct rt2x00_pci *rt2x00pci)
+{
+	u32			reg;
+
+	rt2x00_register_read(rt2x00pci, LEDCSR, &reg);
+
+	rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, 30);
+	rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, 70);
+
+	if (rt2x00pci->led_mode == LED_MODE_TXRX_ACTIVITY) {
+		rt2x00_set_field32(&reg, LEDCSR_LINK, 1);
+		rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 0);
+	} else if (rt2x00pci->led_mode == LED_MODE_ASUS) {
+		rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
+		rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 1);
+	} else {
+		rt2x00_set_field32(&reg, LEDCSR_LINK, 1);
+		rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 1);
+	}
+
+	rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+}
+
+static void
+rt2400pci_disable_led(struct rt2x00_pci *rt2x00pci)
+{
+	u32			reg;
+
+	rt2x00_register_read(rt2x00pci, LEDCSR, &reg);
+	rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
+	rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 0);
+	rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+}
+
+static void
+rt2400pci_activity_led(struct rt2x00_pci *rt2x00pci, char activity)
+{
+	u32			reg;
+
+	if (rt2x00pci->led_mode != LED_MODE_TXRX_ACTIVITY)
+		return;
+
+	rt2x00_register_read(rt2x00pci, LEDCSR, &reg);
+	rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, activity);
+	rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+}
+
+/*
  * Device state switch.
  * This will put the device to sleep, or awake it.
  */
@@ -882,6 +933,11 @@ rt2400pci_rxdone(void *data)
 	 * Tune link for optimal performance.
 	 */
 	rt2400pci_link_tuner(rt2x00pci);
+
+	/*
+	 * Update LED.
+	 */
+	rt2400pci_activity_led(rt2x00pci, 0);
 }
 
 static void
@@ -987,10 +1043,13 @@ rt2400pci_interrupt(int irq, void *dev_i
 
 	/*
 	 * 2 - Rx ring done interrupt.
+	 * Enable the TXRX activity led.
 	 */
-	if (rt2x00_get_field32(reg, CSR7_RXDONE))
+	if (rt2x00_get_field32(reg, CSR7_RXDONE)) {
 		queue_work(rt2x00pci->workqueue,
 			&rt2x00pci->ring[RING_RX].irq_work);
+		rt2400pci_activity_led(rt2x00pci, 1);
+	}
 
 	/*
 	 * 3 - Atim ring transmit done interrupt.
@@ -1333,13 +1392,6 @@ rt2400pci_init_registers(struct rt2x00_p
 	rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID1, 154);
 	rt2x00_register_write(rt2x00pci, RALINKCSR, reg);
 
-	rt2x00_register_read(rt2x00pci, LEDCSR, &reg);
-	rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, 30);
-	rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, 70);
-	rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
-	rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 0);
-	rt2x00_register_write(rt2x00pci, LEDCSR, reg);
-
 	rt2x00_register_read(rt2x00pci, CSR1, &reg);
 	rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
 	rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
@@ -1555,6 +1607,11 @@ rt2400pci_open(struct net_device *net_de
 	}
 
 	/*
+	 * Enable LED
+	 */
+	rt2400pci_enable_led(rt2x00pci);
+
+	/*
 	 * Enable interrupts.
 	 */
 	rt2x00_register_read(rt2x00pci, CSR8, &reg);
@@ -1597,11 +1654,9 @@ rt2400pci_stop(struct net_device *net_de
 	rt2x00_register_write(rt2x00pci, RXCSR0, reg);
 
 	/*
-	 * Switch off LED.
+	 * Disable LED
 	 */
-	rt2x00_register_read(rt2x00pci, LEDCSR, &reg);
-	rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
-	rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+	rt2400pci_disable_led(rt2x00pci);
 
 	/*
 	 * Disable interrupts.
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:03:48.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 22:04:19.000000000 +0200
@@ -722,6 +722,57 @@ dynamic_cca_tune:
 }
 
 /*
+ * LED functions.
+ */
+static void
+rt2500pci_enable_led(struct rt2x00_pci *rt2x00pci)
+{
+	u32			reg;
+
+	rt2x00_register_read(rt2x00pci, LEDCSR, &reg);
+
+	rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, 30);
+	rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, 70);
+
+	if (rt2x00pci->led_mode == LED_MODE_TXRX_ACTIVITY) {
+		rt2x00_set_field32(&reg, LEDCSR_LINK, 1);
+		rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 0);
+	} else if (rt2x00pci->led_mode == LED_MODE_ASUS) {
+		rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
+		rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 1);
+	} else {
+		rt2x00_set_field32(&reg, LEDCSR_LINK, 1);
+		rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 1);
+	}
+
+	rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+}
+
+static void
+rt2500pci_disable_led(struct rt2x00_pci *rt2x00pci)
+{
+	u32			reg;
+
+	rt2x00_register_read(rt2x00pci, LEDCSR, &reg);
+	rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
+	rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 0);
+	rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+}
+
+static void
+rt2500pci_activity_led(struct rt2x00_pci *rt2x00pci, char activity)
+{
+	u32			reg;
+
+	if (rt2x00pci->led_mode != LED_MODE_TXRX_ACTIVITY)
+		return;
+
+	rt2x00_register_read(rt2x00pci, LEDCSR, &reg);
+	rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, activity);
+	rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+}
+
+/*
  * Device state switch.
  * This will put the device to sleep, or awake it.
  */
@@ -962,6 +1013,11 @@ rt2500pci_rxdone(void *data)
 	 */
 	if (total_rssi && rssi_count)
 		rt2500pci_link_tuner(rt2x00pci, total_rssi / rssi_count);
+
+	/*
+	 * Update LED.
+	 */
+	rt2500pci_activity_led(rt2x00pci, 0);
 }
 
 static void
@@ -1067,10 +1123,13 @@ rt2500pci_interrupt(int irq, void *dev_i
 
 	/*
 	 * 2 - Rx ring done interrupt.
+	 * Enable the TXRX activity led.
 	 */
-	if (rt2x00_get_field32(reg, CSR7_RXDONE))
+	if (rt2x00_get_field32(reg, CSR7_RXDONE)) {
 		queue_work(rt2x00pci->workqueue,
 			&rt2x00pci->ring[RING_RX].irq_work);
+		rt2500pci_activity_led(rt2x00pci, 1);
+	}
 
 	/*
 	 * 3 - Atim ring transmit done interrupt.
@@ -1435,13 +1494,6 @@ rt2500pci_init_registers(struct rt2x00_p
 	rt2x00_register_write(rt2x00pci, ARTCSR1, cpu_to_le32(0x1d21252d));
 	rt2x00_register_write(rt2x00pci, ARTCSR2, cpu_to_le32(0x1919191d));
 
-	rt2x00_register_read(rt2x00pci, LEDCSR, &reg);
-	rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, 30);
-	rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, 70);
-	rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
-	rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 0);
-	rt2x00_register_write(rt2x00pci, LEDCSR, reg);
-
 	rt2x00_register_read(rt2x00pci, CSR1, &reg);
 	rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
 	rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
@@ -1663,6 +1715,11 @@ rt2500pci_open(struct net_device *net_de
 	}
 
 	/*
+	 * Enable LED
+	 */
+	rt2500pci_enable_led(rt2x00pci);
+
+	/*
 	 * Enable interrupts.
 	 */
 	rt2x00_register_read(rt2x00pci, CSR8, &reg);
@@ -1705,11 +1762,9 @@ rt2500pci_stop(struct net_device *net_de
 	rt2x00_register_write(rt2x00pci, RXCSR0, reg);
 
 	/*
-	 * Switch off LED.
+	 * Disable LED
 	 */
-	rt2x00_register_read(rt2x00pci, LEDCSR, &reg);
-	rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
-	rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+	rt2500pci_disable_led(rt2x00pci);
 
 	/*
 	 * Disable interrupts.
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 21:57:18.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 22:04:19.000000000 +0200
@@ -532,6 +532,59 @@ rt2500usb_link_tuner(struct rt2x00_usb *
 }
 
 /*
+ * LED functions.
+ */
+static void
+rt2500usb_enable_led(struct rt2x00_usb *rt2x00usb)
+{
+	u16			reg;
+
+	rt2x00_register_read(rt2x00usb, MAC_CSR21, &reg);
+	rt2x00_set_field16_nb(&reg, MAC_CSR21_ON_PERIOD, 30);
+	rt2x00_set_field16_nb(&reg, MAC_CSR21_OFF_PERIOD, 70);
+	rt2x00_register_write(rt2x00usb, MAC_CSR21, reg);
+
+	rt2x00_register_read(rt2x00usb, MAC_CSR20, &reg);
+
+	if (rt2x00usb->led_mode == LED_MODE_TXRX_ACTIVITY) {
+		rt2x00_set_field16_nb(&reg, MAC_CSR20_LINK, 1);
+		rt2x00_set_field16_nb(&reg, MAC_CSR20_ACTIVITY, 0);
+	} else if (rt2x00usb->led_mode == LED_MODE_ASUS) {
+		rt2x00_set_field16_nb(&reg, MAC_CSR20_LINK, 0);
+		rt2x00_set_field16_nb(&reg, MAC_CSR20_ACTIVITY, 1);
+	} else {
+		rt2x00_set_field16_nb(&reg, MAC_CSR20_LINK, 1);
+		rt2x00_set_field16_nb(&reg, MAC_CSR20_ACTIVITY, 1);
+	}
+
+	rt2x00_register_write(rt2x00usb, MAC_CSR20, reg);
+}
+
+static void
+rt2500usb_disable_led(struct rt2x00_usb *rt2x00usb)
+{
+	u16			reg;
+
+	rt2x00_register_read(rt2x00usb, MAC_CSR20, &reg);
+	rt2x00_set_field16_nb(&reg, MAC_CSR20_LINK, 0);
+	rt2x00_set_field16_nb(&reg, MAC_CSR20_ACTIVITY, 0);
+	rt2x00_register_write(rt2x00usb, MAC_CSR20, reg);
+}
+
+static void
+rt2500usb_activity_led(struct rt2x00_usb *rt2x00usb, char activity)
+{
+	u16			reg;
+
+	if (rt2x00usb->led_mode != LED_MODE_TXRX_ACTIVITY)
+		return;
+
+	rt2x00_register_read(rt2x00usb, MAC_CSR20, &reg);
+	rt2x00_set_field16_nb(&reg, MAC_CSR20_ACTIVITY, activity);
+	rt2x00_register_write(rt2x00usb, MAC_CSR20, reg);
+}
+
+/*
  * Device state switch.
  * This will put the device to sleep, or awake it.
  */
@@ -782,6 +835,11 @@ rt2500usb_rxdone(void *data)
 	 */
 	if (total_rssi && rssi_count)
 		rt2500usb_link_tuner(rt2x00usb, total_rssi / rssi_count);
+
+	/*
+	 * Update LED.
+	 */
+	rt2500usb_activity_led(rt2x00usb, 0);
 }
 
 static void
@@ -857,9 +915,14 @@ rt2500usb_interrupt(struct urb *urb, str
 	if (!GET_FLAG(rt2x00usb, RADIO_ENABLED))
 		return;
 
+	CLEAR_FLAG(entry, ENTRY_OWNER_NIC);
+
 	if (urb->status)
 		return;
 
+	if (GET_FLAG(entry, ENTRY_TYPE_RX))
+		rt2500usb_activity_led(rt2x00usb, 1);
+
 	queue_work(rt2x00usb->workqueue, &entry->ring->irq_work);
 }
 
@@ -1104,7 +1167,6 @@ rt2500usb_init_registers(struct rt2x00_u
 	rt2x00_register_write(rt2x00usb, TXRX_CSR21, 0xe78f);
 	rt2x00_register_write(rt2x00usb, MAC_CSR9, 0xff1d);
 	rt2x00_register_write(rt2x00usb, MAC_CSR1, 0x0004);
-	rt2x00_register_write(rt2x00usb, MAC_CSR20, 0x0000);
 
 	reg = 0;
 	rt2x00_register_read(rt2x00usb, MAC_CSR0, &reg);
@@ -1321,6 +1383,11 @@ rt2500usb_open(struct net_device *net_de
 	rt2x00_set_field16_nb(&reg, TXRX_CSR2_DISABLE_RX, 0);
 	rt2x00_register_write(rt2x00usb, TXRX_CSR2, reg);
 
+	/*
+	 * Enable LED
+	 */
+	rt2500usb_enable_led(rt2x00usb);
+
 	SET_FLAG(rt2x00usb, RADIO_ENABLED);
 
 	return 0;
@@ -1348,16 +1415,16 @@ rt2500usb_stop(struct net_device *net_de
 	rt2x00_set_field16_nb(&reg, TXRX_CSR2_DISABLE_RX, 1);
 	rt2x00_register_write(rt2x00usb, TXRX_CSR2, reg);
 
+	/*
+	 * Disable LED
+	 */
+	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);
 	}
 
-	/*
-	 * Switch off LED.
-	 */
-	rt2x00_register_write(rt2x00usb, MAC_CSR20, 0);
-
 	rt2x00_vendor_request(rt2x00usb, USB_RX_CONTROL,
 		USB_VENDOR_REQUEST_OUT, 0x00, 0x00, NULL, 0);
 

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 29/32] rt2x00: dscape compatibilitiy
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 255 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Latest dscape patches have broken rt2x00,
fix compile issues, and support the new features.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>

Available on server:

http://mendiosus.nl/rt2x00/rt2x00-29-compat.diff

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 30/32] rt2x00: Correctly initialize TX power in registers
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 14733 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

The rate does not need to be configured for each
TX packet. The actual rate for sending is determined
in the PLCP, the rate configuration is only capable
of setting the supported rates, which is dependent
of the physical mode we are in.
When we the configuration function is called,
disable the RX for proper behaviour.

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:04:47.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 22:05:21.000000000 +0200
@@ -660,6 +660,22 @@ rt2400pci_config_rate(struct rt2x00_pci 
 }
 
 static void
+rt2400pci_config_phymode(struct rt2x00_pci *rt2x00pci, const int phymode)
+{
+	struct ieee80211_rate	*rate;
+
+	rate = &rt2x00pci->hw.modes[0].rates[
+		rt2x00pci->hw.modes[0].num_rates - 1];
+
+	rt2400pci_config_rate(rt2x00pci, rate->val2);
+
+	/*
+	 * Update physical mode for rx ring.
+	 */
+	rt2x00pci->rx_params.phymode = phymode;
+}
+
+static void
 rt2400pci_config_mac_address(struct rt2x00_pci *rt2x00pci, void *addr)
 {
 	u32			reg[2] = {0, 0};
@@ -815,11 +831,6 @@ rt2400pci_write_tx_desc(
 	u16			signal;
 	u16			service;
 
-	/*
-	 * Update rate control register.
-	 */
-	rt2400pci_config_rate(rt2x00pci, control->tx_rate);
-
 	rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 1);
 	rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
 
@@ -1545,14 +1556,6 @@ rt2400pci_tx(struct net_device *net_dev,
 
 	rt2x00_ring_index_inc(ring);
 
-	/*
-	 * We are going to cheat now, we update the register
-	 * with the CWmin and CWmax values for the current
-	 * queue. This is the alternative since we cannot
-	 * set the CWmin and CWmax per descriptor.
-	 */
-	rt2400pci_config_cw(rt2x00pci, &ring->tx_params);
-
 	rt2x00_register_read(rt2x00pci, TXCSR0, &reg);
 	if (control->queue == IEEE80211_TX_QUEUE_DATA0)
 		rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
@@ -1769,19 +1772,46 @@ rt2400pci_config_update(void *data)
 	struct rt2x00_pci	*rt2x00pci = data;
 	struct net_device	*net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
 	struct ieee80211_conf	*conf = ieee80211_get_hw_conf(net_dev);
+	u32			reg;
+
+	/*
+	 * Some configuration changes require the RX to be disabled.
+	 */
+	if (GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+		rt2x00_register_read(rt2x00pci, RXCSR0, &reg);
+		rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
+		rt2x00_register_write(rt2x00pci, RXCSR0, reg);
+	}
 
-	rt2400pci_config_bssid(rt2x00pci, conf->client_bssid);
-	rt2400pci_config_type(rt2x00pci, conf->mode);
 	rt2400pci_config_channel(rt2x00pci,
 		conf->channel_val, conf->channel, conf->freq);
 	rt2400pci_config_txpower(rt2x00pci, conf->power_level);
 	rt2400pci_config_antenna(rt2x00pci, conf->antenna_sel);
 	rt2400pci_config_duration(rt2x00pci, conf->short_slot_time);
+	rt2400pci_config_phymode(rt2x00pci, conf->phymode);
 
 	/*
-	 * Update active info for RX.
+	 * Reenable RX only if the radio should be on.
 	 */
-	rt2x00pci->rx_params.phymode = conf->phymode;
+	if (conf->radio_enabled) {
+		if (!GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+			if (rt2400pci_open(net_dev)) {
+				ERROR("Failed to enabled radio.\n");
+				return;
+			}
+		} else {
+			rt2x00_register_read(rt2x00pci, RXCSR0, &reg);
+			rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
+			rt2x00_register_write(rt2x00pci, RXCSR0, reg);
+		}
+	} else {
+		if (GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+			if (rt2400pci_stop(net_dev)) {
+				ERROR("Failed to disable radio.\n");
+				return;
+			}
+		}
+	}
 }
 
 static int
@@ -1863,8 +1893,8 @@ rt2400pci_scan(void *data)
 	 * Switch channel and update active info for RX.
 	 */
 	if (rt2x00pci->scan->state == IEEE80211_SCAN_START) {
-		rt2x00pci->rx_params.phymode =
-			rt2x00pci->scan->conf.scan_phymode;
+		rt2400pci_config_phymode(rt2x00pci,
+			rt2x00pci->scan->conf.scan_phymode);
 
 		rt2400pci_config_channel(rt2x00pci,
 			rt2x00pci->scan->conf.scan_channel_val,
@@ -1874,8 +1904,8 @@ rt2400pci_scan(void *data)
 		rt2400pci_config_txpower(rt2x00pci,
 			rt2x00pci->scan->conf.scan_power_level);
 	} else {
-		rt2x00pci->rx_params.phymode =
-			rt2x00pci->scan->conf.running_phymode;
+		rt2400pci_config_phymode(rt2x00pci,
+			rt2x00pci->scan->conf.running_phymode);
 
 		rt2400pci_config_channel(rt2x00pci,
 			rt2x00pci->scan->conf.running_channel_val,
@@ -2000,10 +2030,6 @@ rt2400pci_conf_tx(struct net_device *net
 	memcpy(&ring->tx_params, params, sizeof(*params));
 
 	/*
-	 * TODO: We can't use different cw_min and cw_max variables
-	 * per queue, we need to find a good method for dealing with
-	 * this shortage. Also we need to find a method to possibly
-	 * support the other values passed in ieee80211_tx_queue_params.
 	 * The passed variables are stored as real value ((2^n)-1).
 	 * RT2400 registers require to know the bit number 'n'.
 	 */
@@ -2017,6 +2043,11 @@ rt2400pci_conf_tx(struct net_device *net
 	else
 		ring->tx_params.cw_max = 10; /* cw_min: 2^10 = 1024. */
 
+	/*
+	 * Write configuration to register.
+	 */
+	rt2400pci_config_cw(rt2x00pci, &ring->tx_params);
+
 	return 0;
 }
 
@@ -2330,7 +2361,7 @@ rt2400pci_init_hw(struct rt2x00_pci *rt2
 	 * RF2420 is capable of faster channel switches.
 	 */
 	if (rt2x00_rf(&rt2x00pci->chip, RF2420))
-		hw->channel_change_time = 100;
+		hw->channel_change_time = 150;
 	else
 		hw->channel_change_time = 2500;
 
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:04:47.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 22:05:21.000000000 +0200
@@ -703,6 +703,30 @@ rt2500pci_config_rate(struct rt2x00_pci 
 }
 
 static void
+rt2500pci_config_phymode(struct rt2x00_pci *rt2x00pci, const int phymode)
+{
+	struct ieee80211_rate	*rate;
+
+	if (phymode == MODE_IEEE80211A
+	&& rt2x00_rf(&rt2x00pci->chip, RF5222))
+		rate = &rt2x00pci->hw.modes[2].rates[
+			rt2x00pci->hw.modes[2].num_rates - 1];
+	else if (phymode == MODE_IEEE80211B)
+		rate = &rt2x00pci->hw.modes[1].rates[
+			rt2x00pci->hw.modes[1].num_rates - 1];
+	else
+		rate = &rt2x00pci->hw.modes[0].rates[
+			rt2x00pci->hw.modes[0].num_rates - 1];
+
+	rt2500pci_config_rate(rt2x00pci, rate->val2);
+
+	/*
+	 * Update physical mode for rx ring.
+	 */
+	rt2x00pci->rx_params.phymode = phymode;
+}
+
+static void
 rt2500pci_config_mac_address(struct rt2x00_pci *rt2x00pci, void *addr)
 {
 	u32			reg[2] = {0, 0};
@@ -870,11 +894,6 @@ rt2500pci_write_tx_desc(
 	u16			service;
 	u8			rate;
 
-	/*
-	 * Update rate control register.
-	 */
-	rt2500pci_config_rate(rt2x00pci, control->tx_rate);
-
 	rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 1);
 	rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
 
@@ -1879,19 +1898,46 @@ rt2500pci_config_update(void *data)
 	struct rt2x00_pci	*rt2x00pci = data;
 	struct net_device	*net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
 	struct ieee80211_conf	*conf = ieee80211_get_hw_conf(net_dev);
+	u32			reg;
+
+	/*
+	 * Some configuration changes require the RX to be disabled.
+	 */
+	if (GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+		rt2x00_register_read(rt2x00pci, RXCSR0, &reg);
+		rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
+		rt2x00_register_write(rt2x00pci, RXCSR0, reg);
+	}
 
-	rt2500pci_config_bssid(rt2x00pci, conf->client_bssid);
-	rt2500pci_config_type(rt2x00pci, conf->mode);
 	rt2500pci_config_channel(rt2x00pci,
 		conf->channel_val, conf->channel, conf->freq,
 		conf->power_level);
 	rt2500pci_config_antenna(rt2x00pci, conf->antenna_sel);
 	rt2500pci_config_duration(rt2x00pci, conf->short_slot_time);
+	rt2500pci_config_phymode(rt2x00pci, conf->phymode);
 
 	/*
-	 * Update active info for RX.
+	 * Reenable RX only if the radio should be on.
 	 */
-	rt2x00pci->rx_params.phymode = conf->phymode;
+	if (conf->radio_enabled) {
+		if (!GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+			if (rt2500pci_open(net_dev)) {
+				ERROR("Failed to enabled radio.\n");
+				return;
+			}
+		} else {
+			rt2x00_register_read(rt2x00pci, RXCSR0, &reg);
+			rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
+			rt2x00_register_write(rt2x00pci, RXCSR0, reg);
+		}
+	} else {
+		if (GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+			if (rt2500pci_stop(net_dev)) {
+				ERROR("Failed to disable radio.\n");
+				return;
+			}
+		}
+	}
 }
 
 static int
@@ -1973,17 +2019,17 @@ rt2500pci_scan(void *data)
 	 * Switch channel and update active info for RX.
 	 */
 	if (rt2x00pci->scan->state == IEEE80211_SCAN_START) {
-		rt2x00pci->rx_params.phymode =
-			rt2x00pci->scan->conf.scan_phymode;
-	
+		rt2500pci_config_phymode(rt2x00pci,
+			rt2x00pci->scan->conf.scan_phymode);
+
 		rt2500pci_config_channel(rt2x00pci,
 			rt2x00pci->scan->conf.scan_channel_val,
 			rt2x00pci->scan->conf.scan_channel,
 			rt2x00pci->scan->conf.scan_freq,
 			rt2x00pci->scan->conf.scan_power_level);
 	} else {
-		rt2x00pci->rx_params.phymode =
-			rt2x00pci->scan->conf.running_phymode;
+		rt2500pci_config_phymode(rt2x00pci,
+			rt2x00pci->scan->conf.running_phymode);
 	
 		rt2500pci_config_channel(rt2x00pci,
 			rt2x00pci->scan->conf.running_channel_val,
@@ -2570,7 +2616,7 @@ rt2500pci_init_hw(struct rt2x00_pci *rt2
 	hw->device_strips_mic = 0;
 	hw->monitor_during_oper = 1;
 	hw->fraglist = 0;
-	hw->channel_change_time = 2500;
+	hw->channel_change_time = 2000;
 
 	/*
 	 * We have 2 TX queues: TX and PRIO.
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:04:47.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 22:05:21.000000000 +0200
@@ -384,6 +384,12 @@ rt2500usb_config_channel(struct rt2x00_u
 	rt2x00_rf_write(rt2x00usb, rf3);
 	if (rf4)
 		rt2x00_rf_write(rt2x00usb, rf4);
+
+	/*
+	 * Update active info for RX.
+	 */
+	rt2x00usb->rx_params.freq = freq;
+	rt2x00usb->rx_params.channel = channel;
 }
 
 static void
@@ -509,9 +515,32 @@ rt2500usb_config_rate(struct rt2x00_usb 
 }
 
 static void
-rt2500usb_config_mac_address(struct net_device *net_dev, void *addr)
+rt2500usb_config_phymode(struct rt2x00_usb *rt2x00usb, const int phymode)
+{
+	struct ieee80211_rate	*rate;
+
+	if (phymode == MODE_IEEE80211A
+	&& rt2x00_rf(&rt2x00usb->chip, RF5222))
+		rate = &rt2x00usb->hw.modes[2].rates[
+			rt2x00usb->hw.modes[2].num_rates - 1];
+	else if (phymode == MODE_IEEE80211B)
+		rate = &rt2x00usb->hw.modes[1].rates[
+			rt2x00usb->hw.modes[1].num_rates - 1];
+	else
+		rate = &rt2x00usb->hw.modes[0].rates[
+			rt2x00usb->hw.modes[0].num_rates - 1];
+
+	rt2500usb_config_rate(rt2x00usb, rate->val2);
+
+	/*
+	 * Update physical mode for rx ring.
+	 */
+	rt2x00usb->rx_params.phymode = phymode;
+}
+
+static void
+rt2500usb_config_mac_address(struct rt2x00_usb *rt2x00usb, void *addr)
 {
-	struct rt2x00_usb	*rt2x00usb = ieee80211_dev_hw_data(net_dev);
 	u16			reg[3] = {0, 0, 0};
 
 	rt2x00_set_field16_nb(&reg[0], MAC_CSR2_BYTE0, ((u8*)addr)[0]);
@@ -698,11 +727,6 @@ rt2500usb_write_tx_desc(
 	u8			service;
 	u8			rate;
 
-	/*
-	 * Update rate control register.
-	 */
-	rt2500usb_config_rate(rt2x00usb, control->tx_rate);
-
 	rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
 
 	ring = rt2x00usb_get_ring(rt2x00usb, control->queue);
@@ -1546,19 +1570,46 @@ rt2500usb_config_update(void *data)
 	struct net_device	*net_dev =
 		usb_get_intfdata(rt2x00usb->usb_intf);
 	struct ieee80211_conf	*conf = ieee80211_get_hw_conf(net_dev);
+	u16			reg;
+
+	/*
+	 * Some configuration changes require the RX to be disabled.
+	 */
+	if (GET_FLAG(rt2x00usb, RADIO_ENABLED)) {
+		rt2x00_register_read(rt2x00usb, TXRX_CSR2, &reg);
+		rt2x00_set_field16_nb(&reg, TXRX_CSR2_DISABLE_RX, 1);
+		rt2x00_register_write(rt2x00usb, TXRX_CSR2, reg);
+	}
 
-	rt2500usb_config_bssid(rt2x00usb, conf->client_bssid);
-	rt2500usb_config_type(rt2x00usb, conf->mode);
 	rt2500usb_config_channel(rt2x00usb,
 		conf->channel_val, conf->channel, conf->freq,
 		conf->power_level);
 	rt2500usb_config_antenna(rt2x00usb, conf->antenna_sel);
 	rt2500usb_config_duration(rt2x00usb, conf->short_slot_time);
+	rt2500usb_config_phymode(rt2x00usb, conf->phymode);
 
 	/*
-	 * Update active info for RX.
+	 * Reenable RX only if the radio should be on.
 	 */
-	rt2x00usb->rx_params.phymode = conf->phymode;
+	if (conf->radio_enabled) {
+		if (!GET_FLAG(rt2x00usb, RADIO_ENABLED)) {
+			if (rt2500usb_open(net_dev)) {
+				ERROR("Failed to enabled radio.\n");
+				return;
+			}
+		} else {
+			rt2x00_register_read(rt2x00usb, TXRX_CSR2, &reg);
+			rt2x00_set_field16_nb(&reg, TXRX_CSR2_DISABLE_RX, 0);
+			rt2x00_register_write(rt2x00usb, TXRX_CSR2, reg);
+		}
+	} else {
+		if (GET_FLAG(rt2x00usb, RADIO_ENABLED)) {
+			if (rt2500usb_stop(net_dev)) {
+				ERROR("Failed to disable radio.\n");
+				return;
+			}
+		}
+	}
 }
 
 static int
@@ -1640,8 +1691,8 @@ rt2500usb_scan(void *data)
 	 * Switch channel and update active info for RX.
 	 */
 	if (rt2x00usb->scan->state == IEEE80211_SCAN_START) {
-		rt2x00usb->rx_params.phymode =
-			rt2x00usb->scan->conf.scan_phymode;
+		rt2500usb_config_phymode(rt2x00usb,
+			rt2x00usb->scan->conf.scan_phymode);
 	
 		rt2500usb_config_channel(rt2x00usb,
 			rt2x00usb->scan->conf.scan_channel_val,
@@ -1649,8 +1700,8 @@ rt2500usb_scan(void *data)
 			rt2x00usb->scan->conf.scan_freq,
 			rt2x00usb->scan->conf.scan_power_level);
 	} else {
-		rt2x00usb->rx_params.phymode =
-			rt2x00usb->scan->conf.running_phymode;
+		rt2500usb_config_phymode(rt2x00usb,
+			rt2x00usb->scan->conf.running_phymode);
 	
 		rt2500usb_config_channel(rt2x00usb,
 			rt2x00usb->scan->conf.running_channel_val,
@@ -2186,7 +2237,7 @@ rt2500usb_init_hw(struct rt2x00_usb *rt2
 	hw->device_strips_mic = 0;
 	hw->monitor_during_oper = 1;
 	hw->fraglist = 0;
-	hw->channel_change_time = 500;
+	hw->channel_change_time = 500000;
 
 	/*
 	 * We have 2 TX queues: TX and PRIO.

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 31/32] rt2x00: Correctly initialization and uninitialization of device
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

* [PATCH 32/32] rt2x00: misc fixes
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
  To: netdev; +Cc: rt2x00-devel

[-- Attachment #1: Type: text/plain, Size: 6511 bytes --]

From: Ivo van Doorn <IvDoorn@gmail.com>

Misc. small fixes. Add small comments,
remove unwanted whitespaces etc.

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:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 22:06:22.000000000 +0200
@@ -1003,7 +1003,7 @@ rt2400pci_txdone(void *data)
 	int			tx_status;
 	int			ack;
 
-	 while (!rt2x00_ring_empty(ring)) {
+	while (!rt2x00_ring_empty(ring)) {
 		entry = rt2x00_get_data_entry_done(ring);
 		txd = entry->desc_addr;
 
@@ -1212,7 +1212,7 @@ rt2400pci_free_ring(struct rt2x00_pci *r
 			ring->data_addr, ring->data_dma);
 	ring->data_addr = NULL;
 
-		kfree(ring->entry);
+	kfree(ring->entry);
 	ring->entry = NULL;
 }
 
@@ -1318,6 +1318,9 @@ rt2400pci_init_rings(struct rt2x00_pci *
 {
 	u32		reg;
 
+	/*
+	 * Initialize rings.
+	 */
 	rt2400pci_init_rxdesc(rt2x00pci, &rt2x00pci->ring[RING_RX]);
 	rt2400pci_init_txdesc(rt2x00pci, &rt2x00pci->ring[RING_TX]);
 	rt2400pci_init_txdesc(rt2x00pci, &rt2x00pci->ring[RING_ATIM]);
@@ -1847,7 +1850,7 @@ rt2400pci_config_interface(struct net_de
 	rt2400pci_config_bssid(rt2x00pci, conf->bssid);
 
 	return 0;
- }
+}
 
 static void
 rt2400pci_set_multicast_list(struct net_device *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:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 22:06:22.000000000 +0200
@@ -487,7 +487,7 @@ rt2500pci_config_channel(struct rt2x00_p
 
 	if (rt2x00_rf(&rt2x00pci->chip, RF5222)) {
 		if (channel < 14) {
-		rf1 = cpu_to_le32(0x00022020);
+			rf1 = cpu_to_le32(0x00022020);
 			rf4 = cpu_to_le32(0x00000a0b);
 		} else if (channel == 14) {
 			rf1 = cpu_to_le32(0x00022010);
@@ -501,7 +501,7 @@ rt2500pci_config_channel(struct rt2x00_p
 		} else if (channel < 161) {
 			rf1 = cpu_to_le32(0x00022020);
 			rf4 = cpu_to_le32(0x00000a07);
-	}
+		}
 	}
 
 	INFO("Switching channel. RF1: 0x%08x, RF2: 0x%08x, RF3: 0x%08x, "
@@ -1091,7 +1091,7 @@ rt2500pci_txdone(void *data)
 	int			tx_status;
 	int			ack;
 
-	 while (!rt2x00_ring_empty(ring)) {
+	while (!rt2x00_ring_empty(ring)) {
 		entry = rt2x00_get_data_entry_done(ring);
 		txd = entry->desc_addr;
 
@@ -1301,7 +1301,7 @@ rt2500pci_free_ring(struct rt2x00_pci *r
 			ring->data_addr, ring->data_dma);
 	ring->data_addr = NULL;
 
-		kfree(ring->entry);
+	kfree(ring->entry);
 	ring->entry = NULL;
 }
 
@@ -2438,7 +2438,7 @@ rt2500pci_init_hw_channels(struct rt2x00
 		for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
 			channels[counter].val =
 				cpu_to_le32(vals[counter] | rf2_base);
-		}
+	}
 	if (rt2x00_rf(&rt2x00pci->chip, RF5222)) {
 		static u32 vals[] = {
 			0x00018896, 0x0001889a, 0x0001889e, 0x000188a2,
@@ -2453,7 +2453,7 @@ rt2500pci_init_hw_channels(struct rt2x00
 	
 		for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
 			(chan++)->val = cpu_to_le32(vals[counter]);
-		}
+	}
 
 	/*
 	 * Set TX power, each EEPROM TXpower entry
@@ -2472,7 +2472,7 @@ rt2500pci_init_hw_channels(struct rt2x00
 			rt2x00_get_field16(eeprom, EEPROM_TXPOWER_2);
 		if (channels[(counter * 2) + 1].power_level > 0x20)
 			channels[(counter * 2) + 1].power_level = 0x18;
-		}
+	}
 
 	/*
 	 * Set device specific, but channel independent RF values.
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:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 22:08:38.000000000 +0200
@@ -335,7 +335,7 @@ rt2500usb_config_channel(struct rt2x00_u
 	|| rt2x00_rf(&rt2x00usb->chip, RF2524)
 	|| rt2x00_rf(&rt2x00usb->chip, RF2525))
 	&& channel == 14)
-			rf4 &= ~0x00000018;
+		rf4 &= ~0x00000018;
 
 	if (rt2x00_rf(&rt2x00usb->chip, RF2525E)) {
 		if (channel & 0x01)
@@ -951,7 +951,7 @@ rt2500usb_txdone(void *data)
 		 * Check if we have received an
 		 * ACK response when ACK was requested and status
 		 * was succesfull.
-		*/
+		 */
 		entry->tx_status.ack = 0;
 		if (ack && (entry->urb->status == TX_SUCCESS))
 			entry->tx_status.ack = 1;
@@ -1636,7 +1636,7 @@ rt2500usb_config_interface(struct net_de
 		return 0;
 
 	rt2500usb_config_bssid(rt2x00usb, conf->bssid);
- 
+
 	return 0;
 }
 
@@ -2071,12 +2071,12 @@ rt2500usb_init_hw_channels(struct rt2x00
 
 		for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
 			channels[counter].val = vals[counter];
-		}
+	}
 
 		/*
 	 * Set TX power, each EEPROM TXpower entry
 	 * contains the TXpower value for 2 channels.
-		 */
+	 */
 	for (counter = 0; counter < EEPROM_TXPOWER_SIZE; counter++) {
 		rt2x00_eeprom_read(rt2x00usb,
 			EEPROM_TXPOWER_START + counter, &eeprom);
@@ -2090,7 +2090,7 @@ rt2500usb_init_hw_channels(struct rt2x00
 			rt2x00_get_field16(eeprom, EEPROM_TXPOWER_2);
 		if (channels[(counter * 2) + 1].power_level > 0x20)
 			channels[(counter * 2) + 1].power_level = 0x18;
-		}
+	}
 
 	/*
 	 * Set device specific, but channel independent RF values.
@@ -2302,7 +2302,6 @@ rt2500usb_init_hw(struct rt2x00_usb *rt2
 	hw->modes[0].num_channels = 14;
 	hw->modes[0].num_rates = 12;
 
-
 	/*
 	 * Intitialize 802.11b
 	 * Rates: CCK.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h	2006-04-27 21:57:18.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h	2006-04-27 22:07:42.000000000 +0200
@@ -44,6 +44,9 @@
  * and should be switched on using the module parameter.
  */
 #ifdef CONFIG_RT2X00_DEBUG
+/*
+ * Module parameter.
+ */
 static int rt2x00_debug_level = 0;
 #define DEBUG_PRINTK(__message...) \
 	do { if (rt2x00_debug_level) printk(__message); } while (0)

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: [PATCH 3/32] rt2x00: use pci_*_consistent for DMA mapping
From: Christoph Hellwig @ 2006-04-27 22:11 UTC (permalink / raw)
  To: Ivo van Doorn; +Cc: netdev, rt2x00-devel
In-Reply-To: <200604280002.52839.IvDoorn@gmail.com>

On Fri, Apr 28, 2006 at 12:02:52AM +0200, Ivo van Doorn wrote:
> From: Ivo van Doorn <IvDoorn@gmail.com>
> 
> Instead of dma_*_coherent
> use pci_*consistent functions.

No point in doing that, quite reverse as you use the gfp_mask argument
which is a (small) pessimation here.


^ permalink raw reply

* Re: [PATCH 20/32] rt2x00: byte ordering correctness
From: Christoph Hellwig @ 2006-04-27 22:13 UTC (permalink / raw)
  To: Ivo van Doorn; +Cc: netdev, rt2x00-devel
In-Reply-To: <200604280003.12743.IvDoorn@gmail.com>

On Fri, Apr 28, 2006 at 12:03:12AM +0200, Ivo van Doorn wrote:
> From: Ivo van Doorn <IvDoorn@gmail.com>
> 
> Fix various little/big endian conversions.
> rt2500pci should use cpu_to_le32 and rt2500usb should not.

While you're at it can you add __be* annotations to the hardware
datastructures so the endianess handling can be verified using sparse?

^ permalink raw reply

* Re: IP1000 gigabit nic driver
From: David Vrabel @ 2006-04-27 22:26 UTC (permalink / raw)
  To: Francois Romieu; +Cc: Linux-kernel, netdev, david
In-Reply-To: <20060427185627.GA30871@electric-eye.fr.zoreil.com>

Francois Romieu wrote:
> David Gómez <david@pleyades.net> :
> [...]
>> Does anybody in this list know why the IP1000 driver is not
>> included in the kernel ?
> 
> Afaik the driver has never been submitted for inclusion.
> At least not on netdev@vger.kernel.org (hint, hint).
> 
> [...]
>> The card in question is:
>>
>> Sundance Technology Inc IC Plus IP1000
>>
>> and the driver can be found in sundance web, sources 
> 
> URL please ?
> 
>> included. I tried to contact the author but my email
>> bounced.
>>
>> There's no LICENSE in the source, just copyrigth
>> sentences in the .c files, so i'm not sure under
>> which license it's distributed :-?.
> 
> /me goes to http://www.icplus.com.tw/driver-pp-IP1000A.html
> 
> $ unzip -c IP1000A-Linux-driver-v2.09f.zip | grep MODULE_LICENSE
>     MODULE_LICENSE("GPL");
> 
> It's a bit bloaty but it does not seem too bad (not mergeable "as
> is" though). Do you volunteer to test random cra^W^W carefully
> engineered code on your computer to help the rework/merging process ?

I finally got around to putting a 2nd NIC in my box that has one of this 
chips and was going to start fixing the driver up and preparing it for 
submission this weekend.  Or I might try rewriting from scratch based on 
the datasheet depending on how horrific the code looks on closer inspection.

Not got a whole lot of time to do this so no timescale for completion...

David Vrabel


^ permalink raw reply

* Re: [PATCH 0/10] [IOAT] I/OAT patches repost
From: Chris Leech @ 2006-04-27 23:45 UTC (permalink / raw)
  To: David S. Miller; +Cc: olof, andrew.grover, netdev
In-Reply-To: <20060420.204200.103377406.davem@davemloft.net>

On 4/20/06, David S. Miller <davem@davemloft.net> wrote:
> Yes, and it means that the memory bandwidth costs are equivalent
> between I/O AT and cpu copy.

The following is a response from the I/OAT architects.  I only point
out that this is not coming directly from me because I have not seen
the data to verify the claims regarding the speed of a copy vs a load
and the cost of the rep mov instruction.  I'll encourage more direct
participation in this discussion from the architects moving forward.

    - Chris

Let's talk about the caching benefits that is seemingly lost when
using the DMA engine. The intent of the DMA engine is to save CPU
cycles spent in copying data (rep mov). In cases where the destination
is already warm in cache (due to destination buffer re-use) and the
source is in memory, the cycles spent in a host copy is not just due
to the cache misses it encounters in the process of bringing in the
source but also due to the execution of rep move itself within the
host core. If you contrast this to simply touching (loading) the data
residing in memory, the cost of this load is primarily the cost of the
cache misses and not so much CPU execution time. Given this, some of
the following points are noteworthy:

1. While the DMA engine forces the destination to be in memory and
touching it may cause the same number of observable cache misses as a
host copy assuming a cache warmed destination, the cost of the host
copy (in terms of CPU cycles) is much more than the cost of the touch.

2. CPU hardware prefetchers do a pretty good job of staying ahead of
the fetch stream to minimize cache misses. So for loads of medium to
large buffers, cache misses form a much smaller component of the data
fetch time…most of it is dominated by front side bus (FSB) or Memory
bandwidth. For small buffers, we do not use the DMA engine but if we
had to, we would insert SW prefetches that do reasonably well.

3. If the destination wasn't already warm in cache i.e., it was in
memory or some CPU other cache, host copy will have to snoop and bring
the destination in and will encounter additional misses on the
destination buffer as well. These misses are the same as those
encountered in #1 above when using the DMA engine and touching the
data afterwards. So in effect it becomes a wash when compared to the
DMA engine's behavior. The case where the destination is already warm
in cache is common in benchmarks such as iperf, ttcp etc. where the
same buffer is reused over and over again. Real applications typically
will not exhibit this aggressive buffer re-use behavior.

4. It may take a large number of packets (and several interrupts) to
satisfy a large posted buffer (say 64KB). Even if you use host copy to
warm the cache with the destination, there is no guarantee that some
or all of the destination will stay in the cache before the
application has a chance to read the data.

5. The source data payload (skb ->data) is typically needed only once
for the copy and has no use later. The host copy brings it into the
cache and may end up polluting the cache, and consuming FSB bandwidth
whereas the DMA engine avoids this altogether.

The IxChariot data posted earlier that touches the data and yet shows
I/OAT benefit is due to some of the reasons above. Bottom line is that
I agree with the cache benefit argument of host copy for small buffers
(64B to 512B) but for larger buffers and certain application scenarios
(destination in memory), the DMA engine will show better performance
regardless of where the destination buffer resided to begin with and
where it is accessed from.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox