2007-11-27 19:39:37

by Ivo Van Doorn

[permalink] [raw]
Subject: Please pull 'upstream' branch of rt2x00

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(-)


2007-11-27 22:21:12

by Mattias Nissler

[permalink] [raw]
Subject: 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

On Tue, 2007-11-27 at 21:49 +0100, Ivo van Doorn wrote:
> 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/
>
> Signed-off-by: Ivo van Doorn <[email protected]>
> ---
> 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(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
> index 31e48c2..ba874cf 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00.h
> +++ b/drivers/net/wireless/rt2x00/rt2x00.h
> @@ -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.
> */
> diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
> index 3aa7e0a..e72c981 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00debug.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
> @@ -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);
> diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
> index 4f32ee8..48e2515 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
> @@ -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);
>
> diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
> index 7319411..0bf10ff 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00lib.h
> +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
> @@ -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 */
>
> /*
> diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
> index 9b11c6d..abeffdb 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
> @@ -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;
> diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
> index f1282c6..82e95b9 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00usb.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
> @@ -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;


2007-11-27 19:39:41

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 02/11] rt2x00: Extend PLCP descriptor definition for rt2400pci

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.

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 40 +++++++++---------------------
drivers/net/wireless/rt2x00/rt2400pci.h | 20 +++++++++++----
2 files changed, 27 insertions(+), 33 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 6d3cdaf..c9a234f 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -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);
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h
index f5dbde7..369aac6 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.h
+++ b/drivers/net/wireless/rt2x00/rt2400pci.h
@@ -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
--
1.5.3.6


2007-11-27 19:41:58

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 08/11] rt2x00: Use IEEE80211_IF_TYPE_INVALID directly

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.

Signed-off-by: Mattias Nissler <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00.h | 7 +++++++
drivers/net/wireless/rt2x00/rt2x00dev.c | 19 ++++++++++++++++++-
2 files changed, 25 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 103a122..218068b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -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.
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index bd7b738..a771a09 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -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;
--
1.5.3.6


2007-11-29 22:28:27

by John W. Linville

[permalink] [raw]
Subject: Re: Please pull 'upstream' branch of rt2x00

On Tue, Nov 27, 2007 at 09:54:29PM +0100, Ivo van Doorn wrote:

> > 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
--
John W. Linville
[email protected]

2007-11-27 19:39:39

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 01/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.

Signed-off-by: Ivo van Doorn <[email protected]>
---
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(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index bdf3edc..6d3cdaf 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -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),
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index b6bb964..a623454 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -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),
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 5bfbac4..f56f3ef 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -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,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 84b0fc9..b2283ce 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -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...) \
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 9f0733b..72cfe00 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -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>

diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 9275d6f..6dc9a25 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -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>
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 3ab1fb9..e894978 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -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>

diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c
index 236025f..0a475e4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c
+++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c
@@ -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>
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 85ea8a8..e216c34 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -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>

diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 30ef4f9..e654568 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -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>
diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
index 16d365d..bbbf51d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c
+++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
@@ -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>
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 936e554..152058f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -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>
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index c2b4509..924f415 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -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),
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 4d1227a..49180de 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -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,
--
1.5.3.6


2007-11-27 19:54:44

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 06/11] rt2x00: Add TX/RX frame dumping facility

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/

Signed-off-by: Ivo van Doorn <[email protected]>
---
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(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 31e48c2..ba874cf 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -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.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 3aa7e0a..e72c981 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -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);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 4f32ee8..48e2515 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -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);

diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 7319411..0bf10ff 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -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 */

/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 9b11c6d..abeffdb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -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;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index f1282c6..82e95b9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -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;
--
1.5.3.6


2007-11-27 19:39:57

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH] rt2x00: Only update rssi average approximation on receiving beacon frames.

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.

Signed-off-by: Mattias Nissler <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00.h | 7 +++++++
drivers/net/wireless/rt2x00/rt2x00dev.c | 19 ++++++++++++++++++-
2 files changed, 25 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 103a122..218068b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -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.
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index bd7b738..a771a09 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -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;
--
1.5.3.6


2007-11-27 19:42:04

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 11/11] rt2x00: Release rt2x00 2.0.13

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 218068b..85cfdab 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -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"

/*
--
1.5.3.6


2007-11-27 19:39:44

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 03/11] rt2x00: Move register value/offset files into new folder

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

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00debug.c | 42 +++++++++++++++++-----------
1 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 6dc9a25..92efc5a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -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);
--
1.5.3.6


2007-11-27 19:39:46

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 04/11] rt2x00: Add chipset version to chipset debugfs entry

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

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00debug.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 92efc5a..3aa7e0a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -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);
}
--
1.5.3.6


2007-11-27 19:42:00

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 09/11] rt2x00: Remove redundant code in rfkill setup

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.

Signed-off-by: Larry Finger <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00rfkill.c | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
index bbbf51d..7439637 100644
--- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c
+++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
@@ -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;
--
1.5.3.6


2007-11-28 19:04:32

by Ivo Van Doorn

[permalink] [raw]
Subject: 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

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

> Mattias
>
> On Tue, 2007-11-27 at 21:49 +0100, Ivo van Doorn wrote:
> > 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/
> >
> > Signed-off-by: Ivo van Doorn <[email protected]>
> > ---
> > 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(-)
> >
> > diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
> > index 31e48c2..ba874cf 100644
> > --- a/drivers/net/wireless/rt2x00/rt2x00.h
> > +++ b/drivers/net/wireless/rt2x00/rt2x00.h
> > @@ -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.
> > */
> > diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
> > index 3aa7e0a..e72c981 100644
> > --- a/drivers/net/wireless/rt2x00/rt2x00debug.c
> > +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
> > @@ -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);
> > diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
> > index 4f32ee8..48e2515 100644
> > --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
> > +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
> > @@ -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);
> >
> > diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
> > index 7319411..0bf10ff 100644
> > --- a/drivers/net/wireless/rt2x00/rt2x00lib.h
> > +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
> > @@ -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 */
> >
> > /*
> > diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
> > index 9b11c6d..abeffdb 100644
> > --- a/drivers/net/wireless/rt2x00/rt2x00pci.c
> > +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
> > @@ -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;
> > diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
> > index f1282c6..82e95b9 100644
> > --- a/drivers/net/wireless/rt2x00/rt2x00usb.c
> > +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
> > @@ -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;
>
>



2007-11-27 19:43:52

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: Please pull 'upstream' branch of rt2x00

Hi,

> 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

2007-11-27 19:39:53

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 07/11] rt2x00: Use IEEE80211_IF_TYPE_INVALID directly

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

Signed-off-by: Ivo van Doorn <[email protected]>
---
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(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index ba874cf..103a122 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -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.
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 48e2515..bd7b738 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -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.
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index e216c34..bae4442 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -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);

--
1.5.3.6


2007-11-30 08:30:56

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: Please pull 'upstream' branch of rt2x00

On Thursday 29 November 2007, John W. Linville wrote:
> On Tue, Nov 27, 2007 at 09:54:29PM +0100, Ivo van Doorn wrote:
>
> > > 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...

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

2007-11-27 19:52:20

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 05/11] rt2x00: Add skb descriptor

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().

Signed-off-by: Ivo van Doorn <[email protected]>
---
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(-)

diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index f56f3ef..2ba8eda 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -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
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index b2283ce..31e48c2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -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);

/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index e894978..4f32ee8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -573,36 +573,26 @@ EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
* 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)
{
struct txdata_entry_desc desc;
- struct data_ring *ring;
+ struct skb_desc *skbdesc = get_skb_desc(skb);
+ struct ieee80211_hdr *ieee80211hdr = skbdesc->data;
+ __le32 *txd = skbdesc->desc;
int tx_rate;
int bitrate;
+ int length;
int duration;
int residual;
u16 frame_control;
u16 seq_ctrl;

- /*
- * Make sure the descriptor is properly cleared.
- */
- memset(&desc, 0x00, sizeof(desc));
+ memset(&desc, 0, sizeof(desc));

- /*
- * Get ring pointer, if we fail to obtain the
- * correct ring, then use the first TX ring.
- */
- ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
- if (!ring)
- ring = rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
-
- desc.cw_min = ring->tx_params.cw_min;
- desc.cw_max = ring->tx_params.cw_max;
- desc.aifs = ring->tx_params.aifs;
+ desc.cw_min = skbdesc->ring->tx_params.cw_min;
+ desc.cw_max = skbdesc->ring->tx_params.cw_max;
+ desc.aifs = skbdesc->ring->tx_params.aifs;

/*
* Identify queue
@@ -683,17 +673,18 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
desc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
desc.service = 0x04;

+ length = skbdesc->data_len + FCS_LEN;
if (test_bit(ENTRY_TXD_OFDM_RATE, &desc.flags)) {
- desc.length_high = ((length + FCS_LEN) >> 6) & 0x3f;
- desc.length_low = ((length + FCS_LEN) & 0x3f);
+ desc.length_high = (length >> 6) & 0x3f;
+ desc.length_low = length & 0x3f;
} else {
bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE);

/*
* Convert length to microseconds.
*/
- residual = get_duration_res(length + FCS_LEN, bitrate);
- duration = get_duration(length + FCS_LEN, bitrate);
+ residual = get_duration_res(length, bitrate);
+ duration = get_duration(length, bitrate);

if (residual != 0) {
duration++;
@@ -716,8 +707,14 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
desc.signal |= 0x08;
}

- rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, txd, &desc,
- ieee80211hdr, length, control);
+ rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, txd, &desc, ieee80211hdr,
+ skbdesc->data_len, control);
+
+ /*
+ * Update ring entry.
+ */
+ skbdesc->entry->skb = skb;
+ memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control));
}
EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc);

diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index e654568..9b11c6d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -38,9 +38,9 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct data_ring *ring =
- rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
- struct data_entry *entry = rt2x00_get_data_entry(ring);
+ struct skb_desc *desc;
+ struct data_ring *ring;
+ struct data_entry *entry;

/*
* Just in case mac80211 doesn't set this correctly,
@@ -48,14 +48,22 @@ int rt2x00pci_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);

/*
- * Update the beacon entry.
+ * Fill in skb descriptor
*/
+ desc = get_skb_desc(skb);
+ desc->desc_len = ring->desc_size;
+ desc->data_len = skb->len;
+ desc->desc = entry->priv;
+ desc->data = skb->data;
+ desc->ring = ring;
+ desc->entry = entry;
+
memcpy(entry->data_addr, skb->data, skb->len);
- rt2x00lib_write_tx_desc(rt2x00dev, entry->priv,
- (struct ieee80211_hdr *)skb->data,
- skb->len, control);
+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);

/*
* Enable beacon generation.
@@ -73,9 +81,9 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
- struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
struct data_entry *entry = rt2x00_get_data_entry(ring);
__le32 *txd = entry->priv;
+ struct skb_desc *desc;
u32 word;

if (rt2x00_ring_full(ring)) {
@@ -95,11 +103,19 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
return -EINVAL;
}

- entry->skb = skb;
- memcpy(&entry->tx_status.control, control, sizeof(*control));
+ /*
+ * Fill in skb descriptor
+ */
+ desc = get_skb_desc(skb);
+ desc->desc_len = ring->desc_size;
+ desc->data_len = skb->len;
+ desc->desc = entry->priv;
+ desc->data = skb->data;
+ desc->ring = ring;
+ desc->entry = entry;
+
memcpy(entry->data_addr, skb->data, skb->len);
- rt2x00lib_write_tx_desc(rt2x00dev, txd, ieee80211hdr,
- skb->len, control);
+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);

rt2x00_ring_index_inc(ring);

@@ -118,6 +134,7 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
struct data_ring *ring = rt2x00dev->rx;
struct data_entry *entry;
struct sk_buff *skb;
+ struct skb_desc *skbdesc;
struct rxdata_entry_desc desc;
__le32 *rxd;
u32 word;
@@ -130,7 +147,7 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC))
break;

- memset(&desc, 0x00, sizeof(desc));
+ memset(&desc, 0, sizeof(desc));
rt2x00dev->ops->lib->fill_rxdone(entry, &desc);

/*
@@ -146,6 +163,17 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
memcpy(skb->data, entry->data_addr, desc.size);

/*
+ * Fill in skb descriptor
+ */
+ skbdesc = get_skb_desc(skb);
+ skbdesc->desc_len = desc.size;
+ skbdesc->data_len = entry->ring->desc_size;
+ skbdesc->desc = entry->priv;
+ skbdesc->data = skb->data;
+ skbdesc->ring = ring;
+ skbdesc->entry = entry;
+
+ /*
* Send the frame to rt2x00lib for further processing.
*/
rt2x00lib_rxdone(entry, skb, &desc);
diff --git a/drivers/net/wireless/rt2x00/rt2x00ring.h b/drivers/net/wireless/rt2x00/rt2x00ring.h
index 5b871ad..5b32f3e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00ring.h
+++ b/drivers/net/wireless/rt2x00/rt2x00ring.h
@@ -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.
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 152058f..f1282c6 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -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);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 924f415..13c8086 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -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,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 49180de..8093a4d 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -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,
--
1.5.3.6


2007-11-27 19:42:03

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 10/11] rt2x00: Cleanup rfkill

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.

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00rfkill.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
index 7439637..34a96d4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c
+++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
@@ -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);
}
--
1.5.3.6