Skip to contentSkip to conversation

Please pull 'upstream' branch of rt2x00

PATCH In review Ivo van Doorn 3 participants 18 messages Nov 27, 2007 – Nov 30, 2007 Networking drivers (wireless)

lore
Share & tools
lore
#0 lore raw

Hi John,

Here is the latest version of rt2x00.

Please merge the patches for 2.6.24
09 - Only update rssi average approximation on receiving beacon frames. 10 - Remove redundant code in rfkill setup
11 - Cleanup rfkill

All other patches can wait for 2.6.25, since they are code cleanups and the new TX/RX frame dumping facility through debugfs.

Ivo

---

The following changes since commit 301df40749bdf144c72637795ba93d82e4b84682:
Johannes Berg (1):
mac80211: remove more forgotten code

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/ivd/rt2x00.git/ upstream

Ivo van Doorn (9):
rt2x00: Replace DRV_NAME with KBUILD_MODNAME
rt2x00: Extend PLCP descriptor definition for rt2400pci
rt2x00: Move register value/offset files into new folder
rt2x00: Add chipset version to chipset debugfs entry
rt2x00: Add skb descriptor
rt2x00: Add TX/RX frame dumping facility
rt2x00: Use IEEE80211_IF_TYPE_INVALID directly
rt2x00: Cleanup rfkill
rt2x00: Release rt2x00 2.0.13

Larry Finger (1):
rt2x00: Remove redundant code in rfkill setup

Mattias Nissler (1):
rt2x00: Only update rssi average approximation on receiving beacon frames.

 drivers/net/wireless/rt2x00/rt2400pci.c      |   49 ++----
 drivers/net/wireless/rt2x00/rt2400pci.h      |   20 ++-
 drivers/net/wireless/rt2x00/rt2500pci.c      |    9 +-
 drivers/net/wireless/rt2x00/rt2500usb.c      |   39 +++--
 drivers/net/wireless/rt2x00/rt2x00.h         |   26 ++-
 drivers/net/wireless/rt2x00/rt2x00config.c   |    5 -
 drivers/net/wireless/rt2x00/rt2x00debug.c    |  240 +++++++++++++++++++++++---
 drivers/net/wireless/rt2x00/rt2x00dev.c      |   93 ++++++----
 drivers/net/wireless/rt2x00/rt2x00firmware.c |    5 -
 drivers/net/wireless/rt2x00/rt2x00lib.h      |    6 +
 drivers/net/wireless/rt2x00/rt2x00mac.c      |    7 +-
 drivers/net/wireless/rt2x00/rt2x00pci.c      |   59 +++++--
 drivers/net/wireless/rt2x00/rt2x00rfkill.c   |   15 --
 drivers/net/wireless/rt2x00/rt2x00ring.h     |   22 +++
 drivers/net/wireless/rt2x00/rt2x00usb.c      |   41 +++--
 drivers/net/wireless/rt2x00/rt61pci.c        |   36 +++--
 drivers/net/wireless/rt2x00/rt73usb.c        |   36 +++--
 17 files changed, 484 insertions(+), 224 deletions(-)
#1 lore raw

PATCH 1/11 rt2x00: Replace DRV_NAME with KBUILD_MODNAME

DRV_NAME was always set to the KBUILD_MODNAME value, lets clean everything up by removing DRV_NAME and just use KBUILD_MODNAME directly.

---
 drivers/net/wireless/rt2x00/rt2400pci.c      |    9 ++-------
 drivers/net/wireless/rt2x00/rt2500pci.c      |    9 ++-------
 drivers/net/wireless/rt2x00/rt2500usb.c      |    9 ++-------
 drivers/net/wireless/rt2x00/rt2x00.h         |    3 +--
 drivers/net/wireless/rt2x00/rt2x00config.c   |    5 -----
 drivers/net/wireless/rt2x00/rt2x00debug.c    |    5 -----
 drivers/net/wireless/rt2x00/rt2x00dev.c      |    5 -----
 drivers/net/wireless/rt2x00/rt2x00firmware.c |    5 -----
 drivers/net/wireless/rt2x00/rt2x00mac.c      |    5 -----
 drivers/net/wireless/rt2x00/rt2x00pci.c      |    5 -----
 drivers/net/wireless/rt2x00/rt2x00rfkill.c   |    5 -----
 drivers/net/wireless/rt2x00/rt2x00usb.c      |    5 -----
 drivers/net/wireless/rt2x00/rt61pci.c        |    9 ++-------
 drivers/net/wireless/rt2x00/rt73usb.c        |    9 ++-------
 14 files changed, 11 insertions(+), 77 deletions(-)
drivers/net/wireless/rt2x00/rt2400pci.c +2 -7
index bdf3edc..6d3cdaf 100644
@@ -24,11 +24,6 @@
 	Supported chipsets: RT2460.
  */
 
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2400pci"
-
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
@@ -1610,7 +1605,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
 };
 
 static const struct rt2x00_ops rt2400pci_ops = {
-	.name		= DRV_NAME,
+	.name		= KBUILD_MODNAME,
 	.rxd_size	= RXD_DESC_SIZE,
 	.txd_size	= TXD_DESC_SIZE,
 	.eeprom_size	= EEPROM_SIZE,
@@ -1638,7 +1633,7 @@ MODULE_DEVICE_TABLE(pci, rt2400pci_device_table);
 MODULE_LICENSE("GPL");
 
 static struct pci_driver rt2400pci_driver = {
-	.name		= DRV_NAME,
+	.name		= KBUILD_MODNAME,
 	.id_table	= rt2400pci_device_table,
 	.probe		= rt2x00pci_probe,
 	.remove		= __devexit_p(rt2x00pci_remove),
drivers/net/wireless/rt2x00/rt2500pci.c +2 -7
index b6bb964..a623454 100644
@@ -24,11 +24,6 @@
 	Supported chipsets: RT2560.
  */
 
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2500pci"
-
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
@@ -1903,7 +1898,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
 };
 
 static const struct rt2x00_ops rt2500pci_ops = {
-	.name		= DRV_NAME,
+	.name		= KBUILD_MODNAME,
 	.rxd_size	= RXD_DESC_SIZE,
 	.txd_size	= TXD_DESC_SIZE,
 	.eeprom_size	= EEPROM_SIZE,
@@ -1931,7 +1926,7 @@ MODULE_DEVICE_TABLE(pci, rt2500pci_device_table);
 MODULE_LICENSE("GPL");
 
 static struct pci_driver rt2500pci_driver = {
-	.name		= DRV_NAME,
+	.name		= KBUILD_MODNAME,
 	.id_table	= rt2500pci_device_table,
 	.probe		= rt2x00pci_probe,
 	.remove		= __devexit_p(rt2x00pci_remove),
drivers/net/wireless/rt2x00/rt2500usb.c +2 -7
index 5bfbac4..f56f3ef 100644
@@ -24,11 +24,6 @@
 	Supported chipsets: RT2570.
  */
 
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2500usb"
-
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
@@ -1790,7 +1785,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
 };
 
 static const struct rt2x00_ops rt2500usb_ops = {
-	.name		= DRV_NAME,
+	.name		= KBUILD_MODNAME,
 	.rxd_size	= RXD_DESC_SIZE,
 	.txd_size	= TXD_DESC_SIZE,
 	.eeprom_size	= EEPROM_SIZE,
@@ -1862,7 +1857,7 @@ MODULE_DEVICE_TABLE(usb, rt2500usb_device_table);
 MODULE_LICENSE("GPL");
 
 static struct usb_driver rt2500usb_driver = {
-	.name		= DRV_NAME,
+	.name		= KBUILD_MODNAME,
 	.id_table	= rt2500usb_device_table,
 	.probe		= rt2x00usb_probe,
 	.disconnect	= rt2x00usb_disconnect,
drivers/net/wireless/rt2x00/rt2x00.h +1 -2
index 84b0fc9..b2283ce 100644
@@ -41,7 +41,6 @@
 
 /*
  * Module information.
- * DRV_NAME should be set within the individual module source files.
  */
 #define DRV_VERSION	"2.0.12"
 #define DRV_PROJECT	"http://rt2x00.serialmonkey.com"
@@ -56,7 +55,7 @@
 
 #define DEBUG_PRINTK_PROBE(__kernlvl, __lvl, __msg, __args...)	\
 	printk(__kernlvl "%s -> %s: %s - " __msg,		\
-	       DRV_NAME, __FUNCTION__, __lvl, ##__args)
+	       KBUILD_MODNAME, __FUNCTION__, __lvl, ##__args)
 
 #ifdef CONFIG_RT2X00_DEBUG
 #define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...)	\
drivers/net/wireless/rt2x00/rt2x00config.c +0 -5
index 9f0733b..72cfe00 100644
@@ -23,11 +23,6 @@
 	Abstract: rt2x00 generic configuration routines.
  */
 
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00lib"
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 
drivers/net/wireless/rt2x00/rt2x00debug.c +0 -5
index 9275d6f..6dc9a25 100644
@@ -23,11 +23,6 @@
 	Abstract: rt2x00 debugfs specific routines.
  */
 
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00lib"
-
 #include <linux/debugfs.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
drivers/net/wireless/rt2x00/rt2x00dev.c +0 -5
index 3ab1fb9..e894978 100644
@@ -23,11 +23,6 @@
 	Abstract: rt2x00 generic device routines.
  */
 
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00lib"
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 
drivers/net/wireless/rt2x00/rt2x00firmware.c +0 -5
index 236025f..0a475e4 100644
@@ -23,11 +23,6 @@
 	Abstract: rt2x00 firmware loading routines.
  */
 
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00lib"
-
 #include <linux/crc-itu-t.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
drivers/net/wireless/rt2x00/rt2x00mac.c +0 -5
index 85ea8a8..e216c34 100644
@@ -23,11 +23,6 @@
 	Abstract: rt2x00 generic mac80211 routines.
  */
 
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00lib"
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 
drivers/net/wireless/rt2x00/rt2x00pci.c +0 -5
index 30ef4f9..e654568 100644
@@ -23,11 +23,6 @@
 	Abstract: rt2x00 generic pci device routines.
  */
 
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00pci"
-
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
drivers/net/wireless/rt2x00/rt2x00rfkill.c +0 -5
index 16d365d..bbbf51d 100644
@@ -23,11 +23,6 @@
 	Abstract: rt2x00 rfkill routines.
  */
 
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00lib"
-
 #include <linux/input-polldev.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
drivers/net/wireless/rt2x00/rt2x00usb.c +0 -5
index 936e554..152058f 100644
@@ -23,11 +23,6 @@
 	Abstract: rt2x00 generic usb device routines.
  */
 
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00usb"
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/usb.h>
drivers/net/wireless/rt2x00/rt61pci.c +2 -7
index c2b4509..924f415 100644
@@ -24,11 +24,6 @@
 	Supported chipsets: RT2561, RT2561s, RT2661.
  */
 
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt61pci"
-
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
@@ -2498,7 +2493,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
 };
 
 static const struct rt2x00_ops rt61pci_ops = {
-	.name		= DRV_NAME,
+	.name		= KBUILD_MODNAME,
 	.rxd_size	= RXD_DESC_SIZE,
 	.txd_size	= TXD_DESC_SIZE,
 	.eeprom_size	= EEPROM_SIZE,
@@ -2535,7 +2530,7 @@ MODULE_FIRMWARE(FIRMWARE_RT2661);
 MODULE_LICENSE("GPL");
 
 static struct pci_driver rt61pci_driver = {
-	.name		= DRV_NAME,
+	.name		= KBUILD_MODNAME,
 	.id_table	= rt61pci_device_table,
 	.probe		= rt2x00pci_probe,
 	.remove		= __devexit_p(rt2x00pci_remove),
drivers/net/wireless/rt2x00/rt73usb.c +2 -7
index 4d1227a..49180de 100644
@@ -24,11 +24,6 @@
 	Supported chipsets: rt2571W & rt2671.
  */
 
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt73usb"
-
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
@@ -2046,7 +2041,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
 };
 
 static const struct rt2x00_ops rt73usb_ops = {
-	.name		= DRV_NAME,
+	.name		= KBUILD_MODNAME,
 	.rxd_size	= RXD_DESC_SIZE,
 	.txd_size	= TXD_DESC_SIZE,
 	.eeprom_size	= EEPROM_SIZE,
@@ -2133,7 +2128,7 @@ MODULE_FIRMWARE(FIRMWARE_RT2571);
 MODULE_LICENSE("GPL");
 
 static struct usb_driver rt73usb_driver = {
-	.name		= DRV_NAME,
+	.name		= KBUILD_MODNAME,
 	.id_table	= rt73usb_device_table,
 	.probe		= rt2x00usb_probe,
 	.disconnect	= rt2x00usb_disconnect,
Signature · 1 line
1.5.3.6
#2 lore raw

PATCH 2/11 rt2x00: Extend PLCP descriptor definition for rt2400pci

In reply to Ivo van Doorn

Extend word field definitions for the PLCP words in the TX descriptor to contain the BBP fields as well. This will remove rt2400pci_write_tx_desc() from the checkstack script.

---
 drivers/net/wireless/rt2x00/rt2400pci.c |   40 +++++++++---------------------
 drivers/net/wireless/rt2x00/rt2400pci.h |   20 +++++++++++----
 2 files changed, 27 insertions(+), 33 deletions(-)
drivers/net/wireless/rt2x00/rt2400pci.c +12 -28
index 6d3cdaf..c9a234f 100644
@@ -1019,30 +1019,6 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 				    struct ieee80211_tx_control *control)
 {
 	u32 word;
-	u32 signal = 0;
-	u32 service = 0;
-	u32 length_high = 0;
-	u32 length_low = 0;
-
-	/*
-	 * The PLCP values should be treated as if they
-	 * were BBP values.
-	 */
-	rt2x00_set_field32(&signal, BBPCSR_VALUE, desc->signal);
-	rt2x00_set_field32(&signal, BBPCSR_REGNUM, 5);
-	rt2x00_set_field32(&signal, BBPCSR_BUSY, 1);
-
-	rt2x00_set_field32(&service, BBPCSR_VALUE, desc->service);
-	rt2x00_set_field32(&service, BBPCSR_REGNUM, 6);
-	rt2x00_set_field32(&service, BBPCSR_BUSY, 1);
-
-	rt2x00_set_field32(&length_high, BBPCSR_VALUE, desc->length_high);
-	rt2x00_set_field32(&length_high, BBPCSR_REGNUM, 7);
-	rt2x00_set_field32(&length_high, BBPCSR_BUSY, 1);
-
-	rt2x00_set_field32(&length_low, BBPCSR_VALUE, desc->length_low);
-	rt2x00_set_field32(&length_low, BBPCSR_REGNUM, 8);
-	rt2x00_set_field32(&length_low, BBPCSR_BUSY, 1);
 
 	/*
 	 * Start writing the descriptor words.
@@ -1052,13 +1028,21 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	rt2x00_desc_write(txd, 2, word);
 
 	rt2x00_desc_read(txd, 3, &word);
-	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, signal);
-	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, service);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1);
 	rt2x00_desc_write(txd, 3, word);
 
 	rt2x00_desc_read(txd, 4, &word);
-	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, length_low);
-	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, length_high);
+	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, desc->length_low);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1);
+	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, desc->length_high);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1);
 	rt2x00_desc_write(txd, 4, word);
 
 	rt2x00_desc_read(txd, 0, &word);
drivers/net/wireless/rt2x00/rt2400pci.h +15 -5
index f5dbde7..369aac6 100644
@@ -839,11 +839,21 @@
 
 /*
  * Word3 & 4: PLCP information
- */
-#define TXD_W3_PLCP_SIGNAL		FIELD32(0x0000ffff)
-#define TXD_W3_PLCP_SERVICE		FIELD32(0xffff0000)
-#define TXD_W4_PLCP_LENGTH_LOW		FIELD32(0x0000ffff)
-#define TXD_W4_PLCP_LENGTH_HIGH		FIELD32(0xffff0000)
+ * The PLCP values should be treated as if they were BBP values.
+ */
+#define TXD_W3_PLCP_SIGNAL		FIELD32(0x000000ff)
+#define TXD_W3_PLCP_SIGNAL_REGNUM	FIELD32(0x00007f00)
+#define TXD_W3_PLCP_SIGNAL_BUSY		FIELD32(0x00008000)
+#define TXD_W3_PLCP_SERVICE		FIELD32(0x00ff0000)
+#define TXD_W3_PLCP_SERVICE_REGNUM	FIELD32(0x7f000000)
+#define TXD_W3_PLCP_SERVICE_BUSY	FIELD32(0x80000000)
+
+#define TXD_W4_PLCP_LENGTH_LOW		FIELD32(0x000000ff)
+#define TXD_W3_PLCP_LENGTH_LOW_REGNUM	FIELD32(0x00007f00)
+#define TXD_W3_PLCP_LENGTH_LOW_BUSY	FIELD32(0x00008000)
+#define TXD_W4_PLCP_LENGTH_HIGH		FIELD32(0x00ff0000)
+#define TXD_W3_PLCP_LENGTH_HIGH_REGNUM	FIELD32(0x7f000000)
+#define TXD_W3_PLCP_LENGTH_HIGH_BUSY	FIELD32(0x80000000)
 
 /*
  * Word5
Signature · 1 line
1.5.3.6
#3 lore raw

PATCH 3/11 rt2x00: Move register value/offset files into new folder

In reply to Ivo van Doorn

Cleanup debugfs interface by moving the csr/bbp/rf/eeprom value/offset entries into the "register" folder.

---
 drivers/net/wireless/rt2x00/rt2x00debug.c |   42 +++++++++++++++++-----------
 1 files changed, 25 insertions(+), 17 deletions(-)
drivers/net/wireless/rt2x00/rt2x00debug.c +25 -17
index 6dc9a25..92efc5a 100644
@@ -50,18 +50,20 @@ struct rt2x00debug_intf {
 	/*
 	 * Debugfs entries for:
 	 * - driver folder
-	 * - driver file
-	 * - chipset file
-	 * - device flags file
-	 * - register offset/value files
-	 * - eeprom offset/value files
-	 * - bbp offset/value files
-	 * - rf offset/value files
+	 *   - driver file
+	 *   - chipset file
+	 *   - device flags file
+	 *   - register folder
+	 *     - csr offset/value files
+	 *     - eeprom offset/value files
+	 *     - bbp offset/value files
+	 *     - rf offset/value files
 	 */
 	struct dentry *driver_folder;
 	struct dentry *driver_entry;
 	struct dentry *chipset_entry;
 	struct dentry *dev_flags;
+	struct dentry *register_folder;
 	struct dentry *csr_off_entry;
 	struct dentry *csr_val_entry;
 	struct dentry *eeprom_off_entry;
@@ -115,7 +117,7 @@ static ssize_t rt2x00debug_read_##__name(struct file *file,	\
 					 size_t length,		\
 					 loff_t *offset)	\
 {								\
-	struct rt2x00debug_intf *intf =	file->private_data;	\
+	struct rt2x00debug_intf *intf = file->private_data;	\
 	const struct rt2x00debug *debug = intf->debug;		\
 	char line[16];						\
 	size_t size;						\
@@ -145,7 +147,7 @@ static ssize_t rt2x00debug_write_##__name(struct file *file,	\
 					  size_t length,	\
 					  loff_t *offset)	\
 {								\
-	struct rt2x00debug_intf *intf =	file->private_data;	\
+	struct rt2x00debug_intf *intf = file->private_data;	\
 	const struct rt2x00debug *debug = intf->debug;		\
 	char line[16];						\
 	size_t size;						\
@@ -301,12 +303,17 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 	if (IS_ERR(intf->dev_flags))
 		goto exit;
 
-#define RT2X00DEBUGFS_CREATE_ENTRY(__intf, __name)		\
+	intf->register_folder =
+	    debugfs_create_dir("register", intf->driver_folder);
+	if (IS_ERR(intf->register_folder))
+		goto exit;
+
+#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name)	\
 ({								\
 	(__intf)->__name##_off_entry =				\
 	    debugfs_create_u32(__stringify(__name) "_offset",	\
 			       S_IRUGO | S_IWUSR,		\
-			       (__intf)->driver_folder,		\
+			       (__intf)->register_folder,	\
 			       &(__intf)->offset_##__name);	\
 	if (IS_ERR((__intf)->__name##_off_entry))		\
 		goto exit;					\
@@ -314,18 +321,18 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 	(__intf)->__name##_val_entry =				\
 	    debugfs_create_file(__stringify(__name) "_value",	\
 				S_IRUGO | S_IWUSR,		\
-				(__intf)->driver_folder,	\
+				(__intf)->register_folder,	\
 				(__intf), &rt2x00debug_fop_##__name);\
 	if (IS_ERR((__intf)->__name##_val_entry))		\
 		goto exit;					\
 })
 
-	RT2X00DEBUGFS_CREATE_ENTRY(intf, csr);
-	RT2X00DEBUGFS_CREATE_ENTRY(intf, eeprom);
-	RT2X00DEBUGFS_CREATE_ENTRY(intf, bbp);
-	RT2X00DEBUGFS_CREATE_ENTRY(intf, rf);
+	RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, csr);
+	RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, eeprom);
+	RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, bbp);
+	RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rf);
 
-#undef RT2X00DEBUGFS_CREATE_ENTRY
+#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
 
 	return;
 
@@ -351,6 +358,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
 	debugfs_remove(intf->eeprom_off_entry);
 	debugfs_remove(intf->csr_val_entry);
 	debugfs_remove(intf->csr_off_entry);
+	debugfs_remove(intf->register_folder);
 	debugfs_remove(intf->dev_flags);
 	debugfs_remove(intf->chipset_entry);
 	debugfs_remove(intf->driver_entry);
Signature · 1 line
1.5.3.6
#4 lore raw

PATCH 4/11 rt2x00: Add chipset version to chipset debugfs entry

In reply to Ivo van Doorn

The chipset debugfs entry already indicates it is about the chipset, it only makes sense to also display the chipset version in there.

---
 drivers/net/wireless/rt2x00/rt2x00debug.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)
drivers/net/wireless/rt2x00/rt2x00debug.c +8 -3
index 92efc5a..3aa7e0a 100644
@@ -251,16 +251,21 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
 	const struct rt2x00debug *debug = intf->debug;
 	char *data;
 
-	data = kzalloc(4 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
+	data = kzalloc(8 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
 	if (!data)
 		return NULL;
 
-	blob->data = data;
+	data += sprintf(data, "rt chip: %04x\n", intf->rt2x00dev->chip.rt);
+	data += sprintf(data, "rf chip: %04x\n", intf->rt2x00dev->chip.rf);
+	data += sprintf(data, "revision:%08x\n", intf->rt2x00dev->chip.rev);
+	data += sprintf(data, "\n");
 	data += sprintf(data, "csr length: %d\n", debug->csr.word_count);
 	data += sprintf(data, "eeprom length: %d\n", debug->eeprom.word_count);
 	data += sprintf(data, "bbp length: %d\n", debug->bbp.word_count);
 	data += sprintf(data, "rf length: %d\n", debug->rf.word_count);
-	blob->size = strlen(blob->data);
+
+	blob->data = data;
+	blob->size = strlen(data);
 
 	return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob);
 }
Signature · 1 line
1.5.3.6
#10 lore raw

PATCH 7/11 rt2x00: Use IEEE80211_IF_TYPE_INVALID directly

In reply to Ivo van Doorn

No need to use a seperate define INVALID_INTERFACE while we can use IEEE80211_IF_TYPE_INVALID directly.

---
 drivers/net/wireless/rt2x00/rt2x00.h    |    2 --
 drivers/net/wireless/rt2x00/rt2x00dev.c |    2 +-
 drivers/net/wireless/rt2x00/rt2x00mac.c |    2 +-
 3 files changed, 2 insertions(+), 4 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +0 -2
index ba874cf..103a122 100644
@@ -369,10 +369,8 @@ struct interface {
 
 	/*
 	 * Current working type (IEEE80211_IF_TYPE_*).
-	 * When set to INVALID_INTERFACE, no interface is configured.
 	 */
 	int type;
-#define INVALID_INTERFACE	IEEE80211_IF_TYPE_INVALID
 
 	/*
 	 * MAC of the device.
drivers/net/wireless/rt2x00/rt2x00dev.c +1 -1
index 48e2515..bd7b738 100644
@@ -1170,7 +1170,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Reset current working type.
 	 */
-	rt2x00dev->interface.type = INVALID_INTERFACE;
+	rt2x00dev->interface.type = IEEE80211_IF_TYPE_INVALID;
 
 	/*
 	 * Allocate ring array.
drivers/net/wireless/rt2x00/rt2x00mac.c +1 -1
index e216c34..bae4442 100644
@@ -242,7 +242,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
 		return;
 
 	intf->id = 0;
-	intf->type = INVALID_INTERFACE;
+	intf->type = IEEE80211_IF_TYPE_INVALID;
 	memset(&intf->bssid, 0x00, ETH_ALEN);
 	memset(&intf->mac, 0x00, ETH_ALEN);
 
Signature · 1 line
1.5.3.6
#6 lore raw

PATCH 1/1 rt2x00: Only update rssi average approximation on receiving beacon frames.

In reply to Ivo van Doorn

From: Mattias Nissler <[email protected]>

Restrict rssi average updating to beacon frames of the bssid the interface is
associated with. Without this restriction, strong signals belonging to other BSS, e.g. beacon frames coming from a nearby AP, would cause incorrectly high rssi approximation values. This would then cause the link tuner to reduce sensitivity, resulting in transmissions from the BSS associated to to be missed.

---
 drivers/net/wireless/rt2x00/rt2x00.h    |    7 +++++++
 drivers/net/wireless/rt2x00/rt2x00dev.c |   19 ++++++++++++++++++-
 2 files changed, 25 insertions(+), 1 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +7 -0
index 103a122..218068b 100644
@@ -32,6 +32,7 @@
 #include <linux/workqueue.h>
 #include <linux/firmware.h>
 #include <linux/mutex.h>
+#include <linux/etherdevice.h>
 
 #include <net/mac80211.h>
 
@@ -149,6 +150,12 @@ static inline int is_probe_resp(u16 fc)
 		((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP));
 }
 
+static inline int is_beacon(u16 fc)
+{
+	return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
+		((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON));
+}
+
 /*
  * Chipset identification
  * The chipset on the device is composed of a RT and RF chip.
drivers/net/wireless/rt2x00/rt2x00dev.c +18 -1
index bd7b738..a771a09 100644
@@ -526,11 +526,14 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
 		      struct rxdata_entry_desc *desc)
 {
 	struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev;
+	struct interface *intf = &rt2x00dev->interface;
 	struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
 	struct ieee80211_hw_mode *mode;
 	struct ieee80211_rate *rate;
+	struct ieee80211_hdr *hdr;
 	unsigned int i;
 	int val = 0;
+	u16 fc;
 
 	/*
 	 * Update RX statistics.
@@ -555,7 +558,21 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
 		}
 	}
 
-	rt2x00lib_update_link_stats(&rt2x00dev->link, desc->rssi);
+	/*
+	 * Only update link status if this is a beacon frame carrying our
+	 * bssid.
+	 */
+	hdr = (struct ieee80211_hdr *) skb->data;
+	if (skb->len >= sizeof(struct ieee80211_hdr *)) {
+		fc = le16_to_cpu(hdr->frame_control);
+		if ((intf->type == IEEE80211_IF_TYPE_STA
+		     || intf->type == IEEE80211_IF_TYPE_IBSS)
+		    && is_beacon(fc)
+		    && compare_ether_addr(hdr->addr3, intf->bssid) == 0)
+			rt2x00lib_update_link_stats(&rt2x00dev->link,
+						    desc->rssi);
+	}
+
 	rt2x00dev->link.qual.rx_success++;
 
 	rx_status->rate = val;
Signature · 1 line
1.5.3.6
#11 lore raw

PATCH 8/11 rt2x00: Use IEEE80211_IF_TYPE_INVALID directly

In reply to Ivo van Doorn

From: Mattias Nissler <[email protected]>

Restrict rssi average updating to beacon frames of the bssid the interface is
associated with. Without this restriction, strong signals belonging to other BSS, e.g. beacon frames coming from a nearby AP, would cause incorrectly high rssi approximation values. This would then cause the link tuner to reduce sensitivity, resulting in transmissions from the BSS associated to to be missed.

---
 drivers/net/wireless/rt2x00/rt2x00.h    |    7 +++++++
 drivers/net/wireless/rt2x00/rt2x00dev.c |   19 ++++++++++++++++++-
 2 files changed, 25 insertions(+), 1 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +7 -0
index 103a122..218068b 100644
@@ -32,6 +32,7 @@
 #include <linux/workqueue.h>
 #include <linux/firmware.h>
 #include <linux/mutex.h>
+#include <linux/etherdevice.h>
 
 #include <net/mac80211.h>
 
@@ -149,6 +150,12 @@ static inline int is_probe_resp(u16 fc)
 		((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP));
 }
 
+static inline int is_beacon(u16 fc)
+{
+	return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
+		((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON));
+}
+
 /*
  * Chipset identification
  * The chipset on the device is composed of a RT and RF chip.
drivers/net/wireless/rt2x00/rt2x00dev.c +18 -1
index bd7b738..a771a09 100644
@@ -526,11 +526,14 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
 		      struct rxdata_entry_desc *desc)
 {
 	struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev;
+	struct interface *intf = &rt2x00dev->interface;
 	struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
 	struct ieee80211_hw_mode *mode;
 	struct ieee80211_rate *rate;
+	struct ieee80211_hdr *hdr;
 	unsigned int i;
 	int val = 0;
+	u16 fc;
 
 	/*
 	 * Update RX statistics.
@@ -555,7 +558,21 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
 		}
 	}
 
-	rt2x00lib_update_link_stats(&rt2x00dev->link, desc->rssi);
+	/*
+	 * Only update link status if this is a beacon frame carrying our
+	 * bssid.
+	 */
+	hdr = (struct ieee80211_hdr *) skb->data;
+	if (skb->len >= sizeof(struct ieee80211_hdr *)) {
+		fc = le16_to_cpu(hdr->frame_control);
+		if ((intf->type == IEEE80211_IF_TYPE_STA
+		     || intf->type == IEEE80211_IF_TYPE_IBSS)
+		    && is_beacon(fc)
+		    && compare_ether_addr(hdr->addr3, intf->bssid) == 0)
+			rt2x00lib_update_link_stats(&rt2x00dev->link,
+						    desc->rssi);
+	}
+
 	rt2x00dev->link.qual.rx_success++;
 
 	rx_status->rate = val;
Signature · 1 line
1.5.3.6
#12 lore raw

PATCH 9/11 rt2x00: Remove redundant code in rfkill setup

In reply to Ivo van Doorn

From: Larry Finger <[email protected]>

In rt2x00rfkill.c, routine input_allocate_device() is called even though input_allocate_polled_device(), which was just called, includes a call to that routine. This patch, which has not been tested, removes the redundant code.

---
 drivers/net/wireless/rt2x00/rt2x00rfkill.c |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)
drivers/net/wireless/rt2x00/rt2x00rfkill.c +0 -6
index bbbf51d..7439637 100644
@@ -136,12 +136,6 @@ int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
 	rt2x00dev->poll_dev->poll = rt2x00rfkill_poll;
 	rt2x00dev->poll_dev->poll_interval = RFKILL_POLL_INTERVAL;
 
-	rt2x00dev->poll_dev->input = input_allocate_device();
-	if (!rt2x00dev->poll_dev->input) {
-		ERROR(rt2x00dev, "Failed to allocate input device.\n");
-		goto exit_free_polldev;
-	}
-
 	rt2x00dev->poll_dev->input->name = rt2x00dev->ops->name;
 	rt2x00dev->poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy);
 	rt2x00dev->poll_dev->input->id.bustype = BUS_HOST;
Signature · 1 line
1.5.3.6
#16 lore raw

PATCH 10/11 rt2x00: Cleanup rfkill

In reply to Ivo van Doorn

The label exit_free_polldev is no longer used and can be removed. input_free_polled_device() also calls input_free_device(), so don't call it seperatly.

---
 drivers/net/wireless/rt2x00/rt2x00rfkill.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)
drivers/net/wireless/rt2x00/rt2x00rfkill.c +0 -4
index 7439637..34a96d4 100644
@@ -148,9 +148,6 @@ int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
 
 	return 0;
 
-exit_free_polldev:
-	input_free_polled_device(rt2x00dev->poll_dev);
-
 exit_free_rfkill:
 	rfkill_free(rt2x00dev->rfkill);
 
@@ -163,7 +160,6 @@ void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
 	if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
 		return;
 
-	input_free_device(rt2x00dev->poll_dev->input);
 	input_free_polled_device(rt2x00dev->poll_dev);
 	rfkill_free(rt2x00dev->rfkill);
 }
Signature · 1 line
1.5.3.6
#17 lore raw

PATCH 11/11 rt2x00: Release rt2x00 2.0.13

In reply to Ivo van Doorn
---
 drivers/net/wireless/rt2x00/rt2x00.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +1 -1
index 218068b..85cfdab 100644
@@ -43,7 +43,7 @@
 /*
  * Module information.
  */
-#define DRV_VERSION	"2.0.12"
+#define DRV_VERSION	"2.0.13"
 #define DRV_PROJECT	"http://rt2x00.serialmonkey.com"
 
 /*
Signature · 1 line
1.5.3.6
#13 lore raw
In reply to Ivo van Doorn

Hi,

Quoted 4 lines

Please merge the patches for 2.6.24
09 - Only update rssi average approximation on receiving beacon frames. 10 - Remove redundant code in rfkill setup
11 - Cleanup rfkill

Sorry that should be:
08 - Only update rssi average approximation on receiving beacon frames. 09 - Remove redundant code in rfkill setup
10 - Cleanup rfkill

Ivo

#5 lore raw

PATCH 5/11 rt2x00: Add skb descriptor

In reply to Ivo van Doorn

Use the skb->cb field to add a frame description that can be used to transfer information passed each rt2x00 layer. This reduces the required arguments for rt2x00lib_write_tx_desc().

---
 drivers/net/wireless/rt2x00/rt2500usb.c  |   30 +++++++++++-----
 drivers/net/wireless/rt2x00/rt2x00.h     |    4 +--
 drivers/net/wireless/rt2x00/rt2x00dev.c  |   47 ++++++++++++--------------
 drivers/net/wireless/rt2x00/rt2x00pci.c  |   54 ++++++++++++++++++++++-------
 drivers/net/wireless/rt2x00/rt2x00ring.h |   22 ++++++++++++
 drivers/net/wireless/rt2x00/rt2x00usb.c  |   36 +++++++++++++++-----
 drivers/net/wireless/rt2x00/rt61pci.c    |   27 +++++++++++----
 drivers/net/wireless/rt2x00/rt73usb.c    |   27 +++++++++++----
 8 files changed, 174 insertions(+), 73 deletions(-)
drivers/net/wireless/rt2x00/rt2500usb.c +21 -9
index f56f3ef..2ba8eda 100644
@@ -1686,8 +1686,8 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct usb_device *usb_dev =
 	    interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
-	struct data_ring *ring =
-	    rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
+	struct skb_desc *desc;
+	struct data_ring *ring;
 	struct data_entry *beacon;
 	struct data_entry *guardian;
 	int pipe = usb_sndbulkpipe(usb_dev, 1);
@@ -1699,6 +1699,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
 	 * initialization.
 	 */
 	control->queue = IEEE80211_TX_QUEUE_BEACON;
+	ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
 
 	/*
 	 * Obtain 2 entries, one for the guardian byte,
@@ -1709,23 +1710,34 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
 	beacon = rt2x00_get_data_entry(ring);
 
 	/*
-	 * First we create the beacon.
+	 * Add the descriptor in front of the skb.
 	 */
 	skb_push(skb, ring->desc_size);
 	memset(skb->data, 0, ring->desc_size);
 
-	rt2x00lib_write_tx_desc(rt2x00dev, (__le32 *)skb->data,
-				(struct ieee80211_hdr *)(skb->data +
-							 ring->desc_size),
-				skb->len - ring->desc_size, control);
+	/*
+	 * Fill in skb descriptor
+	 */
+	desc = get_skb_desc(skb);
+	desc->desc_len = ring->desc_size;
+	desc->data_len = skb->len - ring->desc_size;
+	desc->desc = skb->data;
+	desc->data = skb->data + ring->desc_size;
+	desc->ring = ring;
+	desc->entry = beacon;
+
+	rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
 
+	/*
+	 * USB devices cannot blindly pass the skb->len as the
+	 * length of the data to usb_fill_bulk_urb. Pass the skb
+	 * to the driver to determine what the length should be.
+	 */
 	length = rt2500usb_get_tx_data_len(rt2x00dev, skb);
 
 	usb_fill_bulk_urb(beacon->priv, usb_dev, pipe,
 			  skb->data, length, rt2500usb_beacondone, beacon);
 
-	beacon->skb = skb;
-
 	/*
 	 * Second we need to create the guardian byte.
 	 * We only need a single byte, so lets recycle
drivers/net/wireless/rt2x00/rt2x00.h +1 -3
index b2283ce..31e48c2 100644
@@ -901,9 +901,7 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
  * TX descriptor initializer
  */
 void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
-			     __le32 *txd,
-			     struct ieee80211_hdr *ieee80211hdr,
-			     unsigned int length,
+			     struct sk_buff *skb,
 			     struct ieee80211_tx_control *control);
 
 /*
drivers/net/wireless/rt2x00/rt2x00dev.c +22 -25

83 lines not on this page · raw message

drivers/net/wireless/rt2x00/rt2x00pci.c +41 -13

103 lines not on this page · raw message

drivers/net/wireless/rt2x00/rt2x00ring.h +22 -0
index 5b871ad..5b32f3e 100644
@@ -27,6 +27,28 @@
 #define RT2X00RING_H
 
 /*
+ * skb_desc
+ * Descriptor information for the skb buffer
+ */
+struct skb_desc {
+	unsigned int frame_type;
+
+	unsigned int desc_len;
+	unsigned int data_len;
+
+	void *desc;
+	void *data;
+
+	struct data_ring *ring;
+	struct data_entry *entry;
+};
+
+static inline struct skb_desc* get_skb_desc(struct sk_buff *skb)
+{
+	return (struct skb_desc*)&skb->cb[0];
+}
+
+/*
  * rxdata_entry_desc
  * Summary of information that has been read from the
  * RX frame descriptor.
drivers/net/wireless/rt2x00/rt2x00usb.c +27 -9
index 152058f..f1282c6 100644
@@ -176,7 +176,7 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
 	struct usb_device *usb_dev =
 	    interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
 	struct data_entry *entry = rt2x00_get_data_entry(ring);
-	int pipe = usb_sndbulkpipe(usb_dev, 1);
+	struct skb_desc *desc;
 	u32 length;
 
 	if (rt2x00_ring_full(ring)) {
@@ -199,12 +199,18 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
 	skb_push(skb, ring->desc_size);
 	memset(skb->data, 0, ring->desc_size);
 
-	rt2x00lib_write_tx_desc(rt2x00dev, (__le32 *)skb->data,
-				(struct ieee80211_hdr *)(skb->data +
-							 ring->desc_size),
-				skb->len - ring->desc_size, control);
-	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	entry->skb = skb;
+	/*
+	 * Fill in skb descriptor
+	 */
+	desc = get_skb_desc(skb);
+	desc->desc_len = ring->desc_size;
+	desc->data_len = skb->len - ring->desc_size;
+	desc->desc = skb->data;
+	desc->data = skb->data + ring->desc_size;
+	desc->ring = ring;
+	desc->entry = entry;
+
+	rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
 
 	/*
 	 * USB devices cannot blindly pass the skb->len as the
@@ -217,7 +223,7 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
 	 * Initialize URB and send the frame to the device.
 	 */
 	__set_bit(ENTRY_OWNER_NIC, &entry->flags);
-	usb_fill_bulk_urb(entry->priv, usb_dev, pipe,
+	usb_fill_bulk_urb(entry->priv, usb_dev, usb_sndbulkpipe(usb_dev, 1),
 			  skb->data, length, rt2x00usb_interrupt_txdone, entry);
 	usb_submit_urb(entry->priv, GFP_ATOMIC);
 
@@ -239,6 +245,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
 	struct data_ring *ring = entry->ring;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct sk_buff *skb;
+	struct skb_desc *skbdesc;
 	struct rxdata_entry_desc desc;
 	int frame_size;
 
@@ -254,7 +261,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
 	if (urb->actual_length < entry->ring->desc_size || urb->status)
 		goto skip_entry;
 
-	memset(&desc, 0x00, sizeof(desc));
+	memset(&desc, 0, sizeof(desc));
 	rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
 
 	/*
@@ -277,6 +284,17 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
 	skb_trim(entry->skb, desc.size);
 
 	/*
+	 * Fill in skb descriptor
+	 */
+	skbdesc = get_skb_desc(entry->skb);
+	skbdesc->desc_len = desc.size;
+	skbdesc->data_len = entry->ring->desc_size;
+	skbdesc->desc = entry->skb->data + desc.size;
+	skbdesc->data = entry->skb->data;
+	skbdesc->ring = ring;
+	skbdesc->entry = entry;
+
+	/*
 	 * Send the frame to rt2x00lib for further processing.
 	 */
 	rt2x00lib_rxdone(entry, entry->skb, &desc);
drivers/net/wireless/rt2x00/rt61pci.c +20 -7
index 924f415..13c8086 100644
@@ -2409,6 +2409,9 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 			  struct ieee80211_tx_control *control)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
+	struct skb_desc *desc;
+	struct data_ring *ring;
+	struct data_entry *entry;
 
 	/*
 	 * Just in case the ieee80211 doesn't set this,
@@ -2416,6 +2419,8 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 	 * initialization.
 	 */
 	control->queue = IEEE80211_TX_QUEUE_BEACON;
+	ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
+	entry = rt2x00_get_data_entry(ring);
 
 	/*
 	 * We need to append the descriptor in front of the
@@ -2429,15 +2434,23 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 	}
 
 	/*
-	 * First we create the beacon.
+	 * Add the descriptor in front of the skb.
+	 */
+	skb_push(skb, ring->desc_size);
+	memset(skb->data, 0, ring->desc_size);
+
+	/*
+	 * Fill in skb descriptor
 	 */
-	skb_push(skb, TXD_DESC_SIZE);
-	memset(skb->data, 0, TXD_DESC_SIZE);
+	desc = get_skb_desc(skb);
+	desc->desc_len = ring->desc_size;
+	desc->data_len = skb->len - ring->desc_size;
+	desc->desc = skb->data;
+	desc->data = skb->data + ring->desc_size;
+	desc->ring = ring;
+	desc->entry = entry;
 
-	rt2x00lib_write_tx_desc(rt2x00dev, (__le32 *)skb->data,
-				(struct ieee80211_hdr *)(skb->data +
-							 TXD_DESC_SIZE),
-				skb->len - TXD_DESC_SIZE, control);
+	rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
 
 	/*
 	 * Write entire beacon with descriptor to register,
drivers/net/wireless/rt2x00/rt73usb.c +20 -7
index 49180de..8093a4d 100644
@@ -1965,6 +1965,9 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 			  struct ieee80211_tx_control *control)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
+	struct skb_desc *desc;
+	struct data_ring *ring;
+	struct data_entry *entry;
 	int timeout;
 
 	/*
@@ -1973,17 +1976,27 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 	 * initialization.
 	 */
 	control->queue = IEEE80211_TX_QUEUE_BEACON;
+	ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
+	entry = rt2x00_get_data_entry(ring);
 
 	/*
-	 * First we create the beacon.
+	 * Add the descriptor in front of the skb.
 	 */
-	skb_push(skb, TXD_DESC_SIZE);
-	memset(skb->data, 0, TXD_DESC_SIZE);
+	skb_push(skb, ring->desc_size);
+	memset(skb->data, 0, ring->desc_size);
 
-	rt2x00lib_write_tx_desc(rt2x00dev, (__le32 *)skb->data,
-				(struct ieee80211_hdr *)(skb->data +
-							 TXD_DESC_SIZE),
-				skb->len - TXD_DESC_SIZE, control);
+	/*
+	 * Fill in skb descriptor
+	 */
+	desc = get_skb_desc(skb);
+	desc->desc_len = ring->desc_size;
+	desc->data_len = skb->len - ring->desc_size;
+	desc->desc = skb->data;
+	desc->data = skb->data + ring->desc_size;
+	desc->ring = ring;
+	desc->entry = entry;
+
+	rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
 
 	/*
 	 * Write entire beacon with descriptor to register,
Signature · 1 line
1.5.3.6
#7 lore raw

PATCH 6/11 rt2x00: Add TX/RX frame dumping facility

In reply to Ivo van Doorn

This adds TX/RX frame dumping capabilities through debugfs. The intention is that with this approach debugging of rt2x00 is simplified since _all_ frames going in and out of the device are send to debugfs as well along with additional information like the hardware descriptor.

Based on the patch by Mattias Nissler.
Mattias also has some tools that will make the dumped frames available to wireshark: http://www-user.rhrk.uni-kl.de/~nissler/rt2x00/

---
 drivers/net/wireless/rt2x00/rt2x00.h      |    8 +-
 drivers/net/wireless/rt2x00/rt2x00debug.c |  182 ++++++++++++++++++++++++++++-
 drivers/net/wireless/rt2x00/rt2x00dev.c   |   20 +++-
 drivers/net/wireless/rt2x00/rt2x00lib.h   |    6 +
 drivers/net/wireless/rt2x00/rt2x00pci.c   |    4 +-
 drivers/net/wireless/rt2x00/rt2x00usb.c   |    6 +-
 6 files changed, 216 insertions(+), 10 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +7 -1
index 31e48c2..ba874cf 100644
@@ -623,7 +623,7 @@ struct rt2x00_dev {
 	 * required for deregistration of debugfs.
 	 */
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-	const struct rt2x00debug_intf *debugfs_intf;
+	struct rt2x00debug_intf *debugfs_intf;
 #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
 
 	/*
@@ -791,6 +791,12 @@ struct rt2x00_dev {
 	ring_loop(__entry, (__dev)->tx, ring_end(__dev))
 
 /*
+ * Compute an array index from a pointer to an element and the base pointer.
+ */
+#define ARRAY_INDEX(__elem, __base) \
+	( ((char *)(__elem) - (char *)(__base)) / sizeof(*(__elem)) )
+
+/*
  * Generic RF access.
  * The RF is being accessed by word index.
  */
drivers/net/wireless/rt2x00/rt2x00debug.c +181 -1

232 lines not on this page · raw message

drivers/net/wireless/rt2x00/rt2x00dev.c +17 -3
index 4f32ee8..48e2515 100644
@@ -28,6 +28,7 @@
 
 #include "rt2x00.h"
 #include "rt2x00lib.h"
+#include "rt2x00dump.h"
 
 /*
  * Ring handler.
@@ -511,9 +512,11 @@ void rt2x00lib_txdone(struct data_entry *entry,
 	}
 
 	/*
-	 * Send the tx_status to mac80211,
-	 * that method also cleans up the skb structure.
+	 * Send the tx_status to mac80211 & debugfs.
+	 * mac80211 will clean up the skb structure.
 	 */
+	get_skb_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE;
+	rt2x00debug_dump_frame(rt2x00dev, entry->skb);
 	ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status);
 	entry->skb = NULL;
 }
@@ -563,8 +566,10 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
 	rx_status->antenna = rt2x00dev->link.ant.active.rx;
 
 	/*
-	 * Send frame to mac80211
+	 * Send frame to mac80211 & debugfs
 	 */
+	get_skb_desc(skb)->frame_type = DUMP_FRAME_RXDONE;
+	rt2x00debug_dump_frame(rt2x00dev, skb);
 	ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
@@ -715,6 +720,15 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	 */
 	skbdesc->entry->skb = skb;
 	memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control));
+
+	/*
+	 * The frame has been completely initialized and ready
+	 * for sending to the device. The caller will push the
+	 * frame to the device, but we are going to push the
+	 * frame to debugfs here.
+	 */
+	skbdesc->frame_type = DUMP_FRAME_TX;
+	rt2x00debug_dump_frame(rt2x00dev, skb);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc);
 
drivers/net/wireless/rt2x00/rt2x00lib.h +6 -0
index 7319411..0bf10ff 100644
@@ -80,6 +80,7 @@ static inline void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
 void rt2x00debug_register(struct rt2x00_dev *rt2x00dev);
 void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
+void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
 #else
 static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 {
@@ -88,6 +89,11 @@ static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
 {
 }
+
+static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
+					  struct skb_buff *skb)
+{
+}
 #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
 
 /*
drivers/net/wireless/rt2x00/rt2x00pci.c +2 -2
index 9b11c6d..abeffdb 100644
@@ -166,8 +166,8 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
 		 * Fill in skb descriptor
 		 */
 		skbdesc = get_skb_desc(skb);
-		skbdesc->desc_len = desc.size;
-		skbdesc->data_len = entry->ring->desc_size;
+		skbdesc->desc_len = entry->ring->desc_size;
+		skbdesc->data_len = skb->len;
 		skbdesc->desc = entry->priv;
 		skbdesc->data = skb->data;
 		skbdesc->ring = ring;
drivers/net/wireless/rt2x00/rt2x00usb.c +3 -3
index f1282c6..82e95b9 100644
@@ -287,9 +287,9 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
 	 * Fill in skb descriptor
 	 */
 	skbdesc = get_skb_desc(entry->skb);
-	skbdesc->desc_len = desc.size;
-	skbdesc->data_len = entry->ring->desc_size;
-	skbdesc->desc = entry->skb->data + desc.size;
+	skbdesc->desc_len = entry->ring->desc_size;
+	skbdesc->data_len = entry->skb->len;
+	skbdesc->desc = entry->skb->data - skbdesc->desc_len;
 	skbdesc->data = entry->skb->data;
 	skbdesc->ring = ring;
 	skbdesc->entry = entry;
Signature · 1 line
1.5.3.6
#8 lore raw

Re: [Rt2400-devel] [PATCH 06/11] rt2x00: Add TX/RX frame dumping facility

Hi,

John, you don't want to pull this (yet), as it introduces a compile failure.

Ivo, you've missed the new rt2x00dump.h file in the patch. I didn't want it in the first place :-P

Mattias

Quoted 399 lines · Ivo van Doorn

This adds TX/RX frame dumping capabilities through debugfs. The intention is that with this approach debugging of rt2x00 is simplified since _all_ frames going in and out of the device are send to debugfs as well along with additional information like the hardware descriptor.

Based on the patch by Mattias Nissler.
Mattias also has some tools that will make the dumped frames available to wireshark: http://www-user.rhrk.uni-kl.de/~nissler/rt2x00/

---
 drivers/net/wireless/rt2x00/rt2x00.h      |    8 +-
 drivers/net/wireless/rt2x00/rt2x00debug.c |  182 ++++++++++++++++++++++++++++-
 drivers/net/wireless/rt2x00/rt2x00dev.c   |   20 +++-
 drivers/net/wireless/rt2x00/rt2x00lib.h   |    6 +
 drivers/net/wireless/rt2x00/rt2x00pci.c   |    4 +-
 drivers/net/wireless/rt2x00/rt2x00usb.c   |    6 +-
 6 files changed, 216 insertions(+), 10 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +7 -1
index 31e48c2..ba874cf 100644
@@ -623,7 +623,7 @@ struct rt2x00_dev {
 	 * required for deregistration of debugfs.
 	 */
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-	const struct rt2x00debug_intf *debugfs_intf;
+	struct rt2x00debug_intf *debugfs_intf;
 #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
 
 	/*
@@ -791,6 +791,12 @@ struct rt2x00_dev {
 	ring_loop(__entry, (__dev)->tx, ring_end(__dev))
 
 /*
+ * Compute an array index from a pointer to an element and the base pointer.
+ */
+#define ARRAY_INDEX(__elem, __base) \
+	( ((char *)(__elem) - (char *)(__base)) / sizeof(*(__elem)) )
+
+/*
  * Generic RF access.
  * The RF is being accessed by word index.
  */
drivers/net/wireless/rt2x00/rt2x00debug.c +181 -1
index 3aa7e0a..e72c981 100644
@@ -26,10 +26,12 @@
 #include <linux/debugfs.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/poll.h>
 #include <linux/uaccess.h>
 
 #include "rt2x00.h"
 #include "rt2x00lib.h"
+#include "rt2x00dump.h"
 
 #define PRINT_LINE_LEN_MAX 32
 
@@ -58,6 +60,8 @@ struct rt2x00debug_intf {
 	 *     - eeprom offset/value files
 	 *     - bbp offset/value files
 	 *     - rf offset/value files
+	 *   - frame dump folder
+	 *     - frame dump file
 	 */
 	struct dentry *driver_folder;
 	struct dentry *driver_entry;
@@ -72,6 +76,24 @@ struct rt2x00debug_intf {
 	struct dentry *bbp_val_entry;
 	struct dentry *rf_off_entry;
 	struct dentry *rf_val_entry;
+	struct dentry *frame_folder;
+	struct dentry *frame_dump_entry;
+
+	/*
+	 * The frame dump file only allows a single reader,
+	 * so we need to store the current state here.
+	 */
+	unsigned long frame_dump_flags;
+#define FRAME_DUMP_FILE_OPEN	1
+
+	/*
+	 * We queue each frame before dumping it to the user,
+	 * per read command we will pass a single skb structure
+	 * so we should be prepared to queue multiple sk buffers
+	 * before sending it to userspace.
+	 */
+	struct sk_buff_head frame_dump_skbqueue;
+	wait_queue_head_t frame_dump_waitqueue;
 
 	/*
 	 * Driver and chipset files will use a data buffer
@@ -90,6 +112,63 @@ struct rt2x00debug_intf {
 	unsigned int offset_rf;
 };
 
+void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
+			    struct sk_buff *skb)
+{
+	struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
+	struct skb_desc *desc = get_skb_desc(skb);
+	struct sk_buff *skbcopy;
+	struct rt2x00dump_hdr *dump_hdr;
+	struct timeval timestamp;
+	unsigned int ring_index;
+	unsigned int entry_index;
+
+	do_gettimeofday(&timestamp);
+	ring_index = ARRAY_INDEX(desc->ring, rt2x00dev->rx);
+	entry_index = ARRAY_INDEX(desc->entry, desc->ring->entry);
+
+	if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
+		return;
+
+	if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
+		DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n");
+		return;
+	}
+
+	skbcopy = alloc_skb(sizeof(*dump_hdr) + desc->desc_len + desc->data_len,
+			    GFP_ATOMIC);
+	if (!skbcopy) {
+		DEBUG(rt2x00dev, "Failed to copy skb for dump.\n");
+		return;
+	}
+
+	dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr));
+	dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION);
+	dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr));
+	dump_hdr->desc_length = cpu_to_le32(desc->desc_len);
+	dump_hdr->data_length = cpu_to_le32(desc->data_len);
+	dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt);
+	dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
+	dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev);
+	dump_hdr->type = cpu_to_le16(desc->frame_type);
+	dump_hdr->ring_index = ring_index;
+	dump_hdr->entry_index = entry_index;
+	dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
+	dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
+
+	memcpy(skb_put(skbcopy, desc->desc_len), desc->desc, desc->desc_len);
+	memcpy(skb_put(skbcopy, desc->data_len), desc->data, desc->data_len);
+
+	skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy);
+	wake_up_interruptible(&intf->frame_dump_waitqueue);
+
+	/*
+	 * Verify that the file has not been closed while we were working.
+	 */
+	if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
+		skb_queue_purge(&intf->frame_dump_skbqueue);
+}
+
 static int rt2x00debug_file_open(struct inode *inode, struct file *file)
 {
 	struct rt2x00debug_intf *intf = inode->i_private;
@@ -111,6 +190,89 @@ static int rt2x00debug_file_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
+static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file)
+{
+	struct rt2x00debug_intf *intf = inode->i_private;
+	int retval;
+
+	retval = rt2x00debug_file_open(inode, file);
+	if (retval)
+		return retval;
+
+	if (test_and_set_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) {
+		rt2x00debug_file_release(inode, file);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file)
+{
+	struct rt2x00debug_intf *intf = inode->i_private;
+
+	skb_queue_purge(&intf->frame_dump_skbqueue);
+
+	clear_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags);
+
+	return rt2x00debug_file_release(inode, file);
+}
+
+static ssize_t rt2x00debug_read_ring_dump(struct file *file,
+					  char __user *buf,
+					  size_t length,
+					  loff_t *offset)
+{
+	struct rt2x00debug_intf *intf = file->private_data;
+	struct sk_buff *skb;
+	size_t status;
+	int retval;
+
+	if (file->f_flags & O_NONBLOCK)
+		return -EAGAIN;
+
+	retval =
+	    wait_event_interruptible(intf->frame_dump_waitqueue,
+				     (skb =
+				     skb_dequeue(&intf->frame_dump_skbqueue)));
+	if (retval)
+		return retval;
+
+	status = min((size_t)skb->len, length);
+	if (copy_to_user(buf, skb->data, status)) {
+		status = -EFAULT;
+		goto exit;
+	}
+
+	*offset += status;
+
+exit:
+	kfree_skb(skb);
+
+	return status;
+}
+
+static unsigned int rt2x00debug_poll_ring_dump(struct file *file,
+					       poll_table *wait)
+{
+	struct rt2x00debug_intf *intf = file->private_data;
+
+	poll_wait(file, &intf->frame_dump_waitqueue, wait);
+
+	if (!skb_queue_empty(&intf->frame_dump_skbqueue))
+		return POLLOUT | POLLWRNORM;
+
+	return 0;
+}
+
+static const struct file_operations rt2x00debug_fop_ring_dump = {
+	.owner		= THIS_MODULE,
+	.read		= rt2x00debug_read_ring_dump,
+	.poll		= rt2x00debug_poll_ring_dump,
+	.open		= rt2x00debug_open_ring_dump,
+	.release	= rt2x00debug_release_ring_dump,
+};
+
 #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type)	\
 static ssize_t rt2x00debug_read_##__name(struct file *file,	\
 					 char __user *buf,	\
@@ -339,6 +501,20 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 
 #undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
 
+	intf->frame_folder =
+	    debugfs_create_dir("frame", intf->driver_folder);
+	if (IS_ERR(intf->frame_folder))
+		goto exit;
+
+	intf->frame_dump_entry =
+	    debugfs_create_file("dump", S_IRUGO, intf->frame_folder,
+				intf, &rt2x00debug_fop_ring_dump);
+	if (IS_ERR(intf->frame_dump_entry))
+		goto exit;
+
+	skb_queue_head_init(&intf->frame_dump_skbqueue);
+	init_waitqueue_head(&intf->frame_dump_waitqueue);
+
 	return;
 
 exit:
@@ -350,11 +526,15 @@ exit:
 
 void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
 {
-	const struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
+	struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
 
 	if (unlikely(!intf))
 		return;
 
+	skb_queue_purge(&intf->frame_dump_skbqueue);
+
+	debugfs_remove(intf->frame_dump_entry);
+	debugfs_remove(intf->frame_folder);
 	debugfs_remove(intf->rf_val_entry);
 	debugfs_remove(intf->rf_off_entry);
 	debugfs_remove(intf->bbp_val_entry);
drivers/net/wireless/rt2x00/rt2x00dev.c +17 -3
index 4f32ee8..48e2515 100644
@@ -28,6 +28,7 @@
 
 #include "rt2x00.h"
 #include "rt2x00lib.h"
+#include "rt2x00dump.h"
 
 /*
  * Ring handler.
@@ -511,9 +512,11 @@ void rt2x00lib_txdone(struct data_entry *entry,
 	}
 
 	/*
-	 * Send the tx_status to mac80211,
-	 * that method also cleans up the skb structure.
+	 * Send the tx_status to mac80211 & debugfs.
+	 * mac80211 will clean up the skb structure.
 	 */
+	get_skb_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE;
+	rt2x00debug_dump_frame(rt2x00dev, entry->skb);
 	ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status);
 	entry->skb = NULL;
 }
@@ -563,8 +566,10 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
 	rx_status->antenna = rt2x00dev->link.ant.active.rx;
 
 	/*
-	 * Send frame to mac80211
+	 * Send frame to mac80211 & debugfs
 	 */
+	get_skb_desc(skb)->frame_type = DUMP_FRAME_RXDONE;
+	rt2x00debug_dump_frame(rt2x00dev, skb);
 	ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
@@ -715,6 +720,15 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	 */
 	skbdesc->entry->skb = skb;
 	memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control));
+
+	/*
+	 * The frame has been completely initialized and ready
+	 * for sending to the device. The caller will push the
+	 * frame to the device, but we are going to push the
+	 * frame to debugfs here.
+	 */
+	skbdesc->frame_type = DUMP_FRAME_TX;
+	rt2x00debug_dump_frame(rt2x00dev, skb);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc);
 
drivers/net/wireless/rt2x00/rt2x00lib.h +6 -0
index 7319411..0bf10ff 100644
@@ -80,6 +80,7 @@ static inline void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
 void rt2x00debug_register(struct rt2x00_dev *rt2x00dev);
 void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
+void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
 #else
 static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 {
@@ -88,6 +89,11 @@ static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
 {
 }
+
+static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
+					  struct skb_buff *skb)
+{
+}
 #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
 
 /*
drivers/net/wireless/rt2x00/rt2x00pci.c +2 -2
index 9b11c6d..abeffdb 100644
@@ -166,8 +166,8 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
 		 * Fill in skb descriptor
 		 */
 		skbdesc = get_skb_desc(skb);
-		skbdesc->desc_len = desc.size;
-		skbdesc->data_len = entry->ring->desc_size;
+		skbdesc->desc_len = entry->ring->desc_size;
+		skbdesc->data_len = skb->len;
 		skbdesc->desc = entry->priv;
 		skbdesc->data = skb->data;
 		skbdesc->ring = ring;
drivers/net/wireless/rt2x00/rt2x00usb.c +3 -3
index f1282c6..82e95b9 100644
@@ -287,9 +287,9 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
 	 * Fill in skb descriptor
 	 */
 	skbdesc = get_skb_desc(entry->skb);
-	skbdesc->desc_len = desc.size;
-	skbdesc->data_len = entry->ring->desc_size;
-	skbdesc->desc = entry->skb->data + desc.size;
+	skbdesc->desc_len = entry->ring->desc_size;
+	skbdesc->data_len = entry->skb->len;
+	skbdesc->desc = entry->skb->data - skbdesc->desc_len;
 	skbdesc->data = entry->skb->data;
 	skbdesc->ring = ring;
 	skbdesc->entry = entry;
#9 lore raw

Re: [Rt2400-devel] [PATCH 06/11] rt2x00: Add TX/RX frame dumping facility

Hi,

Quoted 5 lines

John, you don't want to pull this (yet), as it introduces a compile failure.

Ivo, you've missed the new rt2x00dump.h file in the patch. I didn't want it in the first place :-P

Oops. Sorry about that. I have committed the fix as a seperate patch to rt2x00.git. The patch mail itself will follow in a few minutes.

Thanks.

Ivo

Quoted 404 lines

Mattias

Quoted 399 lines · Ivo van Doorn

This adds TX/RX frame dumping capabilities through debugfs. The intention is that with this approach debugging of rt2x00 is simplified since _all_ frames going in and out of the device are send to debugfs as well along with additional information like the hardware descriptor.

Based on the patch by Mattias Nissler.
Mattias also has some tools that will make the dumped frames available to wireshark: http://www-user.rhrk.uni-kl.de/~nissler/rt2x00/

---
 drivers/net/wireless/rt2x00/rt2x00.h      |    8 +-
 drivers/net/wireless/rt2x00/rt2x00debug.c |  182 ++++++++++++++++++++++++++++-
 drivers/net/wireless/rt2x00/rt2x00dev.c   |   20 +++-
 drivers/net/wireless/rt2x00/rt2x00lib.h   |    6 +
 drivers/net/wireless/rt2x00/rt2x00pci.c   |    4 +-
 drivers/net/wireless/rt2x00/rt2x00usb.c   |    6 +-
 6 files changed, 216 insertions(+), 10 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +7 -1
index 31e48c2..ba874cf 100644
@@ -623,7 +623,7 @@ struct rt2x00_dev {
 	 * required for deregistration of debugfs.
 	 */
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-	const struct rt2x00debug_intf *debugfs_intf;
+	struct rt2x00debug_intf *debugfs_intf;
 #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
 
 	/*
@@ -791,6 +791,12 @@ struct rt2x00_dev {
 	ring_loop(__entry, (__dev)->tx, ring_end(__dev))
 
 /*
+ * Compute an array index from a pointer to an element and the base pointer.
+ */
+#define ARRAY_INDEX(__elem, __base) \
+	( ((char *)(__elem) - (char *)(__base)) / sizeof(*(__elem)) )
+
+/*
  * Generic RF access.
  * The RF is being accessed by word index.
  */
drivers/net/wireless/rt2x00/rt2x00debug.c +181 -1
index 3aa7e0a..e72c981 100644
@@ -26,10 +26,12 @@
 #include <linux/debugfs.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/poll.h>
 #include <linux/uaccess.h>
 
 #include "rt2x00.h"
 #include "rt2x00lib.h"
+#include "rt2x00dump.h"
 
 #define PRINT_LINE_LEN_MAX 32
 
@@ -58,6 +60,8 @@ struct rt2x00debug_intf {
 	 *     - eeprom offset/value files
 	 *     - bbp offset/value files
 	 *     - rf offset/value files
+	 *   - frame dump folder
+	 *     - frame dump file
 	 */
 	struct dentry *driver_folder;
 	struct dentry *driver_entry;
@@ -72,6 +76,24 @@ struct rt2x00debug_intf {
 	struct dentry *bbp_val_entry;
 	struct dentry *rf_off_entry;
 	struct dentry *rf_val_entry;
+	struct dentry *frame_folder;
+	struct dentry *frame_dump_entry;
+
+	/*
+	 * The frame dump file only allows a single reader,
+	 * so we need to store the current state here.
+	 */
+	unsigned long frame_dump_flags;
+#define FRAME_DUMP_FILE_OPEN	1
+
+	/*
+	 * We queue each frame before dumping it to the user,
+	 * per read command we will pass a single skb structure
+	 * so we should be prepared to queue multiple sk buffers
+	 * before sending it to userspace.
+	 */
+	struct sk_buff_head frame_dump_skbqueue;
+	wait_queue_head_t frame_dump_waitqueue;
 
 	/*
 	 * Driver and chipset files will use a data buffer
@@ -90,6 +112,63 @@ struct rt2x00debug_intf {
 	unsigned int offset_rf;
 };
 
+void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
+			    struct sk_buff *skb)
+{
+	struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
+	struct skb_desc *desc = get_skb_desc(skb);
+	struct sk_buff *skbcopy;
+	struct rt2x00dump_hdr *dump_hdr;
+	struct timeval timestamp;
+	unsigned int ring_index;
+	unsigned int entry_index;
+
+	do_gettimeofday(&timestamp);
+	ring_index = ARRAY_INDEX(desc->ring, rt2x00dev->rx);
+	entry_index = ARRAY_INDEX(desc->entry, desc->ring->entry);
+
+	if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
+		return;
+
+	if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
+		DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n");
+		return;
+	}
+
+	skbcopy = alloc_skb(sizeof(*dump_hdr) + desc->desc_len + desc->data_len,
+			    GFP_ATOMIC);
+	if (!skbcopy) {
+		DEBUG(rt2x00dev, "Failed to copy skb for dump.\n");
+		return;
+	}
+
+	dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr));
+	dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION);
+	dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr));
+	dump_hdr->desc_length = cpu_to_le32(desc->desc_len);
+	dump_hdr->data_length = cpu_to_le32(desc->data_len);
+	dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt);
+	dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
+	dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev);
+	dump_hdr->type = cpu_to_le16(desc->frame_type);
+	dump_hdr->ring_index = ring_index;
+	dump_hdr->entry_index = entry_index;
+	dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
+	dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
+
+	memcpy(skb_put(skbcopy, desc->desc_len), desc->desc, desc->desc_len);
+	memcpy(skb_put(skbcopy, desc->data_len), desc->data, desc->data_len);
+
+	skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy);
+	wake_up_interruptible(&intf->frame_dump_waitqueue);
+
+	/*
+	 * Verify that the file has not been closed while we were working.
+	 */
+	if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
+		skb_queue_purge(&intf->frame_dump_skbqueue);
+}
+
 static int rt2x00debug_file_open(struct inode *inode, struct file *file)
 {
 	struct rt2x00debug_intf *intf = inode->i_private;
@@ -111,6 +190,89 @@ static int rt2x00debug_file_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
+static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file)
+{
+	struct rt2x00debug_intf *intf = inode->i_private;
+	int retval;
+
+	retval = rt2x00debug_file_open(inode, file);
+	if (retval)
+		return retval;
+
+	if (test_and_set_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) {
+		rt2x00debug_file_release(inode, file);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file)
+{
+	struct rt2x00debug_intf *intf = inode->i_private;
+
+	skb_queue_purge(&intf->frame_dump_skbqueue);
+
+	clear_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags);
+
+	return rt2x00debug_file_release(inode, file);
+}
+
+static ssize_t rt2x00debug_read_ring_dump(struct file *file,
+					  char __user *buf,
+					  size_t length,
+					  loff_t *offset)
+{
+	struct rt2x00debug_intf *intf = file->private_data;
+	struct sk_buff *skb;
+	size_t status;
+	int retval;
+
+	if (file->f_flags & O_NONBLOCK)
+		return -EAGAIN;
+
+	retval =
+	    wait_event_interruptible(intf->frame_dump_waitqueue,
+				     (skb =
+				     skb_dequeue(&intf->frame_dump_skbqueue)));
+	if (retval)
+		return retval;
+
+	status = min((size_t)skb->len, length);
+	if (copy_to_user(buf, skb->data, status)) {
+		status = -EFAULT;
+		goto exit;
+	}
+
+	*offset += status;
+
+exit:
+	kfree_skb(skb);
+
+	return status;
+}
+
+static unsigned int rt2x00debug_poll_ring_dump(struct file *file,
+					       poll_table *wait)
+{
+	struct rt2x00debug_intf *intf = file->private_data;
+
+	poll_wait(file, &intf->frame_dump_waitqueue, wait);
+
+	if (!skb_queue_empty(&intf->frame_dump_skbqueue))
+		return POLLOUT | POLLWRNORM;
+
+	return 0;
+}
+
+static const struct file_operations rt2x00debug_fop_ring_dump = {
+	.owner		= THIS_MODULE,
+	.read		= rt2x00debug_read_ring_dump,
+	.poll		= rt2x00debug_poll_ring_dump,
+	.open		= rt2x00debug_open_ring_dump,
+	.release	= rt2x00debug_release_ring_dump,
+};
+
 #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type)	\
 static ssize_t rt2x00debug_read_##__name(struct file *file,	\
 					 char __user *buf,	\
@@ -339,6 +501,20 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 
 #undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
 
+	intf->frame_folder =
+	    debugfs_create_dir("frame", intf->driver_folder);
+	if (IS_ERR(intf->frame_folder))
+		goto exit;
+
+	intf->frame_dump_entry =
+	    debugfs_create_file("dump", S_IRUGO, intf->frame_folder,
+				intf, &rt2x00debug_fop_ring_dump);
+	if (IS_ERR(intf->frame_dump_entry))
+		goto exit;
+
+	skb_queue_head_init(&intf->frame_dump_skbqueue);
+	init_waitqueue_head(&intf->frame_dump_waitqueue);
+
 	return;
 
 exit:
@@ -350,11 +526,15 @@ exit:
 
 void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
 {
-	const struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
+	struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
 
 	if (unlikely(!intf))
 		return;
 
+	skb_queue_purge(&intf->frame_dump_skbqueue);
+
+	debugfs_remove(intf->frame_dump_entry);
+	debugfs_remove(intf->frame_folder);
 	debugfs_remove(intf->rf_val_entry);
 	debugfs_remove(intf->rf_off_entry);
 	debugfs_remove(intf->bbp_val_entry);
drivers/net/wireless/rt2x00/rt2x00dev.c +17 -3
index 4f32ee8..48e2515 100644
@@ -28,6 +28,7 @@
 
 #include "rt2x00.h"
 #include "rt2x00lib.h"
+#include "rt2x00dump.h"
 
 /*
  * Ring handler.
@@ -511,9 +512,11 @@ void rt2x00lib_txdone(struct data_entry *entry,
 	}
 
 	/*
-	 * Send the tx_status to mac80211,
-	 * that method also cleans up the skb structure.
+	 * Send the tx_status to mac80211 & debugfs.
+	 * mac80211 will clean up the skb structure.
 	 */
+	get_skb_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE;
+	rt2x00debug_dump_frame(rt2x00dev, entry->skb);
 	ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status);
 	entry->skb = NULL;
 }
@@ -563,8 +566,10 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
 	rx_status->antenna = rt2x00dev->link.ant.active.rx;
 
 	/*
-	 * Send frame to mac80211
+	 * Send frame to mac80211 & debugfs
 	 */
+	get_skb_desc(skb)->frame_type = DUMP_FRAME_RXDONE;
+	rt2x00debug_dump_frame(rt2x00dev, skb);
 	ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
@@ -715,6 +720,15 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	 */
 	skbdesc->entry->skb = skb;
 	memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control));
+
+	/*
+	 * The frame has been completely initialized and ready
+	 * for sending to the device. The caller will push the
+	 * frame to the device, but we are going to push the
+	 * frame to debugfs here.
+	 */
+	skbdesc->frame_type = DUMP_FRAME_TX;
+	rt2x00debug_dump_frame(rt2x00dev, skb);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc);
 
drivers/net/wireless/rt2x00/rt2x00lib.h +6 -0
index 7319411..0bf10ff 100644
@@ -80,6 +80,7 @@ static inline void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
 void rt2x00debug_register(struct rt2x00_dev *rt2x00dev);
 void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
+void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
 #else
 static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 {
@@ -88,6 +89,11 @@ static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
 {
 }
+
+static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
+					  struct skb_buff *skb)
+{
+}
 #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
 
 /*
drivers/net/wireless/rt2x00/rt2x00pci.c +2 -2
index 9b11c6d..abeffdb 100644
@@ -166,8 +166,8 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
 		 * Fill in skb descriptor
 		 */
 		skbdesc = get_skb_desc(skb);
-		skbdesc->desc_len = desc.size;
-		skbdesc->data_len = entry->ring->desc_size;
+		skbdesc->desc_len = entry->ring->desc_size;
+		skbdesc->data_len = skb->len;
 		skbdesc->desc = entry->priv;
 		skbdesc->data = skb->data;
 		skbdesc->ring = ring;
drivers/net/wireless/rt2x00/rt2x00usb.c +3 -3
index f1282c6..82e95b9 100644
@@ -287,9 +287,9 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
 	 * Fill in skb descriptor
 	 */
 	skbdesc = get_skb_desc(entry->skb);
-	skbdesc->desc_len = desc.size;
-	skbdesc->data_len = entry->ring->desc_size;
-	skbdesc->desc = entry->skb->data + desc.size;
+	skbdesc->desc_len = entry->ring->desc_size;
+	skbdesc->data_len = entry->skb->len;
+	skbdesc->desc = entry->skb->data - skbdesc->desc_len;
 	skbdesc->data = entry->skb->data;
 	skbdesc->ring = ring;
 	skbdesc->entry = entry;
#14 lore raw
In reply to Ivo van Doorn
Quoted 6 lines · Ivo van Doorn
Quoted 1 line

Please merge the patches for 2.6.24

Sorry that should be:
08 - Only update rssi average approximation on receiving beacon frames. 09 - Remove redundant code in rfkill setup
10 - Cleanup rfkill

Actually it looks to me like 9 and 10 apply to code that isn't in 2.6.24. 8 looks like it is close, but it doesn't quite apply either. I'll try to massage it in -- hopefully Jeff won't mind the extra trouble when rebasing...

John

Signature · 2 lines
John W. Linville
[email protected]
#15 lore raw
Quoted 9 lines · John W. Linville
Quoted 6 lines · Ivo van Doorn
Quoted 1 line

Please merge the patches for 2.6.24

Sorry that should be:
08 - Only update rssi average approximation on receiving beacon frames. 09 - Remove redundant code in rfkill setup
10 - Cleanup rfkill

Quoted 4 lines

Actually it looks to me like 9 and 10 apply to code that isn't in 2.6.24. 8 looks like it is close, but it doesn't quite apply either. I'll try to massage it in -- hopefully Jeff won't mind the extra trouble when rebasing...

9 and 10 should apply cleanly since the rfkill code hasn't changed for quite some time now. In fact I believe it hasn't changed since the initial merge to 2.6.24-rc.
Anyway, I'll try to create a patch for the upstream-jgarzik branch this weekend, that would safe you and jeff some work. :)

Ivo