rt2x00: Remove usage of deprecated radio_enabled & IEEE80211_CONF_CHANGE_RADIO_ENABLED
PATCH 1/7 rt2x00: Remove usage of deprecated radio_enabled & IEEE80211_CONF_CHANGE_RADIO_ENABLED
In the config() callback function the fields radio_enabled and the change flag IEEE80211_CONF_CHANGE_RADIO_ENABLED have been deprecated. This removes the usage of those fields by improving antenna change detection in the antenna configuration function.
--- drivers/net/wireless/rt2x00/rt2x00config.c | 22 ++++++++--- drivers/net/wireless/rt2x00/rt2x00dev.c | 7 ++++ drivers/net/wireless/rt2x00/rt2x00link.c | 12 ++++-- drivers/net/wireless/rt2x00/rt2x00mac.c | 54 ++++++++++------------------ 4 files changed, 50 insertions(+), 45 deletions(-)
drivers/net/wireless/rt2x00/rt2x00config.c +16 -6
@@ -124,8 +124,9 @@ enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant, }void rt2x00lib_config_antenna (struct rt2x00_dev *rt2x00dev, -struct antenna_setup ant) +struct antenna_setup config) { +struct link_ant *ant = &rt2x00dev->link.ant;struct antenna_setup *def = &rt2x00dev->default_ant;struct antenna_setup *active = &rt2x00dev->link.ant.active;
@@ -134,14 +135,23 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,* ANTENNA_SW_DIVERSITY state to the driver. * If that happens, fallback to hardware defaults, * or our own default. +* If diversity handling is active for a particular antenna, +* we shouldn't overwrite that antenna. * The calls to rt2x00lib_config_antenna_check() * might have caused that we restore back to the already * active setting. If that has happened we can quit. */ - ant.rx =rt2x00lib_config_antenna_check (ant.rx, def->rx); - ant.tx =rt2x00lib_config_antenna_check (ant.tx, def->tx); +if (!(ant->flags &ANTENNA_RX_DIVERSITY )) + config.rx =rt2x00lib_config_antenna_check (config.rx, def->rx); +else + config.rx = active->rx; -if (ant.rx == active->rx && ant.tx == active->tx) +if (!(ant->flags &ANTENNA_TX_DIVERSITY )) + config.tx =rt2x00lib_config_antenna_check (config.tx, def->tx); +else + config.tx = active->tx; + +if (config.rx == active->rx && config.tx == active->tx)return ;/*
@@ -156,11 +166,11 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,* The latter is required since we need to recalibrate the * noise-sensitivity ratio for the new setup. */ - rt2x00dev->ops->lib->config_ant (rt2x00dev, &ant); + rt2x00dev->ops->lib->config_ant (rt2x00dev, &config);rt2x00link_reset_tuner (rt2x00dev, true); -memcpy (active, &ant,sizeof (ant)); +memcpy (active, &config,sizeof (config));if (test_bit (DEVICE_STATE_ENABLED_RADIO , &rt2x00dev->flags))rt2x00lib_toggle_rx (rt2x00dev,STATE_RADIO_RX_ON_LINK );
drivers/net/wireless/rt2x00/rt2x00dev.c +7 -0
@@ -785,6 +785,13 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) rt2x00dev->intf_sta_count =0 ; rt2x00dev->intf_associated =0 ; +/* Enable the radio */ + retval =rt2x00lib_enable_radio (rt2x00dev); +if (retval) { +rt2x00queue_uninitialize (rt2x00dev); +return retval; + } +set_bit (DEVICE_STATE_STARTED , &rt2x00dev->flags);return 0 ;
drivers/net/wireless/rt2x00/rt2x00link.c +8 -4
@@ -219,6 +219,7 @@ static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev)static void rt2x00lib_antenna_diversity (struct rt2x00_dev *rt2x00dev) {struct link_ant *ant = &rt2x00dev->link.ant; +unsigned int flags = ant->flags;/* * Determine if software diversity is enabled for
@@ -226,13 +227,13 @@ static void rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)* Always perform this check since within the link * tuner interval the configuration might have changed. */ - ant->flags &= ~ANTENNA_RX_DIVERSITY ; - ant->flags &= ~ANTENNA_TX_DIVERSITY ; + flags &= ~ANTENNA_RX_DIVERSITY ; + flags &= ~ANTENNA_TX_DIVERSITY ;if (rt2x00dev->default_ant.rx ==ANTENNA_SW_DIVERSITY ) - ant->flags |=ANTENNA_RX_DIVERSITY ; + flags |=ANTENNA_RX_DIVERSITY ;if (rt2x00dev->default_ant.tx ==ANTENNA_SW_DIVERSITY ) - ant->flags |=ANTENNA_TX_DIVERSITY ; + flags |=ANTENNA_TX_DIVERSITY ;if (!(ant->flags &ANTENNA_RX_DIVERSITY ) && !(ant->flags &ANTENNA_TX_DIVERSITY )) {
@@ -240,6 +241,9 @@ static void rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)return ; } +/* Update flags */ + ant->flags = flags; +/* * If we have only sampled the data over the last period * we should now harvest the data. Otherwise just evaluate
drivers/net/wireless/rt2x00/rt2x00mac.c +19 -35
70 lines not on this page · raw message
Signature · 1 line
1.6.3.3
PATCH 2/7 rt2x00: Use IEEE80211_TX_CTL_MORE_FRAMES flag
Check the IEEE80211_TX_CTL_MORE_FRAMES flag to help determining if the DMA queue should be kicked. At the moment this is combined with the ieee80211_has_morefrags() but we might remove that later.
--- drivers/net/wireless/rt2x00/rt2x00queue.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
drivers/net/wireless/rt2x00/rt2x00queue.c +2 -1
@@ -324,7 +324,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,/* * Check if more fragments are pending */ -if (ieee80211_has_morefrags (hdr->frame_control)) { +if (ieee80211_has_morefrags (hdr->frame_control) || + (tx_info->flags &IEEE80211_TX_CTL_MORE_FRAMES )) {__set_bit (ENTRY_TXD_BURST , &txdesc->flags);__set_bit (ENTRY_TXD_MORE_FRAG , &txdesc->flags); }
Signature · 1 line
1.6.3.3
PATCH 3/7 rt2x00: Align ieee80211 header to 4-byte boundary for PCI devices
Some hardware require the ieee80211 header to be aligned to a 4-byte boundary before mapping it to the DMA. Otherwise some frames (like beacons) will not be send out correctly by the device.
--- drivers/net/wireless/rt2x00/rt2x00queue.c | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-)
drivers/net/wireless/rt2x00/rt2x00queue.c +12 -0
@@ -453,9 +453,21 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)rt2x00crypto_tx_remove_iv (skb, &txdesc); } +/* +* When DMA allocation is required we should guarentee to the +* driver that the DMA is aligned to a 4-byte boundary. +* Aligning the header to this boundary can be done by calling +* rt2x00queue_payload_align with the header length of 0. +* However some drivers require L2 padding to pad the payload +* rather then the header. This could be a requirement for +* PCI and USB devices, while header alignment only is valid +* for PCI devices. +*/ if (test_bit (DRIVER_REQUIRE_L2PAD , &queue->rt2x00dev->flags))rt2x00queue_payload_align (entry->skb, true, txdesc.header_length); +else if (test_bit (DRIVER_REQUIRE_DMA , &queue->rt2x00dev->flags)) +rt2x00queue_payload_align (entry->skb, false,0 );/* * It could be possible that the queue was corrupted and this
Signature · 1 line
1.6.3.3
PATCH 4/7 rt2x00: Fix quality houskeeping for software diversity
From: Lars Ericsson <[email protected]>
Antanna quality statistics is not handled correctly, which leads to software diversity being shutdown completly.
The main problem is that during antenna diversity statistics can be reset resulting in loosing the signal strength just before evaluation.
rssi history is not updated correctly leading to incorrect comparison material for basing antenna switching on.
--- drivers/net/wireless/rt2x00/rt2x00.h | 11 ++--- drivers/net/wireless/rt2x00/rt2x00link.c | 77 +++++++++++++----------------- 2 files changed, 38 insertions(+), 50 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +4 -7
@@ -245,14 +245,11 @@ struct link_ant {struct antenna_setup active;/* -* RSSI information for the different antennas. -* These statistics are used to determine when -* to switch antenna when using software diversity. -* -* rssi[0] -> Antenna A RSSI -* rssi[1] -> Antenna B RSSI +* RSSI history information for the antenna. +* Used to determine when to switch antenna +* when using software diversity. */ -int rssi_history[2 ]; +int rssi_history;/* * Current RSSI average of the currently active antenna.
drivers/net/wireless/rt2x00/rt2x00link.c +34 -43
145 lines not on this page · raw message
Signature · 1 line
1.6.3.3
PATCH 5/7 rt2x00: Fix rounding errors in RSSI average calculation
From: Lars Ericsson <[email protected]>
Small changes in signal level was not detected up by the MOVING_AVERAGE() due to a rounding error, using 'int' type.
rt2x00lib_antenna_diversity_eval:
rssi: -62 -62 -62 -62 -62 -62 -62 -62 -62 -62 -62 -62 -62 -62 -62rssi_avg: -57 -57 -57 -57 -57 -57 -57 -57 -57 -57 -57 -57 -57 -57 -57
The signal level reported back could be significantly (5dBm) different from the actual value. A level +3dBm is the same as double the AP output power.
--- drivers/net/wireless/rt2x00/rt2x00.h | 15 ++++++- drivers/net/wireless/rt2x00/rt2x00link.c | 65 ++++++++++++++++++------------ 2 files changed, 52 insertions(+), 28 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +13 -2
@@ -134,6 +134,17 @@ GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) )/* +* Structure for average calculation +* The avg field contains the actual average value, +* but avg_weight is internally used during calculations +* to prevent rounding errors. +*/ +struct avg_val { +int avg; +int avg_weight; +}; + +/* * Chipset identification * The chipset on the device is composed of a RT and RF chip. * The chipset combination is important for determining device capabilities.
@@ -256,7 +267,7 @@ struct link_ant {* Similar to the avg_rssi in the link_qual structure * this value is updated by using the walking average. */ -int rssi_ant; +struct avg_val rssi_ant; };/*
@@ -285,7 +296,7 @@ struct link {/* * Currently active average RSSI value */ -int avg_rssi; +struct avg_val avg_rssi;/* * Currently precalculated percentages of successful
drivers/net/wireless/rt2x00/rt2x00link.c +39 -26
120 lines not on this page · raw message
Signature · 1 line
1.6.3.3
PATCH 6/7 rt2x00: Fix for race condition while update beacon
From: Igor Perminov <[email protected]>
The patch "Implement set_tim callback for all drivers" can cause kernel oops in rt73usb_write_beacon. The oops is caused by one of the following race conditions:
* In case of two near calls to set_tim: rt2x00lib_beacondone_iter is cleaning the beacon skb, whereas rt73usb_write_beacon is still using it.
* In case of two near updates of beacon: first as the result of set_tim and second as the result of a call from an application (e.g. hostapd). This patch fixes the race condition by rearranging the update logic and guarding rt2x00_intf->beacon->skb with a mutex.
--- drivers/net/wireless/rt2x00/rt2x00.h | 5 +++++ drivers/net/wireless/rt2x00/rt2x00dev.c | 7 ------- drivers/net/wireless/rt2x00/rt2x00mac.c | 1 + drivers/net/wireless/rt2x00/rt2x00queue.c | 15 ++++++++++++++- 4 files changed, 20 insertions(+), 8 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +5 -0
@@ -334,6 +334,11 @@ struct rt2x00_intf {u8 bssid[ETH_ALEN ];/* +* beacon->skb must be protected with the mutex. +*/ +struct mutex beacon_skb_mutex; + +/* * Entry in the beacon queue which belongs to * this interface. Each interface has its own * dedicated beacon entry.
drivers/net/wireless/rt2x00/rt2x00dev.c +0 -7
@@ -186,7 +186,6 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work)static void rt2x00lib_beacondone_iter (void *data,u8 *mac,struct ieee80211_vif *vif) { -struct rt2x00_dev *rt2x00dev = data;struct rt2x00_intf *intf =vif_to_intf (vif); if (vif->type != NL80211_IFTYPE_AP &&
@@ -195,12 +194,6 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac, vif->type != NL80211_IFTYPE_WDS)return ; -/* -* Clean up the beacon skb. -*/ -rt2x00queue_free_skb (rt2x00dev, intf->beacon->skb); - intf->beacon->skb =NULL ; -spin_lock (&intf->lock); intf->delayed_flags |=DELAYED_UPDATE_BEACON ;spin_unlock (&intf->lock);
drivers/net/wireless/rt2x00/rt2x00mac.c +1 -0
@@ -274,6 +274,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,spin_lock_init (&intf->lock);spin_lock_init (&intf->seqlock); +mutex_init (&intf->beacon_skb_mutex); intf->beacon = entry;if (conf->type ==NL80211_IFTYPE_AP )
drivers/net/wireless/rt2x00/rt2x00queue.c +14 -1
@@ -503,14 +503,25 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,if (unlikely (!intf->beacon))return -ENOBUFS ; +mutex_lock (&intf->beacon_skb_mutex); + +/* +* Clean up the beacon skb. +*/ +rt2x00queue_free_skb (rt2x00dev, intf->beacon->skb); + intf->beacon->skb =NULL ; +if (!enable_beacon) { rt2x00dev->ops->lib->kill_tx_queue (rt2x00dev,QID_BEACON ); +mutex_unlock (&intf->beacon_skb_mutex);return 0 ; } intf->beacon->skb =ieee80211_beacon_get (rt2x00dev->hw, vif); -if (!intf->beacon->skb) +if (!intf->beacon->skb) { +mutex_unlock (&intf->beacon_skb_mutex);return -ENOMEM ; + }/* * Copy all TX descriptor information into txdesc,
@@ -548,6 +559,8 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, rt2x00dev->ops->lib->write_beacon (intf->beacon); rt2x00dev->ops->lib->kick_tx_queue (rt2x00dev,QID_BEACON ); +mutex_unlock (&intf->beacon_skb_mutex); +return 0 ; }
Signature · 1 line
1.6.3.3
PATCH 7/7 rt2x00: FIF_PSPOLL filter flag support
From: Igor Perminov <[email protected]>
This patch implements FIF_PSPOLL filter flag support in rt2x00 drivers, which has been introduced in mac80211 (see
http://marc.info/?l=linux-wireless&m=124897986330807&w=2).
--- drivers/net/wireless/rt2x00/rt2800usb.c | 9 ++++++++- drivers/net/wireless/rt2x00/rt2x00.h | 2 ++ drivers/net/wireless/rt2x00/rt2x00mac.c | 17 +++++++++++++++++ drivers/net/wireless/rt2x00/rt61pci.c | 8 +++++++- drivers/net/wireless/rt2x00/rt73usb.c | 8 +++++++- 5 files changed, 41 insertions(+), 3 deletions(-)
drivers/net/wireless/rt2x00/rt2800usb.c +8 -1
@@ -518,7 +518,7 @@ static void rt2800usb_config_filter(struct rt2x00_dev *rt2x00dev,rt2x00_set_field32 (®,RX_FILTER_CFG_DROP_RTS , !(filter_flags &FIF_CONTROL ));rt2x00_set_field32 (®,RX_FILTER_CFG_DROP_PSPOLL , - !(filter_flags &FIF_CONTROL )); + !(filter_flags &FIF_PSPOLL ));rt2x00_set_field32 (®,RX_FILTER_CFG_DROP_BA ,1 );rt2x00_set_field32 (®,RX_FILTER_CFG_DROP_BAR ,0 ); rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL,
@@ -2624,6 +2624,13 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)return retval;/* +* This device has multiple filters for control frames +* and has a separate filter for PS Poll frames. +*/ +__set_bit (DRIVER_SUPPORT_CONTROL_FILTERS , &rt2x00dev->flags); +__set_bit (DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL , &rt2x00dev->flags); + +/* * This device requires firmware. */ __set_bit (DRIVER_REQUIRE_FIRMWARE , &rt2x00dev->flags);
drivers/net/wireless/rt2x00/rt2x00.h +2 -0
@@ -624,6 +624,8 @@ enum rt2x00_flags {*/ CONFIG_SUPPORT_HW_BUTTON ,CONFIG_SUPPORT_HW_CRYPTO , +DRIVER_SUPPORT_CONTROL_FILTERS , + DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,/* * Driver configuration
drivers/net/wireless/rt2x00/rt2x00mac.c +17 -0
@@ -392,6 +392,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,FIF_FCSFAIL |FIF_PLCPFAIL |FIF_CONTROL | +FIF_PSPOLL |FIF_OTHER_BSS |FIF_PROMISC_IN_BSS ;
@@ -407,6 +408,22 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, *total_flags |=FIF_PROMISC_IN_BSS |FIF_OTHER_BSS ;/* +* If the device has a single filter for all control frames, +* FIF_CONTROL and FIF_PSPOLL flags imply each other. +* And if the device has more than one filter for control frames +* of different types, but has no a separate filter for PS Poll frames, +* FIF_CONTROL flag implies FIF_PSPOLL. +*/ +if (!test_bit (DRIVER_SUPPORT_CONTROL_FILTERS , &rt2x00dev->flags)) { +if (*total_flags &FIF_CONTROL || *total_flags &FIF_PSPOLL ) + *total_flags |=FIF_CONTROL |FIF_PSPOLL ; + } +if (!test_bit (DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL , &rt2x00dev->flags)) { +if (*total_flags &FIF_CONTROL ) + *total_flags |=FIF_PSPOLL ; + } + +/* * Check if there is any work left for us. */ if (rt2x00dev->packet_filter == *total_flags)
drivers/net/wireless/rt2x00/rt61pci.c +7 -1
@@ -530,7 +530,7 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,rt2x00_set_field32 (®,TXRX_CSR0_DROP_PHYSICAL , !(filter_flags &FIF_PLCPFAIL ));rt2x00_set_field32 (®,TXRX_CSR0_DROP_CONTROL , - !(filter_flags &FIF_CONTROL )); + !(filter_flags & (FIF_CONTROL |FIF_PSPOLL )));rt2x00_set_field32 (®,TXRX_CSR0_DROP_NOT_TO_ME , !(filter_flags &FIF_PROMISC_IN_BSS )); rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS,
@@ -2624,6 +2624,12 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)return retval;/* +* This device has multiple filters for control frames, +* but has no a separate filter for PS Poll frames. +*/ +__set_bit (DRIVER_SUPPORT_CONTROL_FILTERS , &rt2x00dev->flags); + +/* * This device requires firmware and DMA mapped skbs. */ __set_bit (DRIVER_REQUIRE_FIRMWARE , &rt2x00dev->flags);
drivers/net/wireless/rt2x00/rt73usb.c +7 -1
@@ -493,7 +493,7 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,rt2x00_set_field32 (®,TXRX_CSR0_DROP_PHYSICAL , !(filter_flags &FIF_PLCPFAIL ));rt2x00_set_field32 (®,TXRX_CSR0_DROP_CONTROL , - !(filter_flags &FIF_CONTROL )); + !(filter_flags & (FIF_CONTROL |FIF_PSPOLL )));rt2x00_set_field32 (®,TXRX_CSR0_DROP_NOT_TO_ME , !(filter_flags &FIF_PROMISC_IN_BSS )); rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS,
@@ -2144,6 +2144,12 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)return retval;/* +* This device has multiple filters for control frames, +* but has no a separate filter for PS Poll frames. +*/ +__set_bit (DRIVER_SUPPORT_CONTROL_FILTERS , &rt2x00dev->flags); + +/* * This device requires firmware. */ __set_bit (DRIVER_REQUIRE_FIRMWARE , &rt2x00dev->flags);
Signature · 1 line
1.6.3.3