2008-01-06 22:39:50

by Ivo Van Doorn

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

Hi John,

Here is the 2.0.14 release of rt2x00. Again lots of bugfixes,
and unfortunately we are still not there yet. I am afraid
rt2500usb and rt61pci are lost causes for the 2.6.24 release,
they are both broken, and I haven't figured out what is causing
this.

Next release will contain more interesting stuff, most of those
patches are already done, but due to testing and fine tuning I
have kept those patches back for this release. They primarily
cover basic support for virtual interfaces, led triggers, and some
first patches to make rt2x00lib support rt2800 (Yes, work on those
drivers has begun).

All indivual patches can also be found here:
http://kernel.org//pub/linux/kernel/people/ivd/rt2x00-2.0.14/

Ivo

---
The following changes since commit 2d0811f5ed506397d85792abfd8ef0983f4e8b7c:
John W. Linville (1):
fixup 'everything' after 'upstream-davem' rebase and patch modification

are available in the git repository at:

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

Ivo van Doorn (12):
rt2x00: Fix chipset debugfs file
rt2x00: Always call ieee80211_stop_queue() when return NETDEV_TX_BUSY
rt2x00: Only set the TBCN flag when the interface is configured to send beacons.
rt2x00: Store queue idx and entry idx in data_ring and data_entry
rt2x00: Move start() and stop() handlers into rt2x00lib.c
rt2x00: Put 802.11 data on 4 byte boundary
rt2x00: Move packet filter flags
rt2x00: Cleanup write_tx_desc() arguments
rt2x00: Determine MY_BSS from descriptor
rt2x00: Move init_txring and init_rxring into rt2x00lib
rt2x00: Correctly initialize data and desc pointer
rt2x00: Release rt2x00 2.0.14

drivers/net/wireless/rt2x00/rt2400pci.c | 102 +++++++--------------
drivers/net/wireless/rt2x00/rt2500pci.c | 88 ++++++------------
drivers/net/wireless/rt2x00/rt2500usb.c | 36 +++++---
drivers/net/wireless/rt2x00/rt2x00.h | 32 ++++---
drivers/net/wireless/rt2x00/rt2x00debug.c | 13 +--
drivers/net/wireless/rt2x00/rt2x00dev.c | 142 ++++++++++++++++++++++++-----
drivers/net/wireless/rt2x00/rt2x00lib.h | 4 +-
drivers/net/wireless/rt2x00/rt2x00mac.c | 59 +++---------
drivers/net/wireless/rt2x00/rt2x00pci.c | 28 ++++--
drivers/net/wireless/rt2x00/rt2x00ring.h | 13 +++
drivers/net/wireless/rt2x00/rt2x00usb.c | 87 ++++++++----------
drivers/net/wireless/rt2x00/rt2x00usb.h | 5 +-
drivers/net/wireless/rt2x00/rt61pci.c | 114 +++++++++---------------
drivers/net/wireless/rt2x00/rt73usb.c | 35 ++++---
14 files changed, 378 insertions(+), 380 deletions(-)


2008-01-06 22:42:47

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 05/12] rt2x00: Move start() and stop() handlers into rt2x00lib.c

suspend & resume was broken since it called rt2x00mac_start()
and rt2x00mac_stop() which would fail to execute because the
DEVICE_PRESENT flag was not set.

Move the start and stop handlers into rt2x00lib.c which are called
from rt2x00mac_start() and rt2x00mac_stop() after they have checked
the DEVICE_PRESENT flag, while suspend and resume handlers can
directly call those functions.

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00dev.c | 66 ++++++++++++++++++++++++++++--
drivers/net/wireless/rt2x00/rt2x00lib.h | 4 +-
drivers/net/wireless/rt2x00/rt2x00mac.c | 42 +------------------
3 files changed, 66 insertions(+), 46 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 9b2bd91..cea2bd9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1046,7 +1046,7 @@ static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev)
}
}

-void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
+static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
{
if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
return;
@@ -1067,7 +1067,7 @@ void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
rt2x00lib_free_ring_entries(rt2x00dev);
}

-int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
+static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
{
int status;

@@ -1110,6 +1110,58 @@ exit:
return status;
}

+int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
+{
+ int retval;
+
+ if (test_bit(DEVICE_STARTED, &rt2x00dev->flags))
+ return 0;
+
+ /*
+ * If this is the first interface which is added,
+ * we should load the firmware now.
+ */
+ if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) {
+ retval = rt2x00lib_load_firmware(rt2x00dev);
+ if (retval)
+ return retval;
+ }
+
+ /*
+ * Initialize the device.
+ */
+ retval = rt2x00lib_initialize(rt2x00dev);
+ if (retval)
+ return retval;
+
+ /*
+ * Enable radio.
+ */
+ retval = rt2x00lib_enable_radio(rt2x00dev);
+ if (retval) {
+ rt2x00lib_uninitialize(rt2x00dev);
+ return retval;
+ }
+
+ __set_bit(DEVICE_STARTED, &rt2x00dev->flags);
+
+ return 0;
+}
+
+void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
+{
+ if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
+ return;
+
+ /*
+ * Perhaps we can add something smarter here,
+ * but for now just disabling the radio should do.
+ */
+ rt2x00lib_disable_radio(rt2x00dev);
+
+ __clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
+}
+
/*
* driver allocation handlers.
*/
@@ -1295,7 +1347,7 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
* Disable radio and unitialize all items
* that must be recreated on resume.
*/
- rt2x00mac_stop(rt2x00dev->hw);
+ rt2x00lib_stop(rt2x00dev);
rt2x00lib_uninitialize(rt2x00dev);
rt2x00debug_deregister(rt2x00dev);

@@ -1317,7 +1369,6 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
int retval;

NOTICE(rt2x00dev, "Waking up.\n");
- __set_bit(DEVICE_PRESENT, &rt2x00dev->flags);

/*
* Open the debugfs entry.
@@ -1333,7 +1384,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
/*
* Reinitialize device and all active interfaces.
*/
- retval = rt2x00mac_start(rt2x00dev->hw);
+ retval = rt2x00lib_start(rt2x00dev);
if (retval)
goto exit;

@@ -1349,6 +1400,11 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
rt2x00lib_config_type(rt2x00dev, intf->type);

/*
+ * We are ready again to receive requests from mac80211.
+ */
+ __set_bit(DEVICE_PRESENT, &rt2x00dev->flags);
+
+ /*
* It is possible that during that mac80211 has attempted
* to send frames while we were suspending or resuming.
* In that case we have disabled the TX queue and should
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 108488d..1adbd28 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -44,8 +44,8 @@ void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev);
/*
* Initialization handlers.
*/
-int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev);
-void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev);
+int rt2x00lib_start(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev);

/*
* Configuration handlers.
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 978cffb..1d67bcd 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -139,41 +139,11 @@ EXPORT_SYMBOL_GPL(rt2x00mac_tx);
int rt2x00mac_start(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- int status;

- if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
- test_bit(DEVICE_STARTED, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
return 0;

- /*
- * If this is the first interface which is added,
- * we should load the firmware now.
- */
- if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) {
- status = rt2x00lib_load_firmware(rt2x00dev);
- if (status)
- return status;
- }
-
- /*
- * Initialize the device.
- */
- status = rt2x00lib_initialize(rt2x00dev);
- if (status)
- return status;
-
- /*
- * Enable radio.
- */
- status = rt2x00lib_enable_radio(rt2x00dev);
- if (status) {
- rt2x00lib_uninitialize(rt2x00dev);
- return status;
- }
-
- __set_bit(DEVICE_STARTED, &rt2x00dev->flags);
-
- return 0;
+ return rt2x00lib_start(rt2x00dev);
}
EXPORT_SYMBOL_GPL(rt2x00mac_start);

@@ -184,13 +154,7 @@ void rt2x00mac_stop(struct ieee80211_hw *hw)
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
return;

- /*
- * Perhaps we can add something smarter here,
- * but for now just disabling the radio should do.
- */
- rt2x00lib_disable_radio(rt2x00dev);
-
- __clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
+ rt2x00lib_stop(rt2x00dev);
}
EXPORT_SYMBOL_GPL(rt2x00mac_stop);

--
1.5.3.7


2008-01-06 22:42:52

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 08/12] rt2x00: Cleanup write_tx_desc() arguments

Send the skb structure with write_tx_desc() and use
the skbdesc structure to read all information about
the frame. This saves several arguments in the function
definition and it is easier to send more information
later as well.

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 8 ++++----
drivers/net/wireless/rt2x00/rt2500pci.c | 8 ++++----
drivers/net/wireless/rt2x00/rt2500usb.c | 8 ++++----
drivers/net/wireless/rt2x00/rt2x00.h | 4 +---
drivers/net/wireless/rt2x00/rt2x00dev.c | 4 +---
drivers/net/wireless/rt2x00/rt61pci.c | 14 +++++++-------
drivers/net/wireless/rt2x00/rt73usb.c | 12 ++++++------
7 files changed, 27 insertions(+), 31 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index b042eb5..ffc7e20 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1012,19 +1012,19 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
* TX descriptor initialization
*/
static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- __le32 *txd,
+ struct sk_buff *skb,
struct txdata_entry_desc *desc,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
struct ieee80211_tx_control *control)
{
+ struct skb_desc *skbdesc = get_skb_desc(skb);
+ __le32 *txd = skbdesc->desc;
u32 word;

/*
* Start writing the descriptor words.
*/
rt2x00_desc_read(txd, 2, &word);
- rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, length);
+ rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, skbdesc->data_len);
rt2x00_desc_write(txd, 2, word);

rt2x00_desc_read(txd, 3, &word);
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index c92163d..81a48e8 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1162,12 +1162,12 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
* TX descriptor initialization
*/
static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- __le32 *txd,
+ struct sk_buff *skb,
struct txdata_entry_desc *desc,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
struct ieee80211_tx_control *control)
{
+ struct skb_desc *skbdesc = get_skb_desc(skb);
+ __le32 *txd = skbdesc->desc;
u32 word;

/*
@@ -1208,7 +1208,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
!!(control->flags &
IEEE80211_TXCTL_LONG_RETRY_LIMIT));
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length);
+ rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
rt2x00_desc_write(txd, 0, word);
}
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 576f0f8..f136703 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1024,12 +1024,12 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
* TX descriptor initialization
*/
static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- __le32 *txd,
+ struct sk_buff *skb,
struct txdata_entry_desc *desc,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
struct ieee80211_tx_control *control)
{
+ struct skb_desc *skbdesc = get_skb_desc(skb);
+ __le32 *txd = skbdesc->desc;
u32 word;

/*
@@ -1062,7 +1062,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
!!(control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT));
rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length);
+ rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE);
rt2x00_desc_write(txd, 0, word);
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 0dc880c..0795332 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -488,10 +488,8 @@ struct rt2x00lib_ops {
* TX control handlers
*/
void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,
- __le32 *txd,
+ struct sk_buff *skb,
struct txdata_entry_desc *desc,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
struct ieee80211_tx_control *control);
int (*write_tx_data) (struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *skb,
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 911060d..a95cf53 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -601,7 +601,6 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
struct txdata_entry_desc desc;
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;
@@ -729,8 +728,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
desc.signal |= 0x08;
}

- rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, txd, &desc, ieee80211hdr,
- skbdesc->data_len, control);
+ rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &desc, control);

/*
* Update ring entry.
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 34bd90b..3080984 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1533,12 +1533,12 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
* TX descriptor initialization
*/
static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- __le32 *txd,
- struct txdata_entry_desc *desc,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
- struct ieee80211_tx_control *control)
+ struct sk_buff *skb,
+ struct txdata_entry_desc *desc,
+ struct ieee80211_tx_control *control)
{
+ struct skb_desc *skbdesc = get_skb_desc(skb);
+ __le32 *txd = skbdesc->desc;
u32 word;

/*
@@ -1567,7 +1567,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_desc_write(txd, 5, word);

rt2x00_desc_read(txd, 11, &word);
- rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, length);
+ rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len);
rt2x00_desc_write(txd, 11, word);

rt2x00_desc_read(txd, 0, &word);
@@ -1586,7 +1586,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
!!(control->flags &
IEEE80211_TXCTL_LONG_RETRY_LIMIT));
rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length);
+ rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
rt2x00_set_field32(&word, TXD_W0_BURST,
test_bit(ENTRY_TXD_BURST, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index f2d1810..2982470 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1231,12 +1231,12 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
* TX descriptor initialization
*/
static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- __le32 *txd,
- struct txdata_entry_desc *desc,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
- struct ieee80211_tx_control *control)
+ struct sk_buff *skb,
+ struct txdata_entry_desc *desc,
+ struct ieee80211_tx_control *control)
{
+ struct skb_desc *skbdesc = get_skb_desc(skb);
+ __le32 *txd = skbdesc->desc;
u32 word;

/*
@@ -1281,7 +1281,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
!!(control->flags &
IEEE80211_TXCTL_LONG_RETRY_LIMIT));
rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length);
+ rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
rt2x00_set_field32(&word, TXD_W0_BURST2,
test_bit(ENTRY_TXD_BURST, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
--
1.5.3.7


2008-01-06 22:39:52

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 02/12] rt2x00: Always call ieee80211_stop_queue() when return NETDEV_TX_BUSY

Apparently it was possible that ieee80211_stop_queue() was not full while
NETDEV_TX_BUSY was being reported back. I think that is what causing the WARN_ON().
This moves all calls to ieee80211_stop_queue() in rt2x00mac.c where it is easier
to determine if the queue should be halted.

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00mac.c | 17 +++++++++++++----
drivers/net/wireless/rt2x00/rt2x00pci.c | 8 +-------
drivers/net/wireless/rt2x00/rt2x00usb.c | 8 +-------
3 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 86b6a33..978cffb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -84,7 +84,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
*/
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) {
ieee80211_stop_queues(hw);
- return 0;
+ return NETDEV_TX_OK;
}

/*
@@ -110,15 +110,24 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) &&
(control->flags & (IEEE80211_TXCTL_USE_RTS_CTS |
IEEE80211_TXCTL_USE_CTS_PROTECT))) {
- if (rt2x00_ring_free(ring) <= 1)
+ if (rt2x00_ring_free(ring) <= 1) {
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return NETDEV_TX_BUSY;
+ }

- if (rt2x00mac_tx_rts_cts(rt2x00dev, ring, skb, control))
+ if (rt2x00mac_tx_rts_cts(rt2x00dev, ring, skb, control)) {
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return NETDEV_TX_BUSY;
+ }
}

- if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control))
+ if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) {
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return NETDEV_TX_BUSY;
+ }
+
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);

if (rt2x00dev->ops->lib->kick_tx_queue)
rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index abeffdb..70cb81c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -86,10 +86,8 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
struct skb_desc *desc;
u32 word;

- if (rt2x00_ring_full(ring)) {
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ if (rt2x00_ring_full(ring))
return -EINVAL;
- }

rt2x00_desc_read(txd, 0, &word);

@@ -99,7 +97,6 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
"Arrived at non-free entry in the non-full queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return -EINVAL;
}

@@ -119,9 +116,6 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,

rt2x00_ring_index_inc(ring);

- if (rt2x00_ring_full(ring))
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
-
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 82e95b9..7aba357 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -179,17 +179,14 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
struct skb_desc *desc;
u32 length;

- if (rt2x00_ring_full(ring)) {
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ if (rt2x00_ring_full(ring))
return -EINVAL;
- }

if (test_bit(ENTRY_OWNER_NIC, &entry->flags)) {
ERROR(rt2x00dev,
"Arrived at non-free entry in the non-full queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return -EINVAL;
}

@@ -229,9 +226,6 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,

rt2x00_ring_index_inc(ring);

- if (rt2x00_ring_full(ring))
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
-
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
--
1.5.3.7


2008-01-06 22:42:57

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 10/12] rt2x00: Move init_txring and init_rxring into rt2x00lib

Prior to enabling the radio rt2x00lib should go through all
rings and for each entry should call the callback function
init_txentry() and init_rxentry().

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 83 +++++++++-------------------
drivers/net/wireless/rt2x00/rt2500pci.c | 69 +++++++-----------------
drivers/net/wireless/rt2x00/rt2500usb.c | 4 +-
drivers/net/wireless/rt2x00/rt2x00.h | 8 +++
drivers/net/wireless/rt2x00/rt2x00dev.c | 46 ++++++++++++++++
drivers/net/wireless/rt2x00/rt2x00usb.c | 60 ++++++++-------------
drivers/net/wireless/rt2x00/rt2x00usb.h | 5 ++-
drivers/net/wireless/rt2x00/rt61pci.c | 88 +++++++++++--------------------
drivers/net/wireless/rt2x00/rt73usb.c | 4 +-
9 files changed, 163 insertions(+), 204 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 95db2cc..f4d0c77 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -592,65 +592,43 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev)
/*
* Initialization functions.
*/
-static void rt2400pci_init_rxring(struct rt2x00_dev *rt2x00dev)
+static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
{
- struct data_ring *ring = rt2x00dev->rx;
- __le32 *rxd;
- unsigned int i;
+ __le32 *rxd = entry->priv;
u32 word;

- memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++) {
- rxd = ring->entry[i].priv;
+ rt2x00_desc_read(rxd, 2, &word);
+ rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->ring->data_size);
+ rt2x00_desc_write(rxd, 2, word);

- rt2x00_desc_read(rxd, 2, &word);
- rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH,
- ring->data_size);
- rt2x00_desc_write(rxd, 2, word);
-
- rt2x00_desc_read(rxd, 1, &word);
- rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS,
- ring->entry[i].data_dma);
- rt2x00_desc_write(rxd, 1, word);
-
- rt2x00_desc_read(rxd, 0, &word);
- rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
- rt2x00_desc_write(rxd, 0, word);
- }
+ rt2x00_desc_read(rxd, 1, &word);
+ rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma);
+ rt2x00_desc_write(rxd, 1, word);

- rt2x00_ring_index_clear(rt2x00dev->rx);
+ rt2x00_desc_read(rxd, 0, &word);
+ rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+ rt2x00_desc_write(rxd, 0, word);
}

-static void rt2400pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue)
+static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
{
- struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
- __le32 *txd;
- unsigned int i;
+ __le32 *txd = entry->priv;
u32 word;

- memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++) {
- txd = ring->entry[i].priv;
-
- rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS,
- ring->entry[i].data_dma);
- rt2x00_desc_write(txd, 1, word);
+ rt2x00_desc_read(txd, 1, &word);
+ rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma);
+ rt2x00_desc_write(txd, 1, word);

- rt2x00_desc_read(txd, 2, &word);
- rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH,
- ring->data_size);
- rt2x00_desc_write(txd, 2, word);
-
- rt2x00_desc_read(txd, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
- rt2x00_desc_write(txd, 0, word);
- }
+ rt2x00_desc_read(txd, 2, &word);
+ rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, entry->ring->data_size);
+ rt2x00_desc_write(txd, 2, word);

- rt2x00_ring_index_clear(ring);
+ rt2x00_desc_read(txd, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+ rt2x00_desc_write(txd, 0, word);
}

static int rt2400pci_init_rings(struct rt2x00_dev *rt2x00dev)
@@ -658,15 +636,6 @@ static int rt2400pci_init_rings(struct rt2x00_dev *rt2x00dev)
u32 reg;

/*
- * Initialize rings.
- */
- rt2400pci_init_rxring(rt2x00dev);
- rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
- rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
- rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
- rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
-
- /*
* Initialize registers.
*/
rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
@@ -1569,6 +1538,8 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.probe_hw = rt2400pci_probe_hw,
.initialize = rt2x00pci_initialize,
.uninitialize = rt2x00pci_uninitialize,
+ .init_rxentry = rt2400pci_init_rxentry,
+ .init_txentry = rt2400pci_init_txentry,
.set_device_state = rt2400pci_set_device_state,
.rfkill_poll = rt2400pci_rfkill_poll,
.link_stats = rt2400pci_link_stats,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 133967e..206b50f 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -683,55 +683,35 @@ dynamic_cca_tune:
/*
* Initialization functions.
*/
-static void rt2500pci_init_rxring(struct rt2x00_dev *rt2x00dev)
+static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
{
- struct data_ring *ring = rt2x00dev->rx;
- __le32 *rxd;
- unsigned int i;
+ __le32 *rxd = entry->priv;
u32 word;

- memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++) {
- rxd = ring->entry[i].priv;
-
- rt2x00_desc_read(rxd, 1, &word);
- rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS,
- ring->entry[i].data_dma);
- rt2x00_desc_write(rxd, 1, word);
-
- rt2x00_desc_read(rxd, 0, &word);
- rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
- rt2x00_desc_write(rxd, 0, word);
- }
+ rt2x00_desc_read(rxd, 1, &word);
+ rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma);
+ rt2x00_desc_write(rxd, 1, word);

- rt2x00_ring_index_clear(rt2x00dev->rx);
+ rt2x00_desc_read(rxd, 0, &word);
+ rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+ rt2x00_desc_write(rxd, 0, word);
}

-static void rt2500pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue)
+static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
{
- struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
- __le32 *txd;
- unsigned int i;
+ __le32 *txd = entry->priv;
u32 word;

- memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++) {
- txd = ring->entry[i].priv;
+ rt2x00_desc_read(txd, 1, &word);
+ rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma);
+ rt2x00_desc_write(txd, 1, word);

- rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS,
- ring->entry[i].data_dma);
- rt2x00_desc_write(txd, 1, word);
-
- rt2x00_desc_read(txd, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
- rt2x00_desc_write(txd, 0, word);
- }
-
- rt2x00_ring_index_clear(ring);
+ rt2x00_desc_read(txd, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+ rt2x00_desc_write(txd, 0, word);
}

static int rt2500pci_init_rings(struct rt2x00_dev *rt2x00dev)
@@ -739,15 +719,6 @@ static int rt2500pci_init_rings(struct rt2x00_dev *rt2x00dev)
u32 reg;

/*
- * Initialize rings.
- */
- rt2500pci_init_rxring(rt2x00dev);
- rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
- rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
- rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
- rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
-
- /*
* Initialize registers.
*/
rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
@@ -1878,6 +1849,8 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.probe_hw = rt2500pci_probe_hw,
.initialize = rt2x00pci_initialize,
.uninitialize = rt2x00pci_uninitialize,
+ .init_rxentry = rt2500pci_init_rxentry,
+ .init_txentry = rt2500pci_init_txentry,
.set_device_state = rt2500pci_set_device_state,
.rfkill_poll = rt2500pci_rfkill_poll,
.link_stats = rt2500pci_link_stats,
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 2a4e939..1b05b8a 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -920,8 +920,6 @@ static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev)
return -EIO;
}

- rt2x00usb_enable_radio(rt2x00dev);
-
/*
* Enable LED
*/
@@ -1776,6 +1774,8 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
.probe_hw = rt2500usb_probe_hw,
.initialize = rt2x00usb_initialize,
.uninitialize = rt2x00usb_uninitialize,
+ .init_rxentry = rt2x00usb_init_rxentry,
+ .init_txentry = rt2x00usb_init_txentry,
.set_device_state = rt2500usb_set_device_state,
.link_stats = rt2500usb_link_stats,
.reset_tuner = rt2500usb_reset_tuner,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 0795332..d8585a0 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -474,6 +474,14 @@ struct rt2x00lib_ops {
void (*uninitialize) (struct rt2x00_dev *rt2x00dev);

/*
+ * Ring initialization handlers
+ */
+ void (*init_rxentry) (struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry);
+ void (*init_txentry) (struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry);
+
+ /*
* Radio control handlers.
*/
int (*set_device_state) (struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index a114212..b26c634 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -103,6 +103,46 @@ void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev)
}

/*
+ * Ring initialization
+ */
+static void rt2x00lib_init_rxrings(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_ring *ring = rt2x00dev->rx;
+ unsigned int i;
+
+ if (!rt2x00dev->ops->lib->init_rxentry)
+ return;
+
+ if (ring->data_addr)
+ memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
+
+ for (i = 0; i < ring->stats.limit; i++)
+ rt2x00dev->ops->lib->init_rxentry(rt2x00dev, &ring->entry[i]);
+
+ rt2x00_ring_index_clear(ring);
+}
+
+static void rt2x00lib_init_txrings(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_ring *ring;
+ unsigned int i;
+
+ if (!rt2x00dev->ops->lib->init_txentry)
+ return;
+
+ txringall_for_each(rt2x00dev, ring) {
+ if (ring->data_addr)
+ memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
+
+ for (i = 0; i < ring->stats.limit; i++)
+ rt2x00dev->ops->lib->init_txentry(rt2x00dev,
+ &ring->entry[i]);
+
+ rt2x00_ring_index_clear(ring);
+ }
+}
+
+/*
* Radio control handlers.
*/
int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -118,6 +158,12 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
return 0;

/*
+ * Initialize all data rings.
+ */
+ rt2x00lib_init_rxrings(rt2x00dev);
+ rt2x00lib_init_txrings(rt2x00dev);
+
+ /*
* Enable radio.
*/
status = rt2x00dev->ops->lib->set_device_state(rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 8a6218f..d15d469 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -326,43 +326,6 @@ skip_entry:
/*
* Radio handlers
*/
-void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev)
-{
- struct usb_device *usb_dev =
- interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
- struct data_ring *ring;
- struct data_entry *entry;
- unsigned int i;
-
- /*
- * Initialize the TX rings
- */
- txringall_for_each(rt2x00dev, ring) {
- for (i = 0; i < ring->stats.limit; i++)
- ring->entry[i].flags = 0;
-
- rt2x00_ring_index_clear(ring);
- }
-
- /*
- * Initialize and start the RX ring.
- */
- rt2x00_ring_index_clear(rt2x00dev->rx);
-
- for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
- entry = &rt2x00dev->rx->entry[i];
-
- usb_fill_bulk_urb(entry->priv, usb_dev,
- usb_rcvbulkpipe(usb_dev, 1),
- entry->skb->data, entry->skb->len,
- rt2x00usb_interrupt_rxdone, entry);
-
- __set_bit(ENTRY_OWNER_NIC, &entry->flags);
- usb_submit_urb(entry->priv, GFP_ATOMIC);
- }
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_enable_radio);
-
void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
{
struct data_ring *ring;
@@ -384,6 +347,29 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
/*
* Device initialization handlers.
*/
+void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
+{
+ struct usb_device *usb_dev =
+ interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
+
+ usb_fill_bulk_urb(entry->priv, usb_dev,
+ usb_rcvbulkpipe(usb_dev, 1),
+ entry->skb->data, entry->skb->len,
+ rt2x00usb_interrupt_rxdone, entry);
+
+ __set_bit(ENTRY_OWNER_NIC, &entry->flags);
+ usb_submit_urb(entry->priv, GFP_ATOMIC);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry);
+
+void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
+{
+ entry->flags = 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_init_txentry);
+
static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring)
{
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 2fa45c5..e40df40 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -154,7 +154,6 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
/*
* Radio handlers
*/
-void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev);
void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);

/*
@@ -167,6 +166,10 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
/*
* Device initialization handlers.
*/
+void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry);
+void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry);
int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev);
void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);

diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 47b7430..b2dde4d 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -989,66 +989,46 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
return 0;
}

-static void rt61pci_init_rxring(struct rt2x00_dev *rt2x00dev)
+static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
{
- struct data_ring *ring = rt2x00dev->rx;
- __le32 *rxd;
- unsigned int i;
+ __le32 *rxd = entry->priv;
u32 word;

- memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++) {
- rxd = ring->entry[i].priv;
-
- rt2x00_desc_read(rxd, 5, &word);
- rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
- ring->entry[i].data_dma);
- rt2x00_desc_write(rxd, 5, word);
-
- rt2x00_desc_read(rxd, 0, &word);
- rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
- rt2x00_desc_write(rxd, 0, word);
- }
+ rt2x00_desc_read(rxd, 5, &word);
+ rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
+ entry->data_dma);
+ rt2x00_desc_write(rxd, 5, word);

- rt2x00_ring_index_clear(rt2x00dev->rx);
+ rt2x00_desc_read(rxd, 0, &word);
+ rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+ rt2x00_desc_write(rxd, 0, word);
}

-static void rt61pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue)
+static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
{
- struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
- __le32 *txd;
- unsigned int i;
+ __le32 *txd = entry->priv;
u32 word;

- memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++) {
- txd = ring->entry[i].priv;
-
- rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
- rt2x00_desc_write(txd, 1, word);
-
- rt2x00_desc_read(txd, 5, &word);
- rt2x00_set_field32(&word, TXD_W5_PID_TYPE,
- ring->queue_idx);
- rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE,
- ring->entry[i].entry_idx);
- rt2x00_desc_write(txd, 5, word);
+ rt2x00_desc_read(txd, 1, &word);
+ rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
+ rt2x00_desc_write(txd, 1, word);

- rt2x00_desc_read(txd, 6, &word);
- rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
- ring->entry[i].data_dma);
- rt2x00_desc_write(txd, 6, word);
+ rt2x00_desc_read(txd, 5, &word);
+ rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->ring->queue_idx);
+ rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx);
+ rt2x00_desc_write(txd, 5, word);

- rt2x00_desc_read(txd, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
- rt2x00_desc_write(txd, 0, word);
- }
+ rt2x00_desc_read(txd, 6, &word);
+ rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
+ entry->data_dma);
+ rt2x00_desc_write(txd, 6, word);

- rt2x00_ring_index_clear(ring);
+ rt2x00_desc_read(txd, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+ rt2x00_desc_write(txd, 0, word);
}

static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
@@ -1056,16 +1036,6 @@ static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
u32 reg;

/*
- * Initialize rings.
- */
- rt61pci_init_rxring(rt2x00dev);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA2);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA3);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA4);
-
- /*
* Initialize registers.
*/
rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, &reg);
@@ -2487,6 +2457,8 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
.load_firmware = rt61pci_load_firmware,
.initialize = rt2x00pci_initialize,
.uninitialize = rt2x00pci_uninitialize,
+ .init_rxentry = rt61pci_init_rxentry,
+ .init_txentry = rt61pci_init_txentry,
.set_device_state = rt61pci_set_device_state,
.rfkill_poll = rt61pci_rfkill_poll,
.link_stats = rt61pci_link_stats,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index beaa264..78217dc 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1136,8 +1136,6 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
return -EIO;
}

- rt2x00usb_enable_radio(rt2x00dev);
-
/*
* Enable LED
*/
@@ -2033,6 +2031,8 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
.load_firmware = rt73usb_load_firmware,
.initialize = rt2x00usb_initialize,
.uninitialize = rt2x00usb_uninitialize,
+ .init_rxentry = rt2x00usb_init_rxentry,
+ .init_txentry = rt2x00usb_init_txentry,
.set_device_state = rt73usb_set_device_state,
.link_stats = rt73usb_link_stats,
.reset_tuner = rt73usb_reset_tuner,
--
1.5.3.7


2008-01-11 11:38:27

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 06/12] rt2x00: Put 802.11 data on 4 byte boundary

Sorry I'm late in noticing this :\

> + /*
> + * The data behind the ieee80211 header must be
> + * aligned on a 4 byte boundary.
> + */
> + align = NET_IP_ALIGN + (2 * (header_size % 4 == 0));

I don't think you should be using NET_IP_ALIGN at all, I think the code
should be just

align = header_size % 4;

(which will evaluate to two or four).

See, NET_IP_ALIGN is 2 because ethernet headers are 14 bytes long, and 2
plus 14 gives 16 which is divisible by four.

I have, so far, in mac80211 forced you to align the 802.11 data payload
to a four-byte boundary *even on powerpc* which is the only platform
where NET_IP_ALIGN is not two (it is zero because DMA sucks when done to
unaligned addresses on some powerpc machines).

We are, however, not concerned with ethernet frames here at all! Hence,
NET_IP_ALIGN is pretty much useless because it's designed for the
ethernet case.

I think Broadcom hardware really represents the ideal case here: The sum
of the lengths of all headers including hardware/firmware receive
header, plcp information and 802.11 header is always a multiple of four,
if necessary the hardware/firmware header is padded (by two bytes) to
achieve this. This means we can always do "perfect" DMA right to the
beginning of the buffer and always get the right IP header alignment.

Once you deviate from that ideal case, performance suffers. Either
because you need to move around data or because you have to do unaligned
loads. The latter I have currently disallowed in mac80211 (via that
WARN_ON_ONCE) because most drivers got it wrong and hence won't function
on machines that require or force alignment.

In any case, NET_IP_ALIGN is really designed for ethernet and DMA. Since
we're not doing ethernet, it's not important. Since you're not doing DMA
here, it's even less important. If it becomes possible for you to do
DMA, you should probably do it right into the start of a buffer and
memmove() the data a bit when necessary to achieve 4-byte alignment.

Once you have done that, we can talk about possibly relaxing the
WARN_ON_ONCE() in mac80211 a bit so you don't have to memmove() the data
on machines where unaligned loads are possible. Then we can investigate
which hurts performance more, but I guess it'll be machine-dependent (I
would guess that enough cache means a memmove is fast or at least
amortized later when we load the data anyway, unaligned loads on the
other hand hurt every time the IP stack needs a field)

Now, I can see one case where you could again use NET_IP_ALIGN, but it
has a bunch of preconditions:
- you do DMA right into the skb
- you have a RX header that is divisible by four
- you decide that QoS frames are going to be more common than non-QoS

Initially, these conditions mean that you'd ask the machine to do DMA
into the start of the skb + 2, because you want to have the IP data
aligned properly in the QoS case. Then, however, you should use
NET_IP_ALIGN instead of the two and not do any memmove at all. But
seeing that's only relevant for some powerpc machines and wireless
hardware isn't fast enough yet to matter, I don't think it makes a
difference.

We should, however, reach out to vendors and ask them to do the required
padding in firmware/hardware.

This leads me to an interesting question for A-MSDU packets, but I'll
write another mail about that.

johannes


Attachments:
signature.asc (828.00 B)
This is a digitally signed message part

2008-01-06 22:42:54

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 09/12] rt2x00: Determine MY_BSS from descriptor

Use the MY_BSS descriptor field to determine if the
received frame belongs to the same BSS as the interface.
This can be used by rxdone to determine if the frame
should be updated or not.

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 1 +
drivers/net/wireless/rt2x00/rt2500pci.c | 1 +
drivers/net/wireless/rt2x00/rt2500usb.c | 3 +--
drivers/net/wireless/rt2x00/rt2x00dev.c | 18 +++++-------------
drivers/net/wireless/rt2x00/rt2x00ring.h | 1 +
drivers/net/wireless/rt2x00/rt61pci.c | 3 +--
drivers/net/wireless/rt2x00/rt73usb.c | 3 +--
7 files changed, 11 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index ffc7e20..95db2cc 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1117,6 +1117,7 @@ static void rt2400pci_fill_rxdone(struct data_entry *entry,
entry->ring->rt2x00dev->rssi_offset;
desc->ofdm = 0;
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+ desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
}

/*
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 81a48e8..133967e 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1264,6 +1264,7 @@ static void rt2500pci_fill_rxdone(struct data_entry *entry,
entry->ring->rt2x00dev->rssi_offset;
desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+ desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
}

/*
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index f136703..2a4e939 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1138,8 +1138,7 @@ static void rt2500usb_fill_rxdone(struct data_entry *entry,
entry->ring->rt2x00dev->rssi_offset;
desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-
- return;
+ desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
}

/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index a95cf53..a114212 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -526,7 +526,6 @@ 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;
@@ -559,19 +558,12 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
}

/*
- * Only update link status if this is a beacon frame carrying our
- * bssid.
+ * 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);
- }
+ hdr = (struct ieee80211_hdr*)skb->data;
+ fc = le16_to_cpu(hdr->frame_control);
+ if (is_beacon(fc) && desc->my_bss)
+ rt2x00lib_update_link_stats(&rt2x00dev->link, desc->rssi);

rt2x00dev->link.qual.rx_success++;

diff --git a/drivers/net/wireless/rt2x00/rt2x00ring.h b/drivers/net/wireless/rt2x00/rt2x00ring.h
index e9a5648..1caa6d6 100644
--- a/drivers/net/wireless/rt2x00/rt2x00ring.h
+++ b/drivers/net/wireless/rt2x00/rt2x00ring.h
@@ -59,6 +59,7 @@ struct rxdata_entry_desc {
int ofdm;
int size;
int flags;
+ int my_bss;
};

/*
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 3080984..47b7430 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1695,8 +1695,7 @@ static void rt61pci_fill_rxdone(struct data_entry *entry,
desc->rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1);
desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-
- return;
+ desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
}

/*
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 2982470..beaa264 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1396,13 +1396,12 @@ static void rt73usb_fill_rxdone(struct data_entry *entry,
desc->rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1);
desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+ desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);

/*
* Pull the skb to clear the descriptor area.
*/
skb_pull(entry->skb, entry->ring->desc_size);
-
- return;
}

/*
--
1.5.3.7


2008-01-06 22:39:51

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 01/12] rt2x00: Fix chipset debugfs file

Initialize blob->data before moving the data pointer
Initialize blob->size based on blob->data size

This fixes the empty chipset file in debugfs.

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

diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index e72c981..c55bf0e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -417,6 +417,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
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);
@@ -425,9 +426,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
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->data = data;
- blob->size = strlen(data);
+ blob->size = strlen(blob->data);

return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob);
}
--
1.5.3.7


2008-01-06 22:43:01

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 12/12] rt2x00: Release rt2x00 2.0.14


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 d8585a0..94a8a7c 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.13"
+#define DRV_VERSION "2.0.14"
#define DRV_PROJECT "http://rt2x00.serialmonkey.com"

/*
--
1.5.3.7


2008-01-06 22:39:56

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 04/12] rt2x00: Store queue idx and entry idx in data_ring and data_entry

Store the queue idx inside structure data_ring
Store the entry idx inside structure data_entry
This saves us a few calls to ARRAY_INDEX() which is now unused.

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00.h | 6 ------
drivers/net/wireless/rt2x00/rt2x00debug.c | 8 ++------
drivers/net/wireless/rt2x00/rt2x00dev.c | 4 ++++
drivers/net/wireless/rt2x00/rt2x00ring.h | 12 ++++++++++++
drivers/net/wireless/rt2x00/rt61pci.c | 6 ++++--
5 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 87c2c05..af0bf4b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -796,12 +796,6 @@ 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 c55bf0e..b44a9f4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -120,12 +120,8 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
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;
@@ -151,8 +147,8 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
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->ring_index = desc->ring->queue_idx;
+ dump_hdr->entry_index = desc->entry->entry_idx;
dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);

diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index a771a09..9b2bd91 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -988,6 +988,7 @@ static int rt2x00lib_alloc_entries(struct data_ring *ring,
entry[i].flags = 0;
entry[i].ring = ring;
entry[i].skb = NULL;
+ entry[i].entry_idx = i;
}

ring->entry = entry;
@@ -1115,6 +1116,7 @@ exit:
static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev)
{
struct data_ring *ring;
+ unsigned int index;

/*
* We need the following rings:
@@ -1145,8 +1147,10 @@ static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev)
* cw_min: 2^5 = 32.
* cw_max: 2^10 = 1024.
*/
+ index = 0;
ring_for_each(rt2x00dev, ring) {
ring->rt2x00dev = rt2x00dev;
+ ring->queue_idx = index++;
ring->tx_params.aifs = 2;
ring->tx_params.cw_min = 5;
ring->tx_params.cw_max = 10;
diff --git a/drivers/net/wireless/rt2x00/rt2x00ring.h b/drivers/net/wireless/rt2x00/rt2x00ring.h
index 5b32f3e..e9a5648 100644
--- a/drivers/net/wireless/rt2x00/rt2x00ring.h
+++ b/drivers/net/wireless/rt2x00/rt2x00ring.h
@@ -143,6 +143,11 @@ struct data_entry {
*/
void *data_addr;
dma_addr_t data_dma;
+
+ /*
+ * Entry identification number (index).
+ */
+ unsigned int entry_idx;
};

/*
@@ -181,6 +186,13 @@ struct data_ring {
void *data_addr;

/*
+ * Queue identification number:
+ * RX: 0
+ * TX: IEEE80211_TX_*
+ */
+ unsigned int queue_idx;
+
+ /*
* Index variables.
*/
u16 index;
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index f5b3378..3bfc5af 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1031,8 +1031,10 @@ static void rt61pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue)
rt2x00_desc_write(txd, 1, word);

rt2x00_desc_read(txd, 5, &word);
- rt2x00_set_field32(&word, TXD_W5_PID_TYPE, queue);
- rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, i);
+ rt2x00_set_field32(&word, TXD_W5_PID_TYPE,
+ ring->queue_idx);
+ rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE,
+ ring->entry[i].entry_idx);
rt2x00_desc_write(txd, 5, word);

rt2x00_desc_read(txd, 6, &word);
--
1.5.3.7


2008-01-11 19:51:49

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 06/12] rt2x00: Put 802.11 data on 4 byte boundary

Hi,

> Sorry I'm late in noticing this :\
>
> > + /*
> > + * The data behind the ieee80211 header must be
> > + * aligned on a 4 byte boundary.
> > + */
> > + align = NET_IP_ALIGN + (2 * (header_size % 4 == 0));
>
> I don't think you should be using NET_IP_ALIGN at all, I think the code
> should be just
>
> align = header_size % 4;
>
> (which will evaluate to two or four).

Makes sense. I'll fix this asap.

> I have, so far, in mac80211 forced you to align the 802.11 data payload
> to a four-byte boundary *even on powerpc* which is the only platform
> where NET_IP_ALIGN is not two (it is zero because DMA sucks when done to
> unaligned addresses on some powerpc machines).

Ouch, that would make rt2x00usb panicking as soon as it is used when
NET_IP_ALIGN in 0 and alignment is needed. :S
This will be fixed asap as well.

Thanks,

Ivo

2008-01-10 11:52:43

by Will Dyson

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

On Jan 6, 2008 5:37 PM, Ivo van Doorn <[email protected]> wrote:
> Hi John,
>
> Here is the 2.0.14 release of rt2x00. Again lots of bugfixes,
> and unfortunately we are still not there yet. I am afraid
> rt2500usb and rt61pci are lost causes for the 2.6.24 release,
> they are both broken, and I haven't figured out what is causing
> this.

Hi Ivo,

Sorry to be out of the loop, but what is wrong with rt61pci? It works
really really well for me, using John's "everything" branch.

Hmm. Looking at Linus's tree, I can see that rt61pci is missing at
least 1 critical fix from Mattias Nissler that has been in
wireless-2.6 for a long time now.

rt2x00: Allow rt61 to catch up after a missing tx report

I'd be pretty disappointed if we released 2.6.24 without this. It is a
simple fix for a really obnoxious problem (although one that triggers
rarely on my hardware).

There are also a bunch of antenna selection fixes that never went
upstream. These are required for my card to operate well at rates
greater than 1Mbit, even when fairly close to the AP.

But aside from these issues, the latest 2.6.24-rc7 seems ok for me. My
testing of it is somewhat limited, due to the terrible performance.
But I can associate, browse the web and run iperf tests.

--
Will Dyson

2008-01-10 20:32:50

by Stefan Lippers-Hollmann

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

Hi

On Donnerstag, 10. Januar 2008, Will Dyson wrote:
[...]
> Sorry to be out of the loop, but what is wrong with rt61pci? It works
> really really well for me, using John's "everything" branch.
>
> Hmm. Looking at Linus's tree, I can see that rt61pci is missing at
> least 1 critical fix from Mattias Nissler that has been in
> wireless-2.6 for a long time now.
>
> rt2x00: Allow rt61 to catch up after a missing tx report
>
> I'd be pretty disappointed if we released 2.6.24 without this. It is a
> simple fix for a really obnoxious problem (although one that triggers
> rarely on my hardware).

The same goes for (which can be easily rediffed against linux-2.6):
[PATCH 06/12] rt2x00: Put 802.11 data on 4 byte boundary
without it, at least rt61pci, rt73usb and rt2500usb (plain
2.6.24-rc7-git2) trigger the well known:

WARNING: at net/mac80211/rx.c:1486 __ieee80211_rx()
Pid: 0, comm: swapper Not tainted 2.6.24-rc7-git2-slh64-smp-1 #1

Call Trace:
<IRQ> [<ffffffff80232e4a>] __wake_up_common+0x5a/0x90
[<ffffffff881fed9e>] :mac80211:__ieee80211_rx+0xbde/0xd00
[<ffffffff880cb3e6>] :ehci_hcd:ehci_work+0x5d6/0x8e0
[<ffffffff881f028b>] :mac80211:ieee80211_tasklet_handler+0xbb/0x120
[<ffffffff80243507>] tasklet_action+0x47/0xb0
[<ffffffff80243415>] __do_softirq+0x75/0xe0
[<ffffffff8020d62c>] call_softirq+0x1c/0x30
[<ffffffff8020f9f5>] do_softirq+0x35/0x90
[<ffffffff802432a6>] irq_exit+0x96/0xa0
[<ffffffff8020fad0>] do_IRQ+0x80/0x100
[<ffffffff8020af60>] default_idle+0x0/0x40
[<ffffffff8020af60>] default_idle+0x0/0x40
[<ffffffff8020c981>] ret_from_intr+0x0/0xa
<EOI> [<ffffffff80220e60>] lapic_next_event+0x0/0x10
[<ffffffff8020af89>] default_idle+0x29/0x40
[<ffffffff8020b00f>] cpu_idle+0x6f/0xe0

> There are also a bunch of antenna selection fixes that never went
> upstream. These are required for my card to operate well at rates
> greater than 1Mbit, even when fairly close to the AP.
>
> But aside from these issues, the latest 2.6.24-rc7 seems ok for me. My
> testing of it is somewhat limited, due to the terrible performance.
> But I can associate, browse the web and run iperf tests.

I can just agree to this statement, rt73usb works really well (at steady
~2.4 MB/s) and rt61pci is the first driver to actually work at all (yes,
the same performance issues, but rt61-legacy freezes using wpa2psk;
rt2500usb seems to have more problems).

All tests based on plain 2.6.24-rc7-git2 (amd64 and wpa2psk/ CCMP) + the
following patches:
- [PATCH 06/12] rt2x00: Put 802.11 data on 4 byte boundary
- [PATCH] rt2x00: Corectly initialize rt2500usb MAC

Thanks a lot
Stefan Lippers-Hollmann

2008-01-06 22:39:54

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 03/12] rt2x00: Only set the TBCN flag when the interface is configured to send beacons.

These flags used to be fixed to one in rt2500pci_config_type, which
caused the beacon timer interrupt to fire. This would lead to
rt2x00lib_beacondone adding work which called
rt2x00lib_beacondone_scheduled which called ieee80211_beacon_get which
printed an error about not having any beacon data.

With this patch, these interrupts are only generated when the interface
is configured to send beacons.

Signed-off-by: Matthijs Kooijman <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 2 +-
drivers/net/wireless/rt2x00/rt2500pci.c | 2 +-
drivers/net/wireless/rt2x00/rt2500usb.c | 3 ++-
drivers/net/wireless/rt2x00/rt61pci.c | 3 ++-
drivers/net/wireless/rt2x00/rt73usb.c | 3 ++-
5 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index c9a234f..9eed9e9 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -280,7 +280,7 @@ static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
*/
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
- rt2x00_set_field32(&reg, CSR14_TBCN, 1);
+ rt2x00_set_field32(&reg, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON));
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, tsf_sync);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index a623454..8b2f54b 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -284,7 +284,7 @@ static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
*/
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
- rt2x00_set_field32(&reg, CSR14_TBCN, 1);
+ rt2x00_set_field32(&reg, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON));
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, tsf_sync);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 2ba8eda..27d34dd 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -327,7 +327,8 @@ static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,

rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
- rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
+ rt2x00_set_field16(&reg, TXRX_CSR19_TBCN,
+ (tsf_sync == TSF_SYNC_BEACON));
rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, tsf_sync);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 13c8086..f5b3378 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -317,7 +317,8 @@ static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
*/
rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
- rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
+ rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE,
+ (tsf_sync == TSF_SYNC_BEACON));
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, tsf_sync);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 8093a4d..9393415 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -327,7 +327,8 @@ static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
*/
rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
- rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
+ rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE,
+ (tsf_sync == TSF_SYNC_BEACON));
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, tsf_sync);
rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
--
1.5.3.7


2008-01-10 17:29:09

by Ivo Van Doorn

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

On Thursday 10 January 2008, John W. Linville wrote:
> On Thu, Jan 10, 2008 at 06:52:40AM -0500, Will Dyson wrote:
>
> > Hmm. Looking at Linus's tree, I can see that rt61pci is missing at
> > least 1 critical fix from Mattias Nissler that has been in
> > wireless-2.6 for a long time now.
> >
> > rt2x00: Allow rt61 to catch up after a missing tx report
> >
> > I'd be pretty disappointed if we released 2.6.24 without this. It is a
> > simple fix for a really obnoxious problem (although one that triggers
> > rarely on my hardware).
>
> This one can be cherry-picked fairly easily for 2.6.24. Ivo, any
> reason not to do that?

Nope, if it can be merged into 2.6.24 easily it should indeed go upstream.

> > There are also a bunch of antenna selection fixes that never went
> > upstream. These are required for my card to operate well at rates
> > greater than 1Mbit, even when fairly close to the AP.
>
> Can you identify specific patches? If so I can evaluate whether they
> apply easily to 2.6.24 or if they need significant rework.

I'm afraid the antenna code concerns the antenna diversity which is quite
a lot of code. I'm not sure how easily it can be merged, but I expect it to
be somewhat troublesome.

Ivo


2008-01-10 16:21:33

by John W. Linville

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

On Thu, Jan 10, 2008 at 06:52:40AM -0500, Will Dyson wrote:

> Hmm. Looking at Linus's tree, I can see that rt61pci is missing at
> least 1 critical fix from Mattias Nissler that has been in
> wireless-2.6 for a long time now.
>
> rt2x00: Allow rt61 to catch up after a missing tx report
>
> I'd be pretty disappointed if we released 2.6.24 without this. It is a
> simple fix for a really obnoxious problem (although one that triggers
> rarely on my hardware).

This one can be cherry-picked fairly easily for 2.6.24. Ivo, any
reason not to do that?

> There are also a bunch of antenna selection fixes that never went
> upstream. These are required for my card to operate well at rates
> greater than 1Mbit, even when fairly close to the AP.

Can you identify specific patches? If so I can evaluate whether they
apply easily to 2.6.24 or if they need significant rework.

Thanks,

John
--
John W. Linville
[email protected]

2008-01-06 22:42:48

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 06/12] rt2x00: Put 802.11 data on 4 byte boundary

Check the size of the ieee80211 header during rxdone
and make sure the data behind the ieee80211 header
is placed on a 4 byte boundary.

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00pci.c | 20 ++++++++++++++++----
drivers/net/wireless/rt2x00/rt2x00usb.c | 17 +++++++++++++++--
2 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 70cb81c..dbc23c4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -129,7 +129,10 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
struct data_entry *entry;
struct sk_buff *skb;
struct skb_desc *skbdesc;
+ struct ieee80211_hdr *hdr;
struct rxdata_entry_desc desc;
+ int header_size;
+ int align;
__le32 *rxd;
u32 word;

@@ -144,17 +147,26 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
memset(&desc, 0, sizeof(desc));
rt2x00dev->ops->lib->fill_rxdone(entry, &desc);

+ hdr = (struct ieee80211_hdr *)entry->data_addr;
+ header_size =
+ ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+
+ /*
+ * The data behind the ieee80211 header must be
+ * aligned on a 4 byte boundary.
+ */
+ align = NET_IP_ALIGN + (2 * (header_size % 4 == 0));
+
/*
* Allocate the sk_buffer, initialize it and copy
* all data into it.
*/
- skb = dev_alloc_skb(desc.size + NET_IP_ALIGN);
+ skb = dev_alloc_skb(desc.size + align);
if (!skb)
return;

- skb_reserve(skb, NET_IP_ALIGN);
- skb_put(skb, desc.size);
- memcpy(skb->data, entry->data_addr, desc.size);
+ skb_reserve(skb, align);
+ memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size);

/*
* Fill in skb descriptor
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 7aba357..8a6218f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -240,7 +240,9 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
struct sk_buff *skb;
struct skb_desc *skbdesc;
+ struct ieee80211_hdr *hdr;
struct rxdata_entry_desc desc;
+ int header_size;
int frame_size;

if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
@@ -272,9 +274,20 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
skb_put(skb, frame_size);

/*
- * Trim the skb_buffer to only contain the valid
- * frame data (so ignore the device's descriptor).
+ * The data behind the ieee80211 header must be
+ * aligned on a 4 byte boundary.
+ * After that trim the entire buffer down to only
+ * contain the valid frame data excluding the device
+ * descriptor.
*/
+ hdr = (struct ieee80211_hdr *)entry->skb->data;
+ header_size =
+ ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+
+ if (header_size % 4 == 0) {
+ skb_push(entry->skb, 2);
+ memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2);
+ }
skb_trim(entry->skb, desc.size);

/*
--
1.5.3.7


2008-01-10 17:29:07

by Ivo Van Doorn

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

Hi,

> > Here is the 2.0.14 release of rt2x00. Again lots of bugfixes,
> > and unfortunately we are still not there yet. I am afraid
> > rt2500usb and rt61pci are lost causes for the 2.6.24 release,
> > they are both broken, and I haven't figured out what is causing
> > this.
>
> Hi Ivo,
>
> Sorry to be out of the loop, but what is wrong with rt61pci? It works
> really really well for me, using John's "everything" branch.

My tests indicate rt61pci is currently not working, I just did some regression
testing and it seems the 2.0.14 version is to blame. I still have to run git-bisect
to determine the exact patch that broke it.

Ivo

2008-01-06 22:42:59

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 11/12] rt2x00: Correctly initialize data and desc pointer

rt2500usb and rt73usb store the descriptor in different
places. This means we should move the initialization of
the 2 pointers to the driver callback function fill_rxdone().

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2500usb.c | 12 ++++++++++++
drivers/net/wireless/rt2x00/rt2x00usb.c | 2 --
drivers/net/wireless/rt2x00/rt73usb.c | 7 +++++++
3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 1b05b8a..2f166c8 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1113,6 +1113,7 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
static void rt2500usb_fill_rxdone(struct data_entry *entry,
struct rxdata_entry_desc *desc)
{
+ struct skb_desc *skbdesc = get_skb_desc(entry->skb);
struct urb *urb = entry->priv;
__le32 *rxd = (__le32 *)(entry->skb->data +
(urb->actual_length - entry->ring->desc_size));
@@ -1137,6 +1138,17 @@ static void rt2500usb_fill_rxdone(struct data_entry *entry,
desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
+
+ /*
+ * Trim the skb to clear the descriptor area.
+ */
+ skb_pull(entry->skb, entry->ring->desc_size);
+
+ /*
+ * Set descriptor and data pointer.
+ */
+ skbdesc->desc = entry->skb->data + skbdesc->data_len;
+ skbdesc->data = entry->skb->data;
}

/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index d15d469..8aab28d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -296,8 +296,6 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
skbdesc = get_skb_desc(entry->skb);
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;

diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 78217dc..47ed307 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1376,6 +1376,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
static void rt73usb_fill_rxdone(struct data_entry *entry,
struct rxdata_entry_desc *desc)
{
+ struct skb_desc *skbdesc = get_skb_desc(entry->skb);
__le32 *rxd = (__le32 *)entry->skb->data;
u32 word0;
u32 word1;
@@ -1400,6 +1401,12 @@ static void rt73usb_fill_rxdone(struct data_entry *entry,
* Pull the skb to clear the descriptor area.
*/
skb_pull(entry->skb, entry->ring->desc_size);
+
+ /*
+ * Set descriptor and data pointer.
+ */
+ skbdesc->desc = entry->skb->data - skbdesc->desc_len;
+ skbdesc->data = entry->skb->data;
}

/*
--
1.5.3.7


2008-01-06 22:42:50

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 07/12] rt2x00: Move packet filter flags

The packet filter flags don't belong in the interface structure
because they are device based instead of interface based.
So move the filter fields out of struct interface and into rt2x00_dev.

Additionally we shouldn't change the filter based on the working
mode, if such a thing is needed than mac80211 should have done that.

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 8 ++------
drivers/net/wireless/rt2x00/rt2500pci.c | 8 ++------
drivers/net/wireless/rt2x00/rt2500usb.c | 8 ++------
drivers/net/wireless/rt2x00/rt2x00.h | 12 +++++++-----
drivers/net/wireless/rt2x00/rt2x00dev.c | 4 ++--
drivers/net/wireless/rt2x00/rt61pci.c | 8 ++------
drivers/net/wireless/rt2x00/rt73usb.c | 8 ++------
7 files changed, 19 insertions(+), 37 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 9eed9e9..b042eb5 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1422,7 +1422,6 @@ static void rt2400pci_configure_filter(struct ieee80211_hw *hw,
struct dev_addr_list *mc_list)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct interface *intf = &rt2x00dev->interface;
u32 reg;

/*
@@ -1441,21 +1440,18 @@ static void rt2400pci_configure_filter(struct ieee80211_hw *hw,
* Apply some rules to the filters:
* - Some filters imply different filters to be set.
* - Some things we can't filter out at all.
- * - Some filters are set based on interface type.
*/
*total_flags |= FIF_ALLMULTI;
if (*total_flags & FIF_OTHER_BSS ||
*total_flags & FIF_PROMISC_IN_BSS)
*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
- if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
- *total_flags |= FIF_PROMISC_IN_BSS;

/*
* Check if there is any work left for us.
*/
- if (intf->filter == *total_flags)
+ if (rt2x00dev->packet_filter == *total_flags)
return;
- intf->filter = *total_flags;
+ rt2x00dev->packet_filter = *total_flags;

/*
* Start configuration steps.
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 8b2f54b..c92163d 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1751,7 +1751,6 @@ static void rt2500pci_configure_filter(struct ieee80211_hw *hw,
struct dev_addr_list *mc_list)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct interface *intf = &rt2x00dev->interface;
u32 reg;

/*
@@ -1770,22 +1769,19 @@ static void rt2500pci_configure_filter(struct ieee80211_hw *hw,
* Apply some rules to the filters:
* - Some filters imply different filters to be set.
* - Some things we can't filter out at all.
- * - Some filters are set based on interface type.
*/
if (mc_count)
*total_flags |= FIF_ALLMULTI;
if (*total_flags & FIF_OTHER_BSS ||
*total_flags & FIF_PROMISC_IN_BSS)
*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
- if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
- *total_flags |= FIF_PROMISC_IN_BSS;

/*
* Check if there is any work left for us.
*/
- if (intf->filter == *total_flags)
+ if (rt2x00dev->packet_filter == *total_flags)
return;
- intf->filter = *total_flags;
+ rt2x00dev->packet_filter = *total_flags;

/*
* Start configuration steps.
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 27d34dd..576f0f8 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1611,7 +1611,6 @@ static void rt2500usb_configure_filter(struct ieee80211_hw *hw,
struct dev_addr_list *mc_list)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct interface *intf = &rt2x00dev->interface;
u16 reg;

/*
@@ -1630,22 +1629,19 @@ static void rt2500usb_configure_filter(struct ieee80211_hw *hw,
* Apply some rules to the filters:
* - Some filters imply different filters to be set.
* - Some things we can't filter out at all.
- * - Some filters are set based on interface type.
*/
if (mc_count)
*total_flags |= FIF_ALLMULTI;
if (*total_flags & FIF_OTHER_BSS ||
*total_flags & FIF_PROMISC_IN_BSS)
*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
- if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
- *total_flags |= FIF_PROMISC_IN_BSS;

/*
* Check if there is any work left for us.
*/
- if (intf->filter == *total_flags)
+ if (rt2x00dev->packet_filter == *total_flags)
return;
- intf->filter = *total_flags;
+ rt2x00dev->packet_filter = *total_flags;

/*
* When in atomic context, reschedule and let rt2x00lib
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index af0bf4b..0dc880c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -388,11 +388,6 @@ struct interface {
* BBSID of the AP to associate with.
*/
u8 bssid[ETH_ALEN];
-
- /*
- * Store the packet filter mode for the current interface.
- */
- unsigned int filter;
};

static inline int is_interface_present(struct interface *intf)
@@ -676,6 +671,13 @@ struct rt2x00_dev {
struct mutex usb_cache_mutex;

/*
+ * Current packet filter configuration for the device.
+ * This contains all currently active FIF_* flags send
+ * to us by mac80211 during configure_filter().
+ */
+ unsigned int packet_filter;
+
+ /*
* Interface configuration.
*/
struct interface interface;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index cea2bd9..911060d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -417,7 +417,7 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work)
{
struct rt2x00_dev *rt2x00dev =
container_of(work, struct rt2x00_dev, filter_work);
- unsigned int filter = rt2x00dev->interface.filter;
+ unsigned int filter = rt2x00dev->packet_filter;

/*
* Since we had stored the filter inside interface.filter,
@@ -425,7 +425,7 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work)
* assume nothing has changed (*total_flags will be compared
* to interface.filter to determine if any action is required).
*/
- rt2x00dev->interface.filter = 0;
+ rt2x00dev->packet_filter = 0;

rt2x00dev->ops->hw->configure_filter(rt2x00dev->hw,
filter, &filter, 0, NULL);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 3bfc5af..34bd90b 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2311,7 +2311,6 @@ static void rt61pci_configure_filter(struct ieee80211_hw *hw,
struct dev_addr_list *mc_list)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct interface *intf = &rt2x00dev->interface;
u32 reg;

/*
@@ -2330,22 +2329,19 @@ static void rt61pci_configure_filter(struct ieee80211_hw *hw,
* Apply some rules to the filters:
* - Some filters imply different filters to be set.
* - Some things we can't filter out at all.
- * - Some filters are set based on interface type.
*/
if (mc_count)
*total_flags |= FIF_ALLMULTI;
if (*total_flags & FIF_OTHER_BSS ||
*total_flags & FIF_PROMISC_IN_BSS)
*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
- if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
- *total_flags |= FIF_PROMISC_IN_BSS;

/*
* Check if there is any work left for us.
*/
- if (intf->filter == *total_flags)
+ if (rt2x00dev->packet_filter == *total_flags)
return;
- intf->filter = *total_flags;
+ rt2x00dev->packet_filter = *total_flags;

/*
* Start configuration steps.
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 9393415..f2d1810 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1846,7 +1846,6 @@ static void rt73usb_configure_filter(struct ieee80211_hw *hw,
struct dev_addr_list *mc_list)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct interface *intf = &rt2x00dev->interface;
u32 reg;

/*
@@ -1865,22 +1864,19 @@ static void rt73usb_configure_filter(struct ieee80211_hw *hw,
* Apply some rules to the filters:
* - Some filters imply different filters to be set.
* - Some things we can't filter out at all.
- * - Some filters are set based on interface type.
*/
if (mc_count)
*total_flags |= FIF_ALLMULTI;
if (*total_flags & FIF_OTHER_BSS ||
*total_flags & FIF_PROMISC_IN_BSS)
*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
- if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
- *total_flags |= FIF_PROMISC_IN_BSS;

/*
* Check if there is any work left for us.
*/
- if (intf->filter == *total_flags)
+ if (rt2x00dev->packet_filter == *total_flags)
return;
- intf->filter = *total_flags;
+ rt2x00dev->packet_filter = *total_flags;

/*
* When in atomic context, reschedule and let rt2x00lib
--
1.5.3.7


2008-01-15 00:44:54

by Will Dyson

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

On Jan 10, 2008 10:46 AM, John W. Linville <[email protected]> wrote:
> On Thu, Jan 10, 2008 at 06:52:40AM -0500, Will Dyson wrote:
> > There are also a bunch of antenna selection fixes that never went
> > upstream. These are required for my card to operate well at rates
> > greater than 1Mbit, even when fairly close to the AP.
>
> Can you identify specific patches? If so I can evaluate whether they
> apply easily to 2.6.24 or if they need significant rework.

rt2x00: Rework rt61 antenna selection
(ca9aaeec2d36dd4a00fea6443c53e935cbfa59ef)

However, it definitely depends on

rt2x00: Split rt61/rt73 antenna selection into RX and TX antenna
(9da4cdaefb5e8e2e3be813d94ce7b401e60ff391)

This patch itself has further dependencies:
[PATCH] rt2x00: Correctly translate mac80211 antenna setup to rt2x00
[PATCH] rt2x00: Move quality statistics into seperate structure).

It looks fairly easy to merge around that last quality statistics
patch. But I am uncertain if it is a good idea. I can try it and post
the result if you are interested.

--
Will Dyson