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(-)
PATCH 1/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.
--- drivers/net/wireless/rt2x00/rt2x00debug.c | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-)
drivers/net/wireless/rt2x00/rt2x00debug.c +2 -3
@@ -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); }
Signature · 1 line
1.5.3.7
PATCH 2/12 rt2x00: Always call ieee80211_stop_queue() when return NETDEV_TX_BUSY
In reply to Ivo van DoornApparently 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.
--- 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(-)
drivers/net/wireless/rt2x00/rt2x00mac.c +13 -4
@@ -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);
drivers/net/wireless/rt2x00/rt2x00pci.c +1 -7
@@ -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);
drivers/net/wireless/rt2x00/rt2x00usb.c +1 -7
@@ -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);
Signature · 1 line
1.5.3.7
PATCH 3/12 rt2x00: Only set the TBCN flag when the interface is configured to send beacons.
In reply to Ivo van DoornThese 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.
--- 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(-)
drivers/net/wireless/rt2x00/rt2400pci.c +1 -1
@@ -280,7 +280,7 @@ static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,*/ rt2x00pci_register_read (rt2x00dev,CSR14 , ®);rt2x00_set_field32 (®,CSR14_TSF_COUNT ,1 ); -rt2x00_set_field32 (®,CSR14_TBCN ,1 ); +rt2x00_set_field32 (®,CSR14_TBCN , (tsf_sync ==TSF_SYNC_BEACON ));rt2x00_set_field32 (®,CSR14_BEACON_GEN ,0 );rt2x00_set_field32 (®,CSR14_TSF_SYNC , tsf_sync);rt2x00pci_register_write (rt2x00dev,CSR14 , reg);
drivers/net/wireless/rt2x00/rt2500pci.c +1 -1
@@ -284,7 +284,7 @@ static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,*/ rt2x00pci_register_read (rt2x00dev,CSR14 , ®);rt2x00_set_field32 (®,CSR14_TSF_COUNT ,1 ); -rt2x00_set_field32 (®,CSR14_TBCN ,1 ); +rt2x00_set_field32 (®,CSR14_TBCN , (tsf_sync ==TSF_SYNC_BEACON ));rt2x00_set_field32 (®,CSR14_BEACON_GEN ,0 );rt2x00_set_field32 (®,CSR14_TSF_SYNC , tsf_sync);rt2x00pci_register_write (rt2x00dev,CSR14 , reg);
drivers/net/wireless/rt2x00/rt2500usb.c +2 -1
@@ -327,7 +327,8 @@ static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,rt2500usb_register_read (rt2x00dev,TXRX_CSR19 , ®);rt2x00_set_field16 (®,TXRX_CSR19_TSF_COUNT ,1 ); -rt2x00_set_field16 (®,TXRX_CSR19_TBCN ,1 ); +rt2x00_set_field16 (®,TXRX_CSR19_TBCN , + (tsf_sync ==TSF_SYNC_BEACON ));rt2x00_set_field16 (®,TXRX_CSR19_BEACON_GEN ,0 );rt2x00_set_field16 (®,TXRX_CSR19_TSF_SYNC , tsf_sync);rt2500usb_register_write (rt2x00dev,TXRX_CSR19 , reg);
drivers/net/wireless/rt2x00/rt61pci.c +2 -1
@@ -317,7 +317,8 @@ static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,*/ rt2x00pci_register_read (rt2x00dev,TXRX_CSR9 , ®);rt2x00_set_field32 (®,TXRX_CSR9_TSF_TICKING ,1 ); -rt2x00_set_field32 (®,TXRX_CSR9_TBTT_ENABLE ,1 ); +rt2x00_set_field32 (®,TXRX_CSR9_TBTT_ENABLE , + (tsf_sync ==TSF_SYNC_BEACON ));rt2x00_set_field32 (®,TXRX_CSR9_BEACON_GEN ,0 );rt2x00_set_field32 (®,TXRX_CSR9_TSF_SYNC , tsf_sync);rt2x00pci_register_write (rt2x00dev,TXRX_CSR9 , reg);
drivers/net/wireless/rt2x00/rt73usb.c +2 -1
@@ -327,7 +327,8 @@ static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,*/ rt73usb_register_read (rt2x00dev,TXRX_CSR9 , ®);rt2x00_set_field32 (®,TXRX_CSR9_TSF_TICKING ,1 ); -rt2x00_set_field32 (®,TXRX_CSR9_TBTT_ENABLE ,1 ); +rt2x00_set_field32 (®,TXRX_CSR9_TBTT_ENABLE , + (tsf_sync ==TSF_SYNC_BEACON ));rt2x00_set_field32 (®,TXRX_CSR9_BEACON_GEN ,0 );rt2x00_set_field32 (®,TXRX_CSR9_TSF_SYNC , tsf_sync);rt73usb_register_write (rt2x00dev,TXRX_CSR9 , reg);
Signature · 1 line
1.5.3.7
PATCH 4/12 rt2x00: Store queue idx and entry idx in data_ring and data_entry
In reply to Ivo van DoornStore 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.
--- 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(-)
drivers/net/wireless/rt2x00/rt2x00.h +0 -6
@@ -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. */
drivers/net/wireless/rt2x00/rt2x00debug.c +2 -6
@@ -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 (×tamp); - 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);
drivers/net/wireless/rt2x00/rt2x00dev.c +4 -0
@@ -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 ;
drivers/net/wireless/rt2x00/rt2x00ring.h +12 -0
@@ -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;
drivers/net/wireless/rt2x00/rt61pci.c +4 -2
@@ -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);
Signature · 1 line
1.5.3.7
PATCH 5/12 rt2x00: Move start() and stop() handlers into rt2x00lib.c
In reply to Ivo van Doornsuspend & 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.
--- 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(-)
drivers/net/wireless/rt2x00/rt2x00dev.c +61 -5
@@ -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
drivers/net/wireless/rt2x00/rt2x00lib.h +2 -2
@@ -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.
drivers/net/wireless/rt2x00/rt2x00mac.c +3 -39
57 lines not on this page · raw message
Signature · 1 line
1.5.3.7
PATCH 6/12 rt2x00: Put 802.11 data on 4 byte boundary
In reply to Ivo van DoornCheck the size of the ieee80211 header during rxdone and make sure the data behind the ieee80211 header is placed on a 4 byte boundary.
--- drivers/net/wireless/rt2x00/rt2x00pci.c | 20 ++++++++++++++++---- drivers/net/wireless/rt2x00/rt2x00usb.c | 17 +++++++++++++++-- 2 files changed, 31 insertions(+), 6 deletions(-)
drivers/net/wireless/rt2x00/rt2x00pci.c +16 -4
@@ -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
drivers/net/wireless/rt2x00/rt2x00usb.c +15 -2
@@ -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);/*
Signature · 1 line
1.5.3.7
PATCH 7/12 rt2x00: Move packet filter flags
In reply to Ivo van DoornThe 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.
--- 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(-)
drivers/net/wireless/rt2x00/rt2400pci.c +2 -6
@@ -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.
drivers/net/wireless/rt2x00/rt2500pci.c +2 -6
@@ -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.
drivers/net/wireless/rt2x00/rt2500usb.c +2 -6
@@ -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
drivers/net/wireless/rt2x00/rt2x00.h +7 -5
@@ -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;
drivers/net/wireless/rt2x00/rt2x00dev.c +2 -2
@@ -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 );
drivers/net/wireless/rt2x00/rt61pci.c +2 -6
@@ -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.
drivers/net/wireless/rt2x00/rt73usb.c +2 -6
@@ -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
Signature · 1 line
1.5.3.7
PATCH 8/12 rt2x00: Cleanup write_tx_desc() arguments
In reply to Ivo van DoornSend 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.
--- 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(-)
drivers/net/wireless/rt2x00/rt2400pci.c +4 -4
@@ -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);
drivers/net/wireless/rt2x00/rt2500pci.c +4 -4
@@ -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); }
drivers/net/wireless/rt2x00/rt2500usb.c +4 -4
@@ -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); }
drivers/net/wireless/rt2x00/rt2x00.h +1 -3
@@ -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,
drivers/net/wireless/rt2x00/rt2x00dev.c +1 -3
@@ -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.
drivers/net/wireless/rt2x00/rt61pci.c +7 -7
@@ -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 );
drivers/net/wireless/rt2x00/rt73usb.c +6 -6
@@ -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 );
Signature · 1 line
1.5.3.7
PATCH 9/12 rt2x00: Determine MY_BSS from descriptor
In reply to Ivo van DoornUse 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.
--- 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(-)
drivers/net/wireless/rt2x00/rt2400pci.c +1 -0
@@ -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 ); }/*
drivers/net/wireless/rt2x00/rt2500pci.c +1 -0
@@ -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 ); }/*
drivers/net/wireless/rt2x00/rt2500usb.c +1 -2
@@ -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 ); }/*
drivers/net/wireless/rt2x00/rt2x00dev.c +5 -13
@@ -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++;
drivers/net/wireless/rt2x00/rt2x00ring.h +1 -0
@@ -59,6 +59,7 @@ struct rxdata_entry_desc {int ofdm;int size;int flags; +int my_bss; };/*
drivers/net/wireless/rt2x00/rt61pci.c +1 -2
@@ -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 ); }/*
drivers/net/wireless/rt2x00/rt73usb.c +1 -2
@@ -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 ; }/*
Signature · 1 line
1.5.3.7
PATCH 10/12 rt2x00: Move init_txring and init_rxring into rt2x00lib
In reply to Ivo van DoornPrior to enabling the radio rt2x00lib should go through all rings and for each entry should call the callback function init_txentry() and init_rxentry().
--- 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(-)
drivers/net/wireless/rt2x00/rt2400pci.c +27 -56
@@ -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 , ®);
@@ -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,
drivers/net/wireless/rt2x00/rt2500pci.c +21 -48
97 lines not on this page · raw message
drivers/net/wireless/rt2x00/rt2500usb.c +2 -2
@@ -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,
drivers/net/wireless/rt2x00/rt2x00.h +8 -0
@@ -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,
drivers/net/wireless/rt2x00/rt2x00dev.c +46 -0
58 lines not on this page · raw message
drivers/net/wireless/rt2x00/rt2x00usb.c +23 -37
72 lines not on this page · raw message
drivers/net/wireless/rt2x00/rt2x00usb.h +4 -1
@@ -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);
drivers/net/wireless/rt2x00/rt61pci.c +30 -58
118 lines not on this page · raw message
drivers/net/wireless/rt2x00/rt73usb.c +2 -2
@@ -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,
Signature · 1 line
1.5.3.7
PATCH 11/12 rt2x00: Correctly initialize data and desc pointer
In reply to Ivo van Doornrt2500usb 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().
--- 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(-)
drivers/net/wireless/rt2x00/rt2500usb.c +12 -0
@@ -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; }/*
drivers/net/wireless/rt2x00/rt2x00usb.c +0 -2
@@ -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;
drivers/net/wireless/rt2x00/rt73usb.c +7 -0
@@ -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; }/*
Signature · 1 line
1.5.3.7
PATCH 12/12 rt2x00: Release rt2x00 2.0.14
In reply to Ivo van Doorn--- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +1 -1
@@ -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"/*
Signature · 1 line
1.5.3.7
Quoted 7 lines · Ivo van Doorn
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.
Signature · 1 line
Will Dyson
Quoted 9 lines · Will Dyson
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?
Quoted 3 lines
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
Signature · 2 lines
John W. Linville [email protected]
Hi,
Quoted 10 lines
Quoted 5 lines
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
Quoted 6 lines · John W. Linville
Quoted 4 lines · Will Dyson
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.
Quoted 8 lines
Quoted 5 lines
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.
Quoted 6 lines
Quoted 3 lines
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
Hi
On Donnerstag, 10. Januar 2008, Will Dyson wrote:
[...]
Quoted 7 lines
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.
Quoted 5 lines
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
Quoted 7 lines
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
Johannes Berg
maintainerRe: [PATCH 06/12] rt2x00: Put 802.11 data on 4 byte boundary
In reply to Ivo van DoornSorry I'm late in noticing this :\
drivers/net/wireless/rt2x00/rt2x00pci.c void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) · line 158
Quoted 5 lines
drivers/net/wireless/rt2x00/rt2x00pci.c +5
-0+/* +* 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
Re: [PATCH 06/12] rt2x00: Put 802.11 data on 4 byte boundary
Hi,
Quoted 11 lines
Sorry I'm late in noticing this :\
drivers/net/wireless/rt2x00/rt2x00pci.c void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) · line 158
Quoted 5 lines
drivers/net/wireless/rt2x00/rt2x00pci.c +5
-0+/* +* 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_ALIGNat all, I think the code should be just
Quoted 3 lines
align = header_size % 4;(which will evaluate to two or four).
Makes sense. I'll fix this asap.
Quoted 4 lines
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_ALIGNis 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
Quoted 7 lines · John W. Linville
Quoted 3 lines · Will Dyson
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.
Signature · 1 line
Will Dyson