rt2x00: Limit txpower by eeprom values
PATCH 1/17 rt2x00: Limit txpower by eeprom values
From: Helmut Schaa <[email protected]>
Limit the txpower per rate by the approriate values in the eeprom. This avoids too high txpower values resulting in bad tx performance.
--- drivers/net/wireless/rt2x00/rt2800.h | 20 ++++- drivers/net/wireless/rt2x00/rt2800lib.c | 153 ++++++++++++++++++++----------- 2 files changed, 120 insertions(+), 53 deletions(-)
drivers/net/wireless/rt2x00/rt2800.h +19 -1
@@ -803,6 +803,18 @@#define EDCA_TID_AC_MAP 0x1310/* +* TX_PWR_CFG: +*/ +#define TX_PWR_CFG_RATE0 FIELD32(0x0000000f) +#define TX_PWR_CFG_RATE1 FIELD32(0x000000f0) +#define TX_PWR_CFG_RATE2 FIELD32(0x00000f00) +#define TX_PWR_CFG_RATE3 FIELD32(0x0000f000) +#define TX_PWR_CFG_RATE4 FIELD32(0x000f0000) +#define TX_PWR_CFG_RATE5 FIELD32(0x00f00000) +#define TX_PWR_CFG_RATE6 FIELD32(0x0f000000) +#define TX_PWR_CFG_RATE7 FIELD32(0xf0000000) + +/* * TX_PWR_CFG_0: */ #define TX_PWR_CFG_0 0x1314
@@ -1853,9 +1865,15 @@ struct mac_iveiv_entry {#define EEPROM_TXPOWER_A_2 FIELD16(0xff00)/* -* EEPROM TXpower byrate: 20MHZ power +* EEPROM TXPOWER by rate: tx power per tx rate for HT20 mode */ #define EEPROM_TXPOWER_BYRATE 0x006f +#define EEPROM_TXPOWER_BYRATE_SIZE 9 + +#define EEPROM_TXPOWER_BYRATE_RATE0 FIELD16(0x000f) +#define EEPROM_TXPOWER_BYRATE_RATE1 FIELD16(0x00f0) +#define EEPROM_TXPOWER_BYRATE_RATE2 FIELD16(0x0f00) +#define EEPROM_TXPOWER_BYRATE_RATE3 FIELD16(0xf000)/* * EEPROM BBP.
drivers/net/wireless/rt2x00/rt2800lib.c +101 -52
167 lines not on this page · raw message
Signature · 1 line
1.7.1.1
PATCH 2/17 rt2x00: Convert AGC value from descriptor to RSSI (dBm)
The RSSI values in the RXWI descriptor aren't true RSSI values. Instead they are more like the AGC values similar to rt61pci. And as such, it needs the same conversion before it can be passed to rt2x00lib/mac80211.
This requires the struct queue_entry to be passed to rt2800_process_rxwi rather then the skb structure which is contained in the queue_entry. This is required to obtain the lna_gain information from the rt2x00_dev structure.
This fixes connection problems when using wpa_supplicant which would try to connect to the worst AP's rather then the best ones.
--- drivers/net/wireless/rt2x00/rt2800.h | 2 +- drivers/net/wireless/rt2x00/rt2800lib.c | 57 +++++++++++++++++++++++++++--- drivers/net/wireless/rt2x00/rt2800lib.h | 2 +- drivers/net/wireless/rt2x00/rt2800pci.c | 2 +- drivers/net/wireless/rt2x00/rt2800usb.c | 2 +- 5 files changed, 55 insertions(+), 10 deletions(-)
drivers/net/wireless/rt2x00/rt2800.h +1 -1
@@ -74,7 +74,7 @@* Signal information. * Default offset is required for RSSI <-> dBm conversion. */ -#define DEFAULT_RSSI_OFFSET 120/* FIXME */ +#define DEFAULT_RSSI_OFFSET 120/* * Register layout information.
drivers/net/wireless/rt2x00/rt2800lib.c +51 -6
74 lines not on this page · raw message
drivers/net/wireless/rt2x00/rt2800lib.h +1 -1
@@ -121,7 +121,7 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, const u8 arg0, const u8 arg1);void rt2800_write_txwi (__le32 *txwi,struct txentry_desc *txdesc); -void rt2800_process_rxwi (struct sk_buff *skb,struct rxdone_entry_desc *txdesc); +void rt2800_process_rxwi (struct queue_entry *entry,struct rxdone_entry_desc *txdesc);void rt2800_write_beacon (struct queue_entry *entry,struct txentry_desc *txdesc);
drivers/net/wireless/rt2x00/rt2800pci.c +1 -1
@@ -805,7 +805,7 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,/* * Process the RXWI structure that is at the start of the buffer. */ -rt2800_process_rxwi (entry->skb, rxdesc); +rt2800_process_rxwi (entry, rxdesc);/* * Set RX IDX in register to inform hardware that we have handled
drivers/net/wireless/rt2x00/rt2800usb.c +1 -1
@@ -563,7 +563,7 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,/* * Process the RXWI structure. */ -rt2800_process_rxwi (entry->skb, rxdesc); +rt2800_process_rxwi (entry, rxdesc); }/*
Signature · 1 line
1.7.1.1
PATCH 3/17 rt2x00: Rename CONFIG_DISABLE_LINK_TUNING
Rename CONFIG_DISABLE_LINK_TUNING to DRIVER_SUPPORT_LINK_TUNING Link tuning support is not only based on EEPROM decisions, but also if the device actually supports it.
Currently only rt2500usb doesn't support link tuning because of hardware problems. But rt2800usb is also suspected of having problems with link tuning.
--- drivers/net/wireless/rt2x00/rt2400pci.c | 4 ++-- drivers/net/wireless/rt2x00/rt2500pci.c | 5 ++--- drivers/net/wireless/rt2x00/rt2500usb.c | 8 -------- drivers/net/wireless/rt2x00/rt2800pci.c | 1 + drivers/net/wireless/rt2x00/rt2800usb.c | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 2 +- drivers/net/wireless/rt2x00/rt2x00link.c | 7 ++++--- drivers/net/wireless/rt2x00/rt61pci.c | 1 + drivers/net/wireless/rt2x00/rt73usb.c | 1 + 9 files changed, 13 insertions(+), 17 deletions(-)
drivers/net/wireless/rt2x00/rt2400pci.c +2 -2
@@ -1399,8 +1399,8 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)/* * Check if the BBP tuning should be enabled. */ -if (!rt2x00_get_field16 (eeprom,EEPROM_ANTENNA_RX_AGCVGC_TUNING )) -__set_bit (CONFIG_DISABLE_LINK_TUNING , &rt2x00dev->flags); +if (rt2x00_get_field16 (eeprom,EEPROM_ANTENNA_RX_AGCVGC_TUNING )) +__set_bit (DRIVER_SUPPORT_LINK_TUNING , &rt2x00dev->flags);return 0 ; }
drivers/net/wireless/rt2x00/rt2500pci.c +2 -3
@@ -1557,9 +1557,8 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)* Check if the BBP tuning should be enabled. */ rt2x00_eeprom_read (rt2x00dev,EEPROM_NIC , &eeprom); - -if (rt2x00_get_field16 (eeprom,EEPROM_NIC_DYN_BBP_TUNE )) -__set_bit (CONFIG_DISABLE_LINK_TUNING , &rt2x00dev->flags); +if (!rt2x00_get_field16 (eeprom,EEPROM_NIC_DYN_BBP_TUNE )) +__set_bit (DRIVER_SUPPORT_LINK_TUNING , &rt2x00dev->flags);/* * Read the RSSI <-> dBm offset information.
drivers/net/wireless/rt2x00/rt2500usb.c +0 -8
@@ -1471,13 +1471,6 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)__set_bit (CONFIG_SUPPORT_HW_BUTTON , &rt2x00dev->flags);/* -* Check if the BBP tuning should be disabled. -*/ -rt2x00_eeprom_read (rt2x00dev,EEPROM_NIC , &eeprom); -if (rt2x00_get_field16 (eeprom,EEPROM_NIC_DYN_BBP_TUNE )) -__set_bit (CONFIG_DISABLE_LINK_TUNING , &rt2x00dev->flags); - -/* * Read the RSSI <-> dBm offset information. */ rt2x00_eeprom_read (rt2x00dev,EEPROM_CALIBRATE_OFFSET , &eeprom);
@@ -1743,7 +1736,6 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)__set_bit (CONFIG_SUPPORT_HW_CRYPTO , &rt2x00dev->flags);__set_bit (DRIVER_REQUIRE_COPY_IV , &rt2x00dev->flags); } -__set_bit (CONFIG_DISABLE_LINK_TUNING , &rt2x00dev->flags);/* * Set the rssi offset.
drivers/net/wireless/rt2x00/rt2800pci.c +1 -0
@@ -1037,6 +1037,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)__set_bit (DRIVER_REQUIRE_L2PAD , &rt2x00dev->flags);if (!modparam_nohwcrypt)__set_bit (CONFIG_SUPPORT_HW_CRYPTO , &rt2x00dev->flags); +__set_bit (DRIVER_SUPPORT_LINK_TUNING , &rt2x00dev->flags);/* * Set the rssi offset.
drivers/net/wireless/rt2x00/rt2800usb.c +1 -0
@@ -632,6 +632,7 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)__set_bit (DRIVER_REQUIRE_L2PAD , &rt2x00dev->flags);if (!modparam_nohwcrypt)__set_bit (CONFIG_SUPPORT_HW_CRYPTO , &rt2x00dev->flags); +__set_bit (DRIVER_SUPPORT_LINK_TUNING , &rt2x00dev->flags);/* * Set the rssi offset.
drivers/net/wireless/rt2x00/rt2x00.h +1 -1
@@ -646,6 +646,7 @@ enum rt2x00_flags {CONFIG_SUPPORT_HW_CRYPTO ,DRIVER_SUPPORT_CONTROL_FILTERS ,DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL , + DRIVER_SUPPORT_LINK_TUNING,/* * Driver configuration
@@ -655,7 +656,6 @@ enum rt2x00_flags {CONFIG_EXTERNAL_LNA_A ,CONFIG_EXTERNAL_LNA_BG ,CONFIG_DOUBLE_ANTENNA , -CONFIG_DISABLE_LINK_TUNING , CONFIG_CHANNEL_HT40, };
drivers/net/wireless/rt2x00/rt2x00link.c +4 -3
@@ -359,10 +359,11 @@ static void rt2x00link_tuner(struct work_struct *work) qual->rssi = link->avg_rssi.avg;/* -* Only perform the link tuning when Link tuning -* has been enabled (This could have been disabled from the EEPROM). +* Check if link tuning is supported by the hardware, some hardware +* do not support link tuning at all, while other devices can disable +* the feature from the EEPROM. */ -if (!test_bit (CONFIG_DISABLE_LINK_TUNING , &rt2x00dev->flags)) +if (test_bit (DRIVER_SUPPORT_LINK_TUNING , &rt2x00dev->flags)) rt2x00dev->ops->lib->link_tuner (rt2x00dev, qual, link->count);/*
drivers/net/wireless/rt2x00/rt61pci.c +1 -0
@@ -2690,6 +2690,7 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)__set_bit (DRIVER_REQUIRE_DMA , &rt2x00dev->flags);if (!modparam_nohwcrypt)__set_bit (CONFIG_SUPPORT_HW_CRYPTO , &rt2x00dev->flags); +__set_bit (DRIVER_SUPPORT_LINK_TUNING , &rt2x00dev->flags);/* * Set the rssi offset.
drivers/net/wireless/rt2x00/rt73usb.c +1 -0
@@ -2135,6 +2135,7 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)__set_bit (DRIVER_REQUIRE_FIRMWARE , &rt2x00dev->flags);if (!modparam_nohwcrypt)__set_bit (CONFIG_SUPPORT_HW_CRYPTO , &rt2x00dev->flags); +__set_bit (DRIVER_SUPPORT_LINK_TUNING , &rt2x00dev->flags);/* * Set the rssi offset.
Signature · 1 line
1.7.1.1
PATCH 4/17 rt2x00: Disable link tuning while scanning
While scanning the link tuner must be disabled. Otherwise it will interfere with receiving all beacons for each channel due to changing sensitivity levels.
--- drivers/net/wireless/rt2x00/rt2400pci.c | 2 ++ drivers/net/wireless/rt2x00/rt2500pci.c | 2 ++ drivers/net/wireless/rt2x00/rt2500usb.c | 2 ++ drivers/net/wireless/rt2x00/rt2800lib.c | 2 ++ drivers/net/wireless/rt2x00/rt2x00.h | 3 +++ drivers/net/wireless/rt2x00/rt2x00link.c | 12 +++++++++++- drivers/net/wireless/rt2x00/rt2x00mac.c | 24 +++++++++++++++++++++--- drivers/net/wireless/rt2x00/rt61pci.c | 2 ++ drivers/net/wireless/rt2x00/rt73usb.c | 2 ++ 9 files changed, 47 insertions(+), 4 deletions(-)
drivers/net/wireless/rt2x00/rt2400pci.c +2 -0
@@ -1567,6 +1567,8 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .config = rt2x00mac_config, .configure_filter = rt2x00mac_configure_filter, .set_tim = rt2x00mac_set_tim, + .sw_scan_start = rt2x00mac_sw_scan_start, + .sw_scan_complete = rt2x00mac_sw_scan_complete, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2400pci_conf_tx,
drivers/net/wireless/rt2x00/rt2500pci.c +2 -0
@@ -1864,6 +1864,8 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .config = rt2x00mac_config, .configure_filter = rt2x00mac_configure_filter, .set_tim = rt2x00mac_set_tim, + .sw_scan_start = rt2x00mac_sw_scan_start, + .sw_scan_complete = rt2x00mac_sw_scan_complete, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx,
drivers/net/wireless/rt2x00/rt2500usb.c +2 -0
@@ -1755,6 +1755,8 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .configure_filter = rt2x00mac_configure_filter, .set_tim = rt2x00mac_set_tim, .set_key = rt2x00mac_set_key, + .sw_scan_start = rt2x00mac_sw_scan_start, + .sw_scan_complete = rt2x00mac_sw_scan_complete, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx,
drivers/net/wireless/rt2x00/rt2800lib.c +2 -0
@@ -2896,6 +2896,8 @@ const struct ieee80211_ops rt2800_mac80211_ops = { .configure_filter = rt2x00mac_configure_filter, .set_tim = rt2x00mac_set_tim, .set_key = rt2x00mac_set_key, + .sw_scan_start = rt2x00mac_sw_scan_start, + .sw_scan_complete = rt2x00mac_sw_scan_complete, .get_stats = rt2x00mac_get_stats, .get_tkip_seq = rt2800_get_tkip_seq, .set_rts_threshold = rt2800_set_rts_threshold,
drivers/net/wireless/rt2x00/rt2x00.h +3 -0
@@ -628,6 +628,7 @@ enum rt2x00_flags {DEVICE_STATE_INITIALIZED ,DEVICE_STATE_STARTED ,DEVICE_STATE_ENABLED_RADIO , + DEVICE_STATE_SCANNING,/* * Driver requirements
@@ -1081,6 +1082,8 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,#else #define rt2x00mac_set_key NULL#endif /* CONFIG_RT2X00_LIB_CRYPTO */ +void rt2x00mac_sw_scan_start (struct ieee80211_hw *hw); +void rt2x00mac_sw_scan_complete (struct ieee80211_hw *hw);int rt2x00mac_get_stats (struct ieee80211_hw *hw,struct ieee80211_low_level_stats *stats); void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
drivers/net/wireless/rt2x00/rt2x00link.c +11 -1
@@ -278,6 +278,15 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)if (!rt2x00dev->intf_sta_count)return ; +/** +* While scanning, link tuning is disabled. By default +* the most sensitive settings will be used to make sure +* that all beacons and probe responses will be recieved +* during the scan. +*/ +if (test_bit (DEVICE_STATE_SCANNING , &rt2x00dev->flags)) +return ; +rt2x00link_reset_tuner (rt2x00dev, false);if (test_bit (DEVICE_STATE_PRESENT , &rt2x00dev->flags))
@@ -338,7 +347,8 @@ static void rt2x00link_tuner(struct work_struct *work)* When the radio is shutting down we should * immediately cease all link tuning. */ -if (!test_bit (DEVICE_STATE_ENABLED_RADIO , &rt2x00dev->flags)) +if (!test_bit (DEVICE_STATE_ENABLED_RADIO , &rt2x00dev->flags) || +test_bit (DEVICE_STATE_SCANNING , &rt2x00dev->flags))return ;/*
drivers/net/wireless/rt2x00/rt2x00mac.c +21 -3
@@ -347,9 +347,11 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)/* * Some configuration parameters (e.g. channel and antenna values) can * only be set when the radio is enabled, but do require the RX to -* be off. +* be off. During this period we should keep link tuning enabled, +* if for any reason the link tuner must be reset, this will be +* handled by rt2x00lib_config(). */ -rt2x00lib_toggle_rx (rt2x00dev,STATE_RADIO_RX_OFF ); +rt2x00lib_toggle_rx (rt2x00dev,STATE_RADIO_RX_OFF_LINK );/* * When we've just turned on the radio, we want to reprogram
@@ -367,7 +369,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)rt2x00lib_config_antenna (rt2x00dev, rt2x00dev->default_ant);/* Turn RX back on */ -rt2x00lib_toggle_rx (rt2x00dev,STATE_RADIO_RX_ON ); +rt2x00lib_toggle_rx (rt2x00dev,STATE_RADIO_RX_ON_LINK );return 0 ; }
@@ -540,6 +542,22 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,EXPORT_SYMBOL_GPL (rt2x00mac_set_key);#endif /* CONFIG_RT2X00_LIB_CRYPTO */ +void rt2x00mac_sw_scan_start (struct ieee80211_hw *hw) +{ +struct rt2x00_dev *rt2x00dev = hw->priv; +__set_bit (DEVICE_STATE_SCANNING , &rt2x00dev->flags); +rt2x00link_stop_tuner (rt2x00dev); +} +EXPORT_SYMBOL_GPL (rt2x00mac_sw_scan_start); + +void rt2x00mac_sw_scan_complete (struct ieee80211_hw *hw) +{ +struct rt2x00_dev *rt2x00dev = hw->priv; +__clear_bit (DEVICE_STATE_SCANNING , &rt2x00dev->flags); +rt2x00link_start_tuner (rt2x00dev); +} +EXPORT_SYMBOL_GPL (rt2x00mac_sw_scan_complete); +int rt2x00mac_get_stats (struct ieee80211_hw *hw,struct ieee80211_low_level_stats *stats) {
drivers/net/wireless/rt2x00/rt61pci.c +2 -0
@@ -2784,6 +2784,8 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .configure_filter = rt2x00mac_configure_filter, .set_tim = rt2x00mac_set_tim, .set_key = rt2x00mac_set_key, + .sw_scan_start = rt2x00mac_sw_scan_start, + .sw_scan_complete = rt2x00mac_sw_scan_complete, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt61pci_conf_tx,
drivers/net/wireless/rt2x00/rt73usb.c +2 -0
@@ -2229,6 +2229,8 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .configure_filter = rt2x00mac_configure_filter, .set_tim = rt2x00mac_set_tim, .set_key = rt2x00mac_set_key, + .sw_scan_start = rt2x00mac_sw_scan_start, + .sw_scan_complete = rt2x00mac_sw_scan_complete, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt73usb_conf_tx,
Signature · 1 line
1.7.1.1
PATCH 5/17 rt2x00: Fix vgc_level_reg handling
Currently vgc_level_reg and vgc_level are equal to eachother, while the purpose of vgc_level_reg is the value last written to the register and is remembered through link tuning resets. The vgc_level is the currently active level, which is reset during link tuning resets.
The usage of these variables depends on the drivers, some drivers need both, while others need only one of the two.
--- drivers/net/wireless/rt2x00/rt2400pci.c | 8 +++++--- drivers/net/wireless/rt2x00/rt2500pci.c | 8 +++----- drivers/net/wireless/rt2x00/rt2x00link.c | 8 ++++++++ 3 files changed, 16 insertions(+), 8 deletions(-)
drivers/net/wireless/rt2x00/rt2400pci.c +5 -3
@@ -586,9 +586,11 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,static inline void rt2400pci_set_vgc (struct rt2x00_dev *rt2x00dev,struct link_qual *qual,u8 vgc_level) { -rt2400pci_bbp_write (rt2x00dev,13 , vgc_level); - qual->vgc_level = vgc_level; - qual->vgc_level_reg = vgc_level; +if (qual->vgc_level_reg != vgc_level) { +rt2400pci_bbp_write (rt2x00dev,13 , vgc_level); + qual->vgc_level = vgc_level; + qual->vgc_level_reg = vgc_level; + } } static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
drivers/net/wireless/rt2x00/rt2500pci.c +3 -5
@@ -626,6 +626,7 @@ static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev, {if (qual->vgc_level_reg != vgc_level) {rt2500pci_bbp_write (rt2x00dev,17 , vgc_level); + qual->vgc_level = vgc_level; qual->vgc_level_reg = vgc_level; } }
@@ -700,13 +701,10 @@ dynamic_cca_tune:* R17 is inside the dynamic tuning range, * start tuning the link based on the false cca counter. */ -if (qual->false_cca >512 && qual->vgc_level_reg <0x40 ) { +if (qual->false_cca >512 && qual->vgc_level_reg <0x40 )rt2500pci_set_vgc (rt2x00dev, qual, ++qual->vgc_level_reg); - qual->vgc_level = qual->vgc_level_reg; - }else if (qual->false_cca <100 && qual->vgc_level_reg >0x32 ) { +else if (qual->false_cca <100 && qual->vgc_level_reg >0x32 )rt2500pci_set_vgc (rt2x00dev, qual, --qual->vgc_level_reg); - qual->vgc_level = qual->vgc_level_reg; - } }/*
drivers/net/wireless/rt2x00/rt2x00link.c +8 -0
@@ -302,6 +302,7 @@ void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev)void rt2x00link_reset_tuner (struct rt2x00_dev *rt2x00dev,bool antenna) {struct link_qual *qual = &rt2x00dev->link.qual; +u8 vgc_level = qual->vgc_level_reg;if (!test_bit (DEVICE_STATE_ENABLED_RADIO , &rt2x00dev->flags))return ;
@@ -318,6 +319,13 @@ void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna)memset (qual,0 ,sizeof (*qual));/* +* Restore the VGC level as stored in the registers, +* the driver can use this to determine if the register +* must be updated during reset or not. +*/ + qual->vgc_level_reg = vgc_level; + +/* * Reset the link tuner. */ rt2x00dev->ops->lib->reset_tuner (rt2x00dev, qual);
Signature · 1 line
1.7.1.1
PATCH 6/17 rt2x00: Implement watchdog monitoring
Implement watchdog monitoring for USB devices (PCI support can be added later). This will determine if URBs being uploaded to the hardware are actually returning. Both rt2500usb and rt2800usb have shown that URBs being uploaded can remain hanging without being released by the hardware.
By using this watchdog, a queue can be reset when this occurs. For rt2800usb it has been tested that the connection is preserved even though this interruption.
--- drivers/net/wireless/rt2x00/rt2500usb.c | 2 + drivers/net/wireless/rt2x00/rt2800usb.c | 2 + drivers/net/wireless/rt2x00/rt2x00.h | 7 ++++ drivers/net/wireless/rt2x00/rt2x00dev.c | 10 ++++++ drivers/net/wireless/rt2x00/rt2x00lib.h | 26 +++++++++++++-- drivers/net/wireless/rt2x00/rt2x00link.c | 38 ++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00queue.c | 4 ++ drivers/net/wireless/rt2x00/rt2x00queue.h | 11 ++++++ drivers/net/wireless/rt2x00/rt2x00usb.c | 50 +++++++++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00usb.h | 10 ++++++ drivers/net/wireless/rt2x00/rt73usb.c | 2 + 11 files changed, 159 insertions(+), 3 deletions(-)
drivers/net/wireless/rt2x00/rt2500usb.c +2 -0
@@ -1736,6 +1736,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)__set_bit (CONFIG_SUPPORT_HW_CRYPTO , &rt2x00dev->flags);__set_bit (DRIVER_REQUIRE_COPY_IV , &rt2x00dev->flags); } +__set_bit (DRIVER_SUPPORT_WATCHDOG , &rt2x00dev->flags);/* * Set the rssi offset.
@@ -1772,6 +1773,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .rfkill_poll = rt2500usb_rfkill_poll, .link_stats = rt2500usb_link_stats, .reset_tuner = rt2500usb_reset_tuner, + .watchdog = rt2x00usb_watchdog, .write_tx_desc = rt2500usb_write_tx_desc, .write_beacon = rt2500usb_write_beacon, .get_tx_data_len = rt2500usb_get_tx_data_len,
drivers/net/wireless/rt2x00/rt2800usb.c +2 -0
@@ -633,6 +633,7 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)if (!modparam_nohwcrypt)__set_bit (CONFIG_SUPPORT_HW_CRYPTO , &rt2x00dev->flags);__set_bit (DRIVER_SUPPORT_LINK_TUNING , &rt2x00dev->flags); +__set_bit (DRIVER_SUPPORT_WATCHDOG , &rt2x00dev->flags);/* * Set the rssi offset.
@@ -655,6 +656,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .link_stats = rt2800_link_stats, .reset_tuner = rt2800_reset_tuner, .link_tuner = rt2800_link_tuner, + .watchdog = rt2x00usb_watchdog, .write_tx_desc = rt2800usb_write_tx_desc, .write_tx_data = rt2800usb_write_tx_data, .write_beacon = rt2800_write_beacon,
drivers/net/wireless/rt2x00/rt2x00.h +7 -0
@@ -332,6 +332,11 @@ struct link {* Work structure for scheduling periodic link tuning. */ struct delayed_work work; + +/* +* Work structure for scheduling periodic watchdog monitoring. +*/ +struct delayed_work watchdog_work; };/*
@@ -543,6 +548,7 @@ struct rt2x00lib_ops { struct link_qual *qual);void (*link_tuner) (struct rt2x00_dev *rt2x00dev,struct link_qual *qual,const u32 count); +void (*watchdog) (struct rt2x00_dev *rt2x00dev);/* * TX control handlers
@@ -648,6 +654,7 @@ enum rt2x00_flags {DRIVER_SUPPORT_CONTROL_FILTERS ,DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL ,DRIVER_SUPPORT_LINK_TUNING , + DRIVER_SUPPORT_WATCHDOG,/* * Driver configuration
drivers/net/wireless/rt2x00/rt2x00dev.c +10 -0
@@ -70,6 +70,11 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)rt2x00lib_toggle_rx (rt2x00dev,STATE_RADIO_RX_ON );/* +* Start watchdog monitoring. +*/ +rt2x00link_start_watchdog (rt2x00dev); + +/* * Start the TX queues. */ ieee80211_wake_queues (rt2x00dev->hw);
@@ -89,6 +94,11 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)rt2x00queue_stop_queues (rt2x00dev);/* +* Stop watchdog monitoring. +*/ +rt2x00link_stop_watchdog (rt2x00dev); + +/* * Disable RX. */ rt2x00lib_toggle_rx (rt2x00dev,STATE_RADIO_RX_OFF );
drivers/net/wireless/rt2x00/rt2x00lib.h +23 -3
@@ -30,6 +30,7 @@/* * Interval defines */ +#define WATCHDOG_INTERVAL round_jiffies_relative(HZ)#define LINK_TUNE_INTERVAL round_jiffies_relative(HZ)/*
@@ -257,11 +258,30 @@ void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev);void rt2x00link_reset_tuner (struct rt2x00_dev *rt2x00dev,bool antenna);/** -* rt2x00link_register - Initialize link tuning functionality +* rt2x00link_start_watchdog - Start periodic watchdog monitoring * @rt2x00dev: Pointer to &struct rt2x00_dev. * -* Initialize work structure and all link tuning related -* parameters. This will not start the link tuning process itself. +* This start the watchdog periodic work, this work will +*be executed periodically until &rt2x00link_stop_watchdog has +* been called. +*/ +void rt2x00link_start_watchdog (struct rt2x00_dev *rt2x00dev); + +/** +* rt2x00link_stop_watchdog - Stop periodic watchdog monitoring +* @rt2x00dev: Pointer to &struct rt2x00_dev. +* +* After this function completed the watchdog monitoring will not +* be running until &rt2x00link_start_watchdog is called. +*/ +void rt2x00link_stop_watchdog (struct rt2x00_dev *rt2x00dev); + +/** +* rt2x00link_register - Initialize link tuning & watchdog functionality +* @rt2x00dev: Pointer to &struct rt2x00_dev. +* +* Initialize work structure and all link tuning and watchdog related +* parameters. This will not start the periodic work itself. */ void rt2x00link_register (struct rt2x00_dev *rt2x00dev);
drivers/net/wireless/rt2x00/rt2x00link.c +38 -0
@@ -407,7 +407,45 @@ static void rt2x00link_tuner(struct work_struct *work) &link->work, LINK_TUNE_INTERVAL); } +void rt2x00link_start_watchdog (struct rt2x00_dev *rt2x00dev) +{ +struct link *link = &rt2x00dev->link; + +if (!test_bit (DEVICE_STATE_PRESENT , &rt2x00dev->flags) || + !test_bit (DRIVER_SUPPORT_WATCHDOG , &rt2x00dev->flags)) +return ; + +ieee80211_queue_delayed_work (rt2x00dev->hw, + &link->watchdog_work,WATCHDOG_INTERVAL ); +} + +void rt2x00link_stop_watchdog (struct rt2x00_dev *rt2x00dev) +{ +cancel_delayed_work_sync (&rt2x00dev->link.watchdog_work); +} + +static void rt2x00link_watchdog (struct work_struct *work) +{ +struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, link.watchdog_work.work); +struct link *link = &rt2x00dev->link; + +/* +* When the radio is shutting down we should +* immediately cease the watchdog monitoring. +*/ +if (!test_bit (DEVICE_STATE_ENABLED_RADIO , &rt2x00dev->flags)) +return ; + + rt2x00dev->ops->lib->watchdog (rt2x00dev); + +if (test_bit (DEVICE_STATE_PRESENT , &rt2x00dev->flags)) +ieee80211_queue_delayed_work (rt2x00dev->hw, + &link->watchdog_work,WATCHDOG_INTERVAL ); +} +void rt2x00link_register (struct rt2x00_dev *rt2x00dev) { +INIT_DELAYED_WORK (&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);INIT_DELAYED_WORK (&rt2x00dev->link.work, rt2x00link_tuner); }
drivers/net/wireless/rt2x00/rt2x00queue.c +4 -0
@@ -688,9 +688,11 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)if (index ==Q_INDEX ) { queue->length++; + queue->last_index = jiffies; }else if (index ==Q_INDEX_DONE ) { queue->length--; queue->count++; + queue->last_index_done = jiffies; }spin_unlock_irqrestore (&queue->lock, irqflags);
@@ -704,6 +706,8 @@ static void rt2x00queue_reset(struct data_queue *queue) queue->count =0 ; queue->length =0 ; + queue->last_index = jiffies; + queue->last_index_done = jiffies;memset (queue->index,0 ,sizeof (queue->index));spin_unlock_irqrestore (&queue->lock, irqflags);
drivers/net/wireless/rt2x00/rt2x00queue.h +11 -0
@@ -446,6 +446,8 @@ struct data_queue {enum data_queue_qid qid;spinlock_t lock; +unsigned long last_index; +unsigned long last_index_done;unsigned int count;unsigned short limit;unsigned short threshold;
@@ -599,6 +601,15 @@ static inline int rt2x00queue_threshold(struct data_queue *queue) }/** +* rt2x00queue_timeout - Check if a timeout occured for this queue +* @queue: Queue to check. +*/ +static inline int rt2x00queue_timeout (struct data_queue *queue) +{ +return time_after (queue->last_index, queue->last_index_done + (HZ /10 )); +} + +/** * _rt2x00_desc_read - Read a word from the hardware descriptor. * @desc: Base descriptor address * @word: Word index from where the descriptor should be read.
drivers/net/wireless/rt2x00/rt2x00usb.c +50 -0
56 lines not on this page · raw message
drivers/net/wireless/rt2x00/rt2x00usb.h +10 -0
@@ -399,6 +399,16 @@ void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,void rt2x00usb_kill_tx_queue (struct rt2x00_dev *rt2x00dev,const enum data_queue_qid qid); +/** +* rt2x00usb_watchdog - Watchdog for USB communication +* @rt2x00dev: Pointer to &struct rt2x00_dev +* +* Check the health of the USB communication and determine +* if timeouts have occured. If this is the case, this function +* will reset all communication to restore functionality again. +*/ +void rt2x00usb_watchdog (struct rt2x00_dev *rt2x00dev); +/* * Device initialization handlers. */
drivers/net/wireless/rt2x00/rt73usb.c +2 -0
@@ -2136,6 +2136,7 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)if (!modparam_nohwcrypt)__set_bit (CONFIG_SUPPORT_HW_CRYPTO , &rt2x00dev->flags);__set_bit (DRIVER_SUPPORT_LINK_TUNING , &rt2x00dev->flags); +__set_bit (DRIVER_SUPPORT_WATCHDOG , &rt2x00dev->flags);/* * Set the rssi offset.
@@ -2251,6 +2252,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .link_stats = rt73usb_link_stats, .reset_tuner = rt73usb_reset_tuner, .link_tuner = rt73usb_link_tuner, + .watchdog = rt2x00usb_watchdog, .write_tx_desc = rt73usb_write_tx_desc, .write_beacon = rt73usb_write_beacon, .get_tx_data_len = rt73usb_get_tx_data_len,
Signature · 1 line
1.7.1.1
PATCH 7/17 rt2x00: Make rt2800_write_beacon only export to GPL
rt2800_write_beacon is the only function which uses EXPORT_SYMBOL instead of EXPORT_SYMBOL_GPL. All symbols in rt2x00 should however use the GPL restricted export.
--- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/wireless/rt2x00/rt2800lib.c +1 -1
@@ -473,7 +473,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)dev_kfree_skb_any (entry->skb); entry->skb =NULL ; } -EXPORT_SYMBOL (rt2800_write_beacon); +EXPORT_SYMBOL_GPL (rt2800_write_beacon);static void inline rt2800_clear_beacon (struct rt2x00_dev *rt2x00dev,unsigned int beacon_base)
Signature · 1 line
1.7.1.1
PATCH 8/17 rt2x00: Convert rt2x00 to use threaded interrupts
From: Helmut Schaa <[email protected]>
Use threaded interrupts for all rt2x00 PCI devices.
This has several generic advantages:
- Reduce the time we spend in hard irq context
- Use non-atmic mac80211 functions for rx/tx
Furthermore implementing broad- and multicast buffering will be much easier in process context while maintaining low latency and updating the beacon just before transmission (pre tbtt interrupt) can also be done in process context.
--- drivers/net/wireless/rt2x00/rt2400pci.c | 54 ++++++++++++++++++-------- drivers/net/wireless/rt2x00/rt2500pci.c | 55 +++++++++++++++++++-------- drivers/net/wireless/rt2x00/rt2500usb.c | 2 + drivers/net/wireless/rt2x00/rt2800pci.c | 50 ++++++++++++++++++------ drivers/net/wireless/rt2x00/rt2800usb.c | 2 + drivers/net/wireless/rt2x00/rt2x00.h | 11 +++++ drivers/net/wireless/rt2x00/rt2x00dev.c | 23 ++++++++++- drivers/net/wireless/rt2x00/rt2x00pci.c | 6 ++- drivers/net/wireless/rt2x00/rt2x00reg.h | 2 + drivers/net/wireless/rt2x00/rt61pci.c | 64 +++++++++++++++++++++---------- drivers/net/wireless/rt2x00/rt73usb.c | 2 + 11 files changed, 201 insertions(+), 70 deletions(-)
drivers/net/wireless/rt2x00/rt2400pci.c +38 -16
@@ -879,7 +879,8 @@ static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev,static void rt2400pci_toggle_irq (struct rt2x00_dev *rt2x00dev,enum dev_state state) { -int mask = (state ==STATE_RADIO_IRQ_OFF ); +int mask = (state ==STATE_RADIO_IRQ_OFF ) || + (state ==STATE_RADIO_IRQ_OFF_ISR );u32 reg;/*
@@ -980,7 +981,9 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,rt2400pci_toggle_rx (rt2x00dev, state);break ;case STATE_RADIO_IRQ_ON : +case STATE_RADIO_IRQ_ON_ISR :case STATE_RADIO_IRQ_OFF : +case STATE_RADIO_IRQ_OFF_ISR :rt2400pci_toggle_irq (rt2x00dev, state);break ;case STATE_DEEP_SLEEP :
@@ -1235,23 +1238,10 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, } } -static irqreturn_t rt2400pci_interrupt (int irq,void *dev_instance) +static irqreturn_t rt2400pci_interrupt_thread (int irq,void *dev_instance) {struct rt2x00_dev *rt2x00dev = dev_instance; -u32 reg; - -/* -* Get the interrupt sources & saved to local variable. -* Write register value back to clear pending interrupts. -*/ -rt2x00pci_register_read (rt2x00dev,CSR7 , ®); -rt2x00pci_register_write (rt2x00dev,CSR7 , reg); - -if (!reg) -return IRQ_NONE ; - -if (!test_bit (DEVICE_STATE_ENABLED_RADIO , &rt2x00dev->flags)) -return IRQ_HANDLED ; +u32 reg = rt2x00dev->irqvalue[0 ];/* * Handle interrupts, walk through all bits
@@ -1289,9 +1279,40 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)if (rt2x00_get_field32 (reg,CSR7_TXDONE_TXRING ))rt2400pci_txdone (rt2x00dev,QID_AC_BK ); +/* Enable interrupts again. */ + rt2x00dev->ops->lib->set_device_state (rt2x00dev, +STATE_RADIO_IRQ_ON_ISR );return IRQ_HANDLED ; } +static irqreturn_t rt2400pci_interrupt (int irq,void *dev_instance) +{ +struct rt2x00_dev *rt2x00dev = dev_instance; +u32 reg; + +/* +* Get the interrupt sources & saved to local variable. +* Write register value back to clear pending interrupts. +*/ +rt2x00pci_register_read (rt2x00dev,CSR7 , ®); +rt2x00pci_register_write (rt2x00dev,CSR7 , reg); + +if (!reg) +return IRQ_NONE ; + +if (!test_bit (DEVICE_STATE_ENABLED_RADIO , &rt2x00dev->flags)) +return IRQ_HANDLED ; + +/* Store irqvalues for use in the interrupt thread. */ + rt2x00dev->irqvalue[0 ] = reg; + +/* Disable interrupts, will be enabled again in the interrupt thread. */ + rt2x00dev->ops->lib->set_device_state (rt2x00dev, +STATE_RADIO_IRQ_OFF_ISR ); + +return IRQ_WAKE_THREAD ; +} +/* * Device probe functions. */
@@ -1581,6 +1602,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .irq_handler = rt2400pci_interrupt, + .irq_handler_thread = rt2400pci_interrupt_thread, .probe_hw = rt2400pci_probe_hw, .initialize = rt2x00pci_initialize, .uninitialize = rt2x00pci_uninitialize,
drivers/net/wireless/rt2x00/rt2500pci.c +39 -16
91 lines not on this page · raw message
drivers/net/wireless/rt2x00/rt2500usb.c +2 -0
@@ -1004,7 +1004,9 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,rt2500usb_toggle_rx (rt2x00dev, state);break ;case STATE_RADIO_IRQ_ON : +case STATE_RADIO_IRQ_ON_ISR :case STATE_RADIO_IRQ_OFF : +case STATE_RADIO_IRQ_OFF_ISR :/* No support, but no error either */ break ;case STATE_DEEP_SLEEP :
drivers/net/wireless/rt2x00/rt2800pci.c +37 -13
86 lines not on this page · raw message
drivers/net/wireless/rt2x00/rt2800usb.c +2 -0
@@ -406,7 +406,9 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,rt2800usb_toggle_rx (rt2x00dev, state);break ;case STATE_RADIO_IRQ_ON : +case STATE_RADIO_IRQ_ON_ISR :case STATE_RADIO_IRQ_OFF : +case STATE_RADIO_IRQ_OFF_ISR :/* No support, but no error either */ break ;case STATE_DEEP_SLEEP :
drivers/net/wireless/rt2x00/rt2x00.h +11 -0
@@ -515,6 +515,11 @@ struct rt2x00lib_ops {irq_handler_t irq_handler;/* +* Threaded Interrupt handlers. +*/ +irq_handler_t irq_handler_thread; + +/* * Device init handlers. */ int (*probe_hw) (struct rt2x00_dev *rt2x00dev);
@@ -871,6 +876,12 @@ struct rt2x00_dev {const struct firmware *fw;/* +* Interrupt values, stored between interrupt service routine +* and interrupt thread routine. +*/ +u32 irqvalue[2 ]; + +/* * Driver specific data. */ void *priv;
drivers/net/wireless/rt2x00/rt2x00dev.c +20 -3
@@ -340,9 +340,17 @@ void rt2x00lib_txdone(struct queue_entry *entry,* send the status report back. */ if (!(skbdesc_flags &SKBDESC_NOT_MAC80211 )) -ieee80211_tx_status_irqsafe (rt2x00dev->hw, entry->skb); +/* +* Only PCI and SOC devices process the tx status in process +* context. Hence use ieee80211_tx_status for PCI and SOC +* devices and stick to ieee80211_tx_status_irqsafe for USB. +*/ +if (rt2x00_is_usb (rt2x00dev)) +ieee80211_tx_status_irqsafe (rt2x00dev->hw, entry->skb); +else +ieee80211_tx_status (rt2x00dev->hw, entry->skb);else -dev_kfree_skb_irq (entry->skb); +dev_kfree_skb_any (entry->skb);/* * Make this entry available for reuse.
@@ -489,7 +497,16 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,*/ rt2x00debug_dump_frame (rt2x00dev,DUMP_FRAME_RXDONE , entry->skb);memcpy (IEEE80211_SKB_RXCB (entry->skb), rx_status,sizeof (*rx_status)); -ieee80211_rx_irqsafe (rt2x00dev->hw, entry->skb); + +/* +* Currently only PCI and SOC devices handle rx interrupts in process +* context. Hence, use ieee80211_rx_irqsafe for USB and ieee80211_rx_ni +* for PCI and SOC devices. +*/ +if (rt2x00_is_usb (rt2x00dev)) +ieee80211_rx_irqsafe (rt2x00dev->hw, entry->skb); +else +ieee80211_rx_ni (rt2x00dev->hw, entry->skb);/* * Replace the skb with the freshly allocated one.
drivers/net/wireless/rt2x00/rt2x00pci.c +4 -2
@@ -153,8 +153,10 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)/* * Register interrupt handler. */ - status =request_irq (rt2x00dev->irq, rt2x00dev->ops->lib->irq_handler, -IRQF_SHARED , rt2x00dev->name, rt2x00dev); + status =request_threaded_irq (rt2x00dev->irq, + rt2x00dev->ops->lib->irq_handler, + rt2x00dev->ops->lib->irq_handler_thread, +IRQF_SHARED , rt2x00dev->name, rt2x00dev);if (status) {ERROR (rt2x00dev,"IRQ %d allocation failed (error %d).\n" , rt2x00dev->irq, status);
drivers/net/wireless/rt2x00/rt2x00reg.h +2 -0
@@ -88,6 +88,8 @@ enum dev_state {STATE_RADIO_RX_OFF_LINK ,STATE_RADIO_IRQ_ON ,STATE_RADIO_IRQ_OFF , +STATE_RADIO_IRQ_ON_ISR , + STATE_RADIO_IRQ_OFF_ISR, };/*
drivers/net/wireless/rt2x00/rt61pci.c +44 -20
100 lines not on this page · raw message
drivers/net/wireless/rt2x00/rt73usb.c +2 -0
@@ -1400,7 +1400,9 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,rt73usb_toggle_rx (rt2x00dev, state);break ;case STATE_RADIO_IRQ_ON : +case STATE_RADIO_IRQ_ON_ISR :case STATE_RADIO_IRQ_OFF : +case STATE_RADIO_IRQ_OFF_ISR :/* No support, but no error either */ break ;case STATE_DEEP_SLEEP :
Signature · 1 line
1.7.1.1
PATCH 9/17 rt2x00: Allow beacon update without scheduling a work
From: Helmut Schaa <[email protected]>
Since all rt2x00 PCI drivers use threaded interrupts now we don't need to schedule a work just to update the beacon. The only place where the beacon still gets updated in atomic context is from the set_tim callback. Hence, move the work scheduling there.
--- drivers/net/wireless/rt2x00/rt2x00dev.c | 13 +++++-------- drivers/net/wireless/rt2x00/rt2x00mac.c | 26 +++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 9 deletions(-)
drivers/net/wireless/rt2x00/rt2x00dev.c +5 -8
@@ -181,7 +181,7 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work)static void rt2x00lib_beacondone_iter (void *data,u8 *mac,struct ieee80211_vif *vif) { -struct rt2x00_intf *intf =vif_to_intf (vif); +struct rt2x00_dev *rt2x00dev = data; if (vif->type != NL80211_IFTYPE_AP && vif->type != NL80211_IFTYPE_ADHOC &&
@@ -189,9 +189,7 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac, vif->type != NL80211_IFTYPE_WDS)return ; -spin_lock (&intf->lock); - intf->delayed_flags |=DELAYED_UPDATE_BEACON ; -spin_unlock (&intf->lock); +rt2x00queue_update_beacon (rt2x00dev, vif, true); }void rt2x00lib_beacondone (struct rt2x00_dev *rt2x00dev)
@@ -199,11 +197,10 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)if (!test_bit (DEVICE_STATE_ENABLED_RADIO , &rt2x00dev->flags))return ; -ieee80211_iterate_active_interfaces_atomic (rt2x00dev->hw, - rt2x00lib_beacondone_iter, - rt2x00dev); +ieee80211_iterate_active_interfaces (rt2x00dev->hw, + rt2x00lib_beacondone_iter, + rt2x00dev); -ieee80211_queue_work (rt2x00dev->hw, &rt2x00dev->intf_work); }EXPORT_SYMBOL_GPL (rt2x00lib_beacondone);
drivers/net/wireless/rt2x00/rt2x00mac.c +25 -1
@@ -433,12 +433,36 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, }EXPORT_SYMBOL_GPL (rt2x00mac_configure_filter); +static void rt2x00mac_set_tim_iter (void *data,u8 *mac, +struct ieee80211_vif *vif) +{ +struct rt2x00_intf *intf =vif_to_intf (vif); + +if (vif->type !=NL80211_IFTYPE_AP && + vif->type !=NL80211_IFTYPE_ADHOC && + vif->type !=NL80211_IFTYPE_MESH_POINT && + vif->type !=NL80211_IFTYPE_WDS ) +return ; + +spin_lock (&intf->lock); + intf->delayed_flags |=DELAYED_UPDATE_BEACON ; +spin_unlock (&intf->lock); +} +int rt2x00mac_set_tim (struct ieee80211_hw *hw,struct ieee80211_sta *sta,bool set) {struct rt2x00_dev *rt2x00dev = hw->priv; -rt2x00lib_beacondone (rt2x00dev); +if (!test_bit (DEVICE_STATE_ENABLED_RADIO , &rt2x00dev->flags)) +return 0 ; + +ieee80211_iterate_active_interfaces_atomic (rt2x00dev->hw, + rt2x00mac_set_tim_iter, + rt2x00dev); + +/* queue work to upodate the beacon template */ +ieee80211_queue_work (rt2x00dev->hw, &rt2x00dev->intf_work);return 0 ; }EXPORT_SYMBOL_GPL (rt2x00mac_set_tim);
Signature · 1 line
1.7.1.1
PATCH 10/17 rt2x00: Implement broad- and multicast buffering
From: Helmut Schaa <[email protected]>
Although mac80211 buffers broad- and mutlicast frames for us in AP mode we still have to send them out after a DTIM beacon. Implement this behavior by sending out the buffered frames when the beacondone interrupt is processed.
--- drivers/net/wireless/rt2x00/rt2x00dev.c | 32 +++++++++++++++++++++++++++++- 1 files changed, 30 insertions(+), 2 deletions(-)
drivers/net/wireless/rt2x00/rt2x00dev.c +30 -2
@@ -178,6 +178,28 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work)/* * Interrupt context handlers. */ +static void rt2x00lib_bc_buffer_iter (void *data,u8 *mac, +struct ieee80211_vif *vif) +{ +struct rt2x00_dev *rt2x00dev = data; +struct sk_buff *skb; + +/* +* Only AP mode interfaces do broad- and multicast buffering +*/ +if (vif->type !=NL80211_IFTYPE_AP ) +return ; + +/* +* Send out buffered broad- and multicast frames +*/ + skb =ieee80211_get_buffered_bc (rt2x00dev->hw, vif); +while (skb) { +rt2x00mac_tx (rt2x00dev->hw, skb); + skb =ieee80211_get_buffered_bc (rt2x00dev->hw, vif); + } +} +static void rt2x00lib_beacondone_iter (void *data,u8 *mac,struct ieee80211_vif *vif) {
@@ -197,9 +219,15 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)if (!test_bit (DEVICE_STATE_ENABLED_RADIO , &rt2x00dev->flags))return ; +/* send buffered bc/mc frames out for every bssid */ ieee80211_iterate_active_interfaces (rt2x00dev->hw, - rt2x00lib_beacondone_iter, - rt2x00dev); + rt2x00lib_bc_buffer_iter, + rt2x00dev); + +/* fetch next beacon */ +ieee80211_iterate_active_interfaces (rt2x00dev->hw, + rt2x00lib_beacondone_iter, + rt2x00dev); }EXPORT_SYMBOL_GPL (rt2x00lib_beacondone);
Signature · 1 line
1.7.1.1
PATCH 11/17 rt2x00: Use pretbtt irq for fetching beacons on rt2800pci
From: Helmut Schaa <[email protected]>
Updating the beacon on pre tbtt instead of beacondone allows much lower latency in regard to TIM updates. Hence, use the pre tbtt interrupt for updating the beacon in rt2800pci (older devices don't provide a pre tbtt interrupt).
Also, add a new driver flag to indicate if a driver has pre tbtt support or not and implement the according behavior in rt2x00lib.
--- drivers/net/wireless/rt2x00/rt2800.h | 8 +++++++- drivers/net/wireless/rt2x00/rt2800lib.c | 16 ++++++++++++++++ drivers/net/wireless/rt2x00/rt2800pci.c | 28 +++++++++++++++++++++++----- drivers/net/wireless/rt2x00/rt2x00.h | 2 ++ drivers/net/wireless/rt2x00/rt2x00dev.c | 26 ++++++++++++++++++++++---- 5 files changed, 70 insertions(+), 10 deletions(-)
drivers/net/wireless/rt2x00/rt2800.h +7 -1
@@ -719,14 +719,20 @@#define TBTT_TIMER 0x1124/* -* INT_TIMER_CFG: +* INT_TIMER_CFG: timer configuration +* PRE_TBTT_TIMER: leadtime to tbtt for pretbtt interrupt in units of 1/16 TU +* GP_TIMER: period of general purpose timer in units of 1/16 TU */ #define INT_TIMER_CFG 0x1128 +#define INT_TIMER_CFG_PRE_TBTT_TIMER FIELD32(0x0000ffff) +#define INT_TIMER_CFG_GP_TIMER FIELD32(0xffff0000)/* * INT_TIMER_EN: GP-timer and pre-tbtt Int enable */ #define INT_TIMER_EN 0x112c +#define INT_TIMER_EN_PRE_TBTT_TIMER FIELD32(0x00000001) +#define INT_TIMER_EN_GP_TIMER FIELD32(0x00000002)/* * CH_IDLE_STA: channel idle time
drivers/net/wireless/rt2x00/rt2800lib.c +16 -0
@@ -807,6 +807,15 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,rt2x00_set_field32 (®,BCN_TIME_CFG_TBTT_ENABLE , (conf->sync ==TSF_SYNC_BEACON ));rt2800_register_write (rt2x00dev,BCN_TIME_CFG , reg); + +/* +* Enable pre tbtt interrupt for beaconing modes +*/ +rt2800_register_read (rt2x00dev,INT_TIMER_EN , ®); +rt2x00_set_field32 (®,INT_TIMER_EN_PRE_TBTT_TIMER , + (conf->sync ==TSF_SYNC_BEACON )); +rt2800_register_write (rt2x00dev,INT_TIMER_EN , reg); + }if (flags &CONFIG_UPDATE_MAC ) {
@@ -1732,6 +1741,13 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)rt2800_register_read (rt2x00dev,TX_STA_CNT1 , ®);rt2800_register_read (rt2x00dev,TX_STA_CNT2 , ®); +/* +* Setup leadtime for pre tbtt interrupt to 6ms +*/ +rt2800_register_read (rt2x00dev,INT_TIMER_CFG , ®); +rt2x00_set_field32 (®,INT_TIMER_CFG_PRE_TBTT_TIMER ,6 <<4 ); +rt2800_register_write (rt2x00dev,INT_TIMER_CFG , reg); +return 0 ; }EXPORT_SYMBOL_GPL (rt2800_init_registers);
drivers/net/wireless/rt2x00/rt2800pci.c +23 -5
@@ -938,20 +938,32 @@ static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance)u32 reg = rt2x00dev->irqvalue[0 ];/* -* 1 - Rx ring done interrupt. +* 1 - Pre TBTT interrupt. +*/ +if (rt2x00_get_field32 (reg,INT_SOURCE_CSR_PRE_TBTT )) +rt2x00lib_pretbtt (rt2x00dev); + +/* +* 2 - Beacondone interrupt. +*/ +if (rt2x00_get_field32 (reg,INT_SOURCE_CSR_TBTT )) +rt2x00lib_beacondone (rt2x00dev); + +/* +* 3 - Rx ring done interrupt. */ if (rt2x00_get_field32 (reg,INT_SOURCE_CSR_RX_DONE ))rt2x00pci_rxdone (rt2x00dev); +/* +* 4 - Tx done interrupt. +*/ if (rt2x00_get_field32 (reg,INT_SOURCE_CSR_TX_FIFO_STATUS ))rt2800pci_txdone (rt2x00dev);/* -* Current beacon was sent out, fetch the next one +* 5 - Auto wakeup interrupt. */ -if (rt2x00_get_field32 (reg,INT_SOURCE_CSR_TBTT )) -rt2x00lib_beacondone (rt2x00dev); -if (rt2x00_get_field32 (reg,INT_SOURCE_CSR_AUTO_WAKEUP ))rt2800pci_wakeup (rt2x00dev);
@@ -1052,6 +1064,12 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)__set_bit (DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL , &rt2x00dev->flags);/* +* This device has a pre tbtt interrupt and thus fetches +* a new beacon directly prior to transmission. +*/ +__set_bit (DRIVER_SUPPORT_PRE_TBTT_INTERRUPT , &rt2x00dev->flags); + +/* * This device requires firmware. */ if (!rt2x00_is_soc (rt2x00dev))
drivers/net/wireless/rt2x00/rt2x00.h +2 -0
@@ -658,6 +658,7 @@ enum rt2x00_flags {CONFIG_SUPPORT_HW_CRYPTO ,DRIVER_SUPPORT_CONTROL_FILTERS ,DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL , +DRIVER_SUPPORT_PRE_TBTT_INTERRUPT ,DRIVER_SUPPORT_LINK_TUNING , DRIVER_SUPPORT_WATCHDOG,
@@ -1071,6 +1072,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,* Interrupt context handlers. */ void rt2x00lib_beacondone (struct rt2x00_dev *rt2x00dev); +void rt2x00lib_pretbtt (struct rt2x00_dev *rt2x00dev);void rt2x00lib_txdone (struct queue_entry *entry,struct txdone_entry_desc *txdesc); void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
drivers/net/wireless/rt2x00/rt2x00dev.c +22 -4
@@ -200,8 +200,8 @@ static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac, } } -static void rt2x00lib_beacondone_iter (void *data,u8 *mac, -struct ieee80211_vif *vif) +static void rt2x00lib_beaconupdate_iter (void *data,u8 *mac, +struct ieee80211_vif *vif) {struct rt2x00_dev *rt2x00dev = data;
@@ -223,15 +223,33 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)ieee80211_iterate_active_interfaces (rt2x00dev->hw, rt2x00lib_bc_buffer_iter, rt2x00dev); +/* +* Devices with pre tbtt interrupt don't need to update the beacon +* here as they will fetch the next beacon directly prior to +* transmission. +*/ +if (test_bit (DRIVER_SUPPORT_PRE_TBTT_INTERRUPT , &rt2x00dev->flags)) +return ;/* fetch next beacon */ ieee80211_iterate_active_interfaces (rt2x00dev->hw, - rt2x00lib_beacondone_iter, + rt2x00lib_beaconupdate_iter, rt2x00dev); - }EXPORT_SYMBOL_GPL (rt2x00lib_beacondone); +void rt2x00lib_pretbtt (struct rt2x00_dev *rt2x00dev) +{ +if (!test_bit (DEVICE_STATE_ENABLED_RADIO , &rt2x00dev->flags)) +return ; + +/* fetch next beacon */ +ieee80211_iterate_active_interfaces (rt2x00dev->hw, + rt2x00lib_beaconupdate_iter, + rt2x00dev); +} +EXPORT_SYMBOL_GPL (rt2x00lib_pretbtt); +void rt2x00lib_txdone (struct queue_entry *entry,struct txdone_entry_desc *txdesc) {
Signature · 1 line
1.7.1.1
PATCH 12/17 rt2x00: Use separate mac80211_ops for rt2800pci and rt2800usb
From: Helmut Schaa <[email protected]>
Use separate mac80211_ops for rt2800pci and rt2800usb in preparation for further fixes. This shouldn't introduce functional changes.
--- drivers/net/wireless/rt2x00/rt2800lib.c | 48 +++++++++---------------------- drivers/net/wireless/rt2x00/rt2800lib.h | 10 ++++++- drivers/net/wireless/rt2x00/rt2800pci.c | 24 +++++++++++++++- drivers/net/wireless/rt2x00/rt2800usb.c | 24 +++++++++++++++- 4 files changed, 69 insertions(+), 37 deletions(-)
drivers/net/wireless/rt2x00/rt2800lib.c +14 -34
@@ -2740,8 +2740,8 @@ EXPORT_SYMBOL_GPL(rt2800_probe_hw_mode);/* * IEEE80211 stack callback functions. */ -static void rt2800_get_tkip_seq (struct ieee80211_hw *hw,u8 hw_key_idx, -u32 *iv32,u16 *iv16) +void rt2800_get_tkip_seq (struct ieee80211_hw *hw,u8 hw_key_idx,u32 *iv32, +u16 *iv16) {struct rt2x00_dev *rt2x00dev = hw->priv;struct mac_iveiv_entry iveiv_entry;
@@ -2754,8 +2754,9 @@ static void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx,memcpy (iv16, &iveiv_entry.iv[0 ],sizeof (*iv16));memcpy (iv32, &iveiv_entry.iv[4 ],sizeof (*iv32)); } +EXPORT_SYMBOL_GPL (rt2800_get_tkip_seq); -static int rt2800_set_rts_threshold (struct ieee80211_hw *hw,u32 value) +int rt2800_set_rts_threshold (struct ieee80211_hw *hw,u32 value) {struct rt2x00_dev *rt2x00dev = hw->priv;u32 reg;
@@ -2791,9 +2792,10 @@ static int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)return 0 ; } +EXPORT_SYMBOL_GPL (rt2800_set_rts_threshold); -static int rt2800_conf_tx (struct ieee80211_hw *hw,u16 queue_idx, -const struct ieee80211_tx_queue_params *params) +int rt2800_conf_tx (struct ieee80211_hw *hw,u16 queue_idx, +const struct ieee80211_tx_queue_params *params) {struct rt2x00_dev *rt2x00dev = hw->priv;struct data_queue *queue;
@@ -2858,8 +2860,9 @@ static int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,return 0 ; } +EXPORT_SYMBOL_GPL (rt2800_conf_tx); -static u64 rt2800_get_tsf (struct ieee80211_hw *hw) +u64 rt2800_get_tsf (struct ieee80211_hw *hw) {struct rt2x00_dev *rt2x00dev = hw->priv;u64 tsf;
@@ -2872,12 +2875,11 @@ static u64 rt2800_get_tsf(struct ieee80211_hw *hw)return tsf; } +EXPORT_SYMBOL_GPL (rt2800_get_tsf); -static int rt2800_ampdu_action (struct ieee80211_hw *hw, -struct ieee80211_vif *vif, -enum ieee80211_ampdu_mlme_action action, -struct ieee80211_sta *sta, -u16 tid,u16 *ssn) +int rt2800_ampdu_action (struct ieee80211_hw *hw,struct ieee80211_vif *vif, +enum ieee80211_ampdu_mlme_action action, +struct ieee80211_sta *sta,u16 tid,u16 *ssn) {int ret =0 ;
@@ -2901,29 +2903,7 @@ static int rt2800_ampdu_action(struct ieee80211_hw *hw,return ret; } - -const struct ieee80211_ops rt2800_mac80211_ops = { - .tx = rt2x00mac_tx, - .start = rt2x00mac_start, - .stop = rt2x00mac_stop, - .add_interface = rt2x00mac_add_interface, - .remove_interface = rt2x00mac_remove_interface, - .config = rt2x00mac_config, - .configure_filter = rt2x00mac_configure_filter, - .set_tim = rt2x00mac_set_tim, - .set_key = rt2x00mac_set_key, - .sw_scan_start = rt2x00mac_sw_scan_start, - .sw_scan_complete = rt2x00mac_sw_scan_complete, - .get_stats = rt2x00mac_get_stats, - .get_tkip_seq = rt2800_get_tkip_seq, - .set_rts_threshold = rt2800_set_rts_threshold, - .bss_info_changed = rt2x00mac_bss_info_changed, - .conf_tx = rt2800_conf_tx, - .get_tsf = rt2800_get_tsf, - .rfkill_poll = rt2x00mac_rfkill_poll, - .ampdu_action = rt2800_ampdu_action, -}; -EXPORT_SYMBOL_GPL (rt2800_mac80211_ops); +EXPORT_SYMBOL_GPL (rt2800_ampdu_action);MODULE_AUTHOR (DRV_PROJECT ", Bartlomiej Zolnierkiewicz" );MODULE_VERSION (DRV_VERSION );
drivers/net/wireless/rt2x00/rt2800lib.h +9 -1
@@ -159,6 +159,14 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev);int rt2800_init_eeprom (struct rt2x00_dev *rt2x00dev);int rt2800_probe_hw_mode (struct rt2x00_dev *rt2x00dev); -extern const struct ieee80211_ops rt2800_mac80211_ops; +void rt2800_get_tkip_seq (struct ieee80211_hw *hw,u8 hw_key_idx,u32 *iv32, +u16 *iv16); +int rt2800_set_rts_threshold (struct ieee80211_hw *hw,u32 value); +int rt2800_conf_tx (struct ieee80211_hw *hw,u16 queue_idx, +const struct ieee80211_tx_queue_params *params); +u64 rt2800_get_tsf (struct ieee80211_hw *hw); +int rt2800_ampdu_action (struct ieee80211_hw *hw,struct ieee80211_vif *vif, +enum ieee80211_ampdu_mlme_action action, +struct ieee80211_sta *sta,u16 tid,u16 *ssn);#endif /* RT2800LIB_H */
drivers/net/wireless/rt2x00/rt2800pci.c +23 -1
@@ -1088,6 +1088,28 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)return 0 ; } +static const struct ieee80211_ops rt2800pci_mac80211_ops = { + .tx = rt2x00mac_tx, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, + .remove_interface = rt2x00mac_remove_interface, + .config = rt2x00mac_config, + .configure_filter = rt2x00mac_configure_filter, + .set_tim = rt2x00mac_set_tim, + .set_key = rt2x00mac_set_key, + .sw_scan_start = rt2x00mac_sw_scan_start, + .sw_scan_complete = rt2x00mac_sw_scan_complete, + .get_stats = rt2x00mac_get_stats, + .get_tkip_seq = rt2800_get_tkip_seq, + .set_rts_threshold = rt2800_set_rts_threshold, + .bss_info_changed = rt2x00mac_bss_info_changed, + .conf_tx = rt2800_conf_tx, + .get_tsf = rt2800_get_tsf, + .rfkill_poll = rt2x00mac_rfkill_poll, + .ampdu_action = rt2800_ampdu_action, +}; +static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .irq_handler = rt2800pci_interrupt, .irq_handler_thread = rt2800pci_interrupt_thread,
@@ -1152,7 +1174,7 @@ static const struct rt2x00_ops rt2800pci_ops = { .tx = &rt2800pci_queue_tx, .bcn = &rt2800pci_queue_bcn, .lib = &rt2800pci_rt2x00_ops, - .hw = &rt2800_mac80211_ops, + .hw = &rt2800pci_mac80211_ops,#ifdef CONFIG_RT2X00_LIB_DEBUGFS .debugfs = &rt2800_rt2x00debug,#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
drivers/net/wireless/rt2x00/rt2800usb.c +23 -1
@@ -645,6 +645,28 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)return 0 ; } +static const struct ieee80211_ops rt2800usb_mac80211_ops = { + .tx = rt2x00mac_tx, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, + .remove_interface = rt2x00mac_remove_interface, + .config = rt2x00mac_config, + .configure_filter = rt2x00mac_configure_filter, + .set_tim = rt2x00mac_set_tim, + .set_key = rt2x00mac_set_key, + .sw_scan_start = rt2x00mac_sw_scan_start, + .sw_scan_complete = rt2x00mac_sw_scan_complete, + .get_stats = rt2x00mac_get_stats, + .get_tkip_seq = rt2800_get_tkip_seq, + .set_rts_threshold = rt2800_set_rts_threshold, + .bss_info_changed = rt2x00mac_bss_info_changed, + .conf_tx = rt2800_conf_tx, + .get_tsf = rt2800_get_tsf, + .rfkill_poll = rt2x00mac_rfkill_poll, + .ampdu_action = rt2800_ampdu_action, +}; +static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .probe_hw = rt2800usb_probe_hw, .get_firmware_name = rt2800usb_get_firmware_name,
@@ -708,7 +730,7 @@ static const struct rt2x00_ops rt2800usb_ops = { .tx = &rt2800usb_queue_tx, .bcn = &rt2800usb_queue_bcn, .lib = &rt2800usb_rt2x00_ops, - .hw = &rt2800_mac80211_ops, + .hw = &rt2800usb_mac80211_ops,#ifdef CONFIG_RT2X00_LIB_DEBUGFS .debugfs = &rt2800_rt2x00debug,#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
Signature · 1 line
1.7.1.1
PATCH 13/17 rt2x00: Remove set_tim callback from PCI drivers
From: Helmut Schaa <[email protected]>
Using the set_tim callback without managing the DTIM count and the broad- and multicast buffering in hw, fw or the driver results in wrong DTIM count values being sent out in beacons. Since all PCI drivers fetch new beacons periodically and hence get an updated TIM we can just remove the set_tim callback from these.
The rt2x00 USB drivers don't update the beacon periodically and thus rely on the set_tim callback to get a correct TIM for beacon transmission. USB devices still suffer from the DTIM count being wrong under some circumstances but removing the set_tim callback from these would cause more harm then good.
--- drivers/net/wireless/rt2x00/rt2400pci.c | 1 - drivers/net/wireless/rt2x00/rt2500pci.c | 1 - drivers/net/wireless/rt2x00/rt2800pci.c | 1 - drivers/net/wireless/rt2x00/rt61pci.c | 1 - 4 files changed, 0 insertions(+), 4 deletions(-)
drivers/net/wireless/rt2x00/rt2400pci.c +0 -1
@@ -1589,7 +1589,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .configure_filter = rt2x00mac_configure_filter, - .set_tim = rt2x00mac_set_tim, .sw_scan_start = rt2x00mac_sw_scan_start, .sw_scan_complete = rt2x00mac_sw_scan_complete, .get_stats = rt2x00mac_get_stats,
drivers/net/wireless/rt2x00/rt2500pci.c +0 -1
@@ -1883,7 +1883,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .configure_filter = rt2x00mac_configure_filter, - .set_tim = rt2x00mac_set_tim, .sw_scan_start = rt2x00mac_sw_scan_start, .sw_scan_complete = rt2x00mac_sw_scan_complete, .get_stats = rt2x00mac_get_stats,
drivers/net/wireless/rt2x00/rt2800pci.c +0 -1
@@ -1096,7 +1096,6 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .configure_filter = rt2x00mac_configure_filter, - .set_tim = rt2x00mac_set_tim, .set_key = rt2x00mac_set_key, .sw_scan_start = rt2x00mac_sw_scan_start, .sw_scan_complete = rt2x00mac_sw_scan_complete,
drivers/net/wireless/rt2x00/rt61pci.c +0 -1
@@ -2805,7 +2805,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .configure_filter = rt2x00mac_configure_filter, - .set_tim = rt2x00mac_set_tim, .set_key = rt2x00mac_set_key, .sw_scan_start = rt2x00mac_sw_scan_start, .sw_scan_complete = rt2x00mac_sw_scan_complete,
Signature · 1 line
1.7.1.1
PATCH 14/17 rt2x00: Don't initialize beacon interval to 0 on rt2800 devices
From: Helmut Schaa <[email protected]>
Activating the TBTT interrupt when a beacon interval of 0 is configured results in an interrupt storm causing the machine to hang. Hence, initialize the beacon interval to a reasonable default of 100TUs.
--- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/wireless/rt2x00/rt2800lib.c +1 -1
@@ -1419,7 +1419,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)rt2800_register_write (rt2x00dev,MAC_SYS_CTRL ,0x00000000 );rt2800_register_read (rt2x00dev,BCN_TIME_CFG , ®); -rt2x00_set_field32 (®,BCN_TIME_CFG_BEACON_INTERVAL ,0 ); +rt2x00_set_field32 (®,BCN_TIME_CFG_BEACON_INTERVAL ,1600 );rt2x00_set_field32 (®,BCN_TIME_CFG_TSF_TICKING ,0 );rt2x00_set_field32 (®,BCN_TIME_CFG_TSF_SYNC ,0 );rt2x00_set_field32 (®,BCN_TIME_CFG_TBTT_ENABLE ,0 );
Signature · 1 line
1.7.1.1
PATCH 15/17 rt2x00: Add missing TSF sync mode for AP operation
From: Helmut Schaa <[email protected]>
Currently rt2x00 uses the TSF_SYNC_BEACON mode for all beaconing interface types. However, TSF_SYNC_BEACON is meant for IBSS networks and thus implements TSF merging in the hardware. Rename TSF_SYNC_BEACON to TSF_SYNC_ADHOC to better express its purpose and introduce the missing TSF sync mode TSF_SYNC_AP_NONE which should be used for beaconing modes that don't need TSF merging.
--- drivers/net/wireless/rt2x00/rt2800lib.c | 5 +++-- drivers/net/wireless/rt2x00/rt2x00config.c | 4 +++- drivers/net/wireless/rt2x00/rt2x00reg.h | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-)
drivers/net/wireless/rt2x00/rt2800lib.c +3 -2
@@ -805,7 +805,8 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,rt2x00_set_field32 (®,BCN_TIME_CFG_TSF_TICKING ,1 );rt2x00_set_field32 (®,BCN_TIME_CFG_TSF_SYNC , conf->sync);rt2x00_set_field32 (®,BCN_TIME_CFG_TBTT_ENABLE , - (conf->sync ==TSF_SYNC_BEACON )); + (conf->sync ==TSF_SYNC_ADHOC || + conf->sync ==TSF_SYNC_AP_NONE ));rt2800_register_write (rt2x00dev,BCN_TIME_CFG , reg);/*
@@ -813,7 +814,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,*/ rt2800_register_read (rt2x00dev,INT_TIMER_EN , ®);rt2x00_set_field32 (®,INT_TIMER_EN_PRE_TBTT_TIMER , - (conf->sync ==TSF_SYNC_BEACON )); + (conf->sync ==TSF_SYNC_AP_NONE ));rt2800_register_write (rt2x00dev,INT_TIMER_EN , reg); }
drivers/net/wireless/rt2x00/rt2x00config.c +3 -1
@@ -41,10 +41,12 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,switch (type) {case NL80211_IFTYPE_ADHOC : + conf.sync =TSF_SYNC_ADHOC ; +break ;case NL80211_IFTYPE_AP :case NL80211_IFTYPE_MESH_POINT :case NL80211_IFTYPE_WDS : - conf.sync =TSF_SYNC_BEACON ; + conf.sync =TSF_SYNC_AP_NONE ;break ;case NL80211_IFTYPE_STATION : conf.sync =TSF_SYNC_INFRA ;
drivers/net/wireless/rt2x00/rt2x00reg.h +2 -1
@@ -63,7 +63,8 @@ enum led_mode {enum tsf_sync {TSF_SYNC_NONE =0 ,TSF_SYNC_INFRA =1 , -TSF_SYNC_BEACON =2 , +TSF_SYNC_ADHOC =2 , +TSF_SYNC_AP_NONE =3 , };/*
Signature · 1 line
1.7.1.1
PATCH 16/17 rt2x00: Move common firmware loading into rt2800lib
Large parts of the firmware initialization are shared between rt2800pci and rt2800usb. Move this code into rt2800lib.
--- drivers/net/wireless/rt2x00/rt2800lib.c | 155 +++++++++++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2800lib.h | 15 +++ drivers/net/wireless/rt2x00/rt2800pci.c | 101 +------------------- drivers/net/wireless/rt2x00/rt2800usb.c | 119 +----------------------- 4 files changed, 179 insertions(+), 211 deletions(-)
drivers/net/wireless/rt2x00/rt2800lib.c +155 -0
@@ -33,6 +33,7 @@Abstract: rt2800 generic device routines. */ +#include <linux/crc-ccitt.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h>
@@ -272,6 +273,160 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) }EXPORT_SYMBOL_GPL (rt2800_wait_wpdma_ready); +static bool rt2800_check_firmware_crc (const u8 *data,const size_t len) +{ +u16 fw_crc; +u16 crc; + +/* +* The last 2 bytes in the firmware array are the crc checksum itself, +* this means that we should never pass those 2 bytes to the crc +* algorithm. +*/ + fw_crc = (data[len -2 ] <<8 | data[len -1 ]); + +/* +* Use the crc ccitt algorithm. +* This will return the same value as the legacy driver which +* used bit ordering reversion on the both the firmware bytes +* before input input as well as on the final output. +* Obviously using crc ccitt directly is much more efficient. +*/ + crc =crc_ccitt (~0 , data, len -2 ); + +/* +* There is a small difference between the crc-itu-t + bitrev and +* the crc-ccitt crc calculation. In the latter method the 2 bytes +* will be swapped, use swab16 to convert the crc to the correct +* value. +*/ + crc =swab16 (crc); + +return fw_crc == crc; +} + +int rt2800_check_firmware (struct rt2x00_dev *rt2x00dev, +const u8 *data,const size_t len) +{ +size_t offset =0 ; +size_t fw_len; +bool multiple; + +/* +* PCI(e) & SOC devices require firmware with a length +* of 8kb. USB devices require firmware files with a length +* of 4kb. Certain USB chipsets however require different firmware, +* which Ralink only provides attached to the original firmware +* file. Thus for USB devices, firmware files have a length +* which is a multiple of 4kb. +*/ +if (rt2x00_is_usb (rt2x00dev)) { + fw_len =4096 ; + multiple = true; + }else { + fw_len =8192 ; + multiple = true; + } + +/* +* Validate the firmware length +*/ +if (len != fw_len && (!multiple || (len % fw_len) !=0 )) +return FW_BAD_LENGTH ; + +/* +* Check if the chipset requires one of the upper parts +* of the firmware. +*/ +if (rt2x00_is_usb (rt2x00dev) && + !rt2x00_rt (rt2x00dev,RT2860 ) && + !rt2x00_rt (rt2x00dev,RT2872 ) && + !rt2x00_rt (rt2x00dev,RT3070 ) && + ((len / fw_len) ==1 )) +return FW_BAD_VERSION ; + +/* +* 8kb firmware files must be checked as if it were +* 2 separate firmware files. +*/ +while (offset < len) { +if (!rt2800_check_firmware_crc (data + offset, fw_len)) +return FW_BAD_CRC ; + + offset += fw_len; + } + +return FW_OK ; +} +EXPORT_SYMBOL_GPL (rt2800_check_firmware); + +int rt2800_load_firmware (struct rt2x00_dev *rt2x00dev, +const u8 *data,const size_t len) +{ +unsigned int i; +u32 reg; + +/* +* Wait for stable hardware. +*/ +for (i =0 ; i <REGISTER_BUSY_COUNT ; i++) { +rt2800_register_read (rt2x00dev,MAC_CSR0 , ®); +if (reg && reg != ~0 ) +break ; +msleep (1 ); + } + +if (i ==REGISTER_BUSY_COUNT ) { +ERROR (rt2x00dev,"Unstable hardware.\n" ); +return -EBUSY ; + } + +if (rt2x00_is_pci (rt2x00dev)) +rt2800_register_write (rt2x00dev,PWR_PIN_CFG ,0x00000002 ); + +/* +* Disable DMA, will be reenabled later when enabling +* the radio. +*/ +rt2800_register_read (rt2x00dev,WPDMA_GLO_CFG , ®); +rt2x00_set_field32 (®,WPDMA_GLO_CFG_ENABLE_TX_DMA ,0 ); +rt2x00_set_field32 (®,WPDMA_GLO_CFG_TX_DMA_BUSY ,0 ); +rt2x00_set_field32 (®,WPDMA_GLO_CFG_ENABLE_RX_DMA ,0 ); +rt2x00_set_field32 (®,WPDMA_GLO_CFG_RX_DMA_BUSY ,0 ); +rt2x00_set_field32 (®,WPDMA_GLO_CFG_TX_WRITEBACK_DONE ,1 ); +rt2800_register_write (rt2x00dev,WPDMA_GLO_CFG , reg); + +/* +* Write firmware to the device. +*/ +rt2800_drv_write_firmware (rt2x00dev, data, len); + +/* +* Wait for device to stabilize. +*/ +for (i =0 ; i <REGISTER_BUSY_COUNT ; i++) { +rt2800_register_read (rt2x00dev,PBF_SYS_CTRL , ®); +if (rt2x00_get_field32 (reg,PBF_SYS_CTRL_READY )) +break ; +msleep (1 ); + } + +if (i ==REGISTER_BUSY_COUNT ) { +ERROR (rt2x00dev,"PBF system register not ready.\n" ); +return -EBUSY ; + } + +/* +* Initialize firmware. +*/ +rt2800_register_write (rt2x00dev,H2M_BBP_AGENT ,0 ); +rt2800_register_write (rt2x00dev,H2M_MAILBOX_CSR ,0 ); +msleep (1 ); + +return 0 ; +} +EXPORT_SYMBOL_GPL (rt2800_load_firmware); +void rt2800_write_txwi (__le32 *txwi,struct txentry_desc *txdesc) {u32 word;
drivers/net/wireless/rt2x00/rt2800lib.h +15 -0
@@ -41,6 +41,8 @@ struct rt2800_ops {const unsigned int offset, const struct rt2x00_field32 field, u32 *reg); +int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev, +const u8 *data,const size_t len);int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); };
@@ -109,6 +111,14 @@ static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev,return rt2800ops->regbusy_read (rt2x00dev, offset, field, reg); } +static inline int rt2800_drv_write_firmware (struct rt2x00_dev *rt2x00dev, +const u8 *data,const size_t len) +{ +const struct rt2800_ops *rt2800ops = rt2x00dev->priv; + +return rt2800ops->drv_write_firmware (rt2x00dev, data, len); +} +static inline int rt2800_drv_init_registers (struct rt2x00_dev *rt2x00dev) {const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
@@ -120,6 +130,11 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, const u8 command, const u8 token, const u8 arg0, const u8 arg1); +int rt2800_check_firmware (struct rt2x00_dev *rt2x00dev, +const u8 *data,const size_t len); +int rt2800_load_firmware (struct rt2x00_dev *rt2x00dev, +const u8 *data,const size_t len); +void rt2800_write_txwi (__le32 *txwi,struct txentry_desc *txdesc);void rt2800_process_rxwi (struct queue_entry *entry,struct rxdone_entry_desc *txdesc);
drivers/net/wireless/rt2x00/rt2800pci.c +5 -96
142 lines not on this page · raw message
drivers/net/wireless/rt2x00/rt2800usb.c +4 -115
158 lines not on this page · raw message
Signature · 1 line
1.7.1.1
PATCH 17/17 rt2x00: Move driver callback functions into the ops structure
All callback functions are gathered in rt2x00dev->ops except for the callback functions which are used in rt2800lib to acces rt2800pci/usb.
Move the priv pointer from rt2x00dev to rt2x00dev->ops and rename it to drv to make it obvious that it is the driver callback structure.
--- drivers/net/wireless/rt2x00/rt2800lib.h | 18 +++++++++--------- drivers/net/wireless/rt2x00/rt2800pci.c | 30 +++++++++++++----------------- drivers/net/wireless/rt2x00/rt2800usb.c | 30 +++++++++++++----------------- drivers/net/wireless/rt2x00/rt2x00.h | 6 +----- 4 files changed, 36 insertions(+), 48 deletions(-)
drivers/net/wireless/rt2x00/rt2800lib.h +9 -9
@@ -50,7 +50,7 @@ static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,const unsigned int offset, u32 *value) { - const struct rt2800_ops *rt2800ops = rt2x00dev->priv; + const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; rt2800ops->register_read (rt2x00dev, offset, value); }
@@ -59,7 +59,7 @@ static inline void rt2800_register_read_lock(struct rt2x00_dev *rt2x00dev,const unsigned int offset, u32 *value) { - const struct rt2800_ops *rt2800ops = rt2x00dev->priv; + const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; rt2800ops->register_read_lock (rt2x00dev, offset, value); }
@@ -68,7 +68,7 @@ static inline void rt2800_register_write(struct rt2x00_dev *rt2x00dev, const unsigned int offset, u32 value) { -const struct rt2800_ops *rt2800ops = rt2x00dev->priv; +const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; rt2800ops->register_write (rt2x00dev, offset, value); }
@@ -77,7 +77,7 @@ static inline void rt2800_register_write_lock(struct rt2x00_dev *rt2x00dev, const unsigned int offset, u32 value) { -const struct rt2800_ops *rt2800ops = rt2x00dev->priv; +const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; rt2800ops->register_write_lock (rt2x00dev, offset, value); }
@@ -86,7 +86,7 @@ static inline void rt2800_register_multiread(struct rt2x00_dev *rt2x00dev,const unsigned int offset, void *value, const u32 length) { - const struct rt2800_ops *rt2800ops = rt2x00dev->priv; + const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; rt2800ops->register_multiread (rt2x00dev, offset, value, length); }
@@ -96,7 +96,7 @@ static inline void rt2800_register_multiwrite(struct rt2x00_dev *rt2x00dev,const void *value, const u32 length) { - const struct rt2800_ops *rt2800ops = rt2x00dev->priv; + const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; rt2800ops->register_multiwrite (rt2x00dev, offset, value, length); }
@@ -106,7 +106,7 @@ static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev,const struct rt2x00_field32 field, u32 *reg) { - const struct rt2800_ops *rt2800ops = rt2x00dev->priv; + const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;return rt2800ops->regbusy_read (rt2x00dev, offset, field, reg); }
@@ -114,14 +114,14 @@ static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev,static inline int rt2800_drv_write_firmware (struct rt2x00_dev *rt2x00dev,const u8 *data,const size_t len) { -const struct rt2800_ops *rt2800ops = rt2x00dev->priv; +const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;return rt2800ops->drv_write_firmware (rt2x00dev, data, len); }static inline int rt2800_drv_init_registers (struct rt2x00_dev *rt2x00dev) { -const struct rt2800_ops *rt2800ops = rt2x00dev->priv; +const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;return rt2800ops->drv_init_registers (rt2x00dev); }
drivers/net/wireless/rt2x00/rt2800pci.c +13 -17
@@ -926,27 +926,10 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)return rt2800_validate_eeprom (rt2x00dev); } -static const struct rt2800_ops rt2800pci_rt2800_ops = { - .register_read = rt2x00pci_register_read, - .register_read_lock = rt2x00pci_register_read,/* same for PCI */ - .register_write = rt2x00pci_register_write, - .register_write_lock = rt2x00pci_register_write,/* same for PCI */ - - .register_multiread = rt2x00pci_register_multiread, - .register_multiwrite = rt2x00pci_register_multiwrite, - - .regbusy_read = rt2x00pci_regbusy_read, - - .drv_write_firmware = rt2800pci_write_firmware, - .drv_init_registers = rt2800pci_init_registers, -}; -static int rt2800pci_probe_hw (struct rt2x00_dev *rt2x00dev) {int retval; - rt2x00dev->priv = (void *)&rt2800pci_rt2800_ops; -/* * Allocate eeprom data. */
@@ -1018,6 +1001,18 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = { .ampdu_action = rt2800_ampdu_action, }; +static const struct rt2800_ops rt2800pci_rt2800_ops = { + .register_read = rt2x00pci_register_read, + .register_read_lock = rt2x00pci_register_read,/* same for PCI */ + .register_write = rt2x00pci_register_write, + .register_write_lock = rt2x00pci_register_write,/* same for PCI */ + .register_multiread = rt2x00pci_register_multiread, + .register_multiwrite = rt2x00pci_register_multiwrite, + .regbusy_read = rt2x00pci_regbusy_read, + .drv_write_firmware = rt2800pci_write_firmware, + .drv_init_registers = rt2800pci_init_registers, +}; +static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .irq_handler = rt2800pci_interrupt, .irq_handler_thread = rt2800pci_interrupt_thread,
@@ -1082,6 +1077,7 @@ static const struct rt2x00_ops rt2800pci_ops = { .tx = &rt2800pci_queue_tx, .bcn = &rt2800pci_queue_bcn, .lib = &rt2800pci_rt2x00_ops, + .drv = &rt2800pci_rt2800_ops, .hw = &rt2800pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS .debugfs = &rt2800_rt2x00debug,
drivers/net/wireless/rt2x00/rt2800usb.c +13 -17
@@ -470,27 +470,10 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)return rt2800_validate_eeprom (rt2x00dev); } -static const struct rt2800_ops rt2800usb_rt2800_ops = { - .register_read = rt2x00usb_register_read, - .register_read_lock = rt2x00usb_register_read_lock, - .register_write = rt2x00usb_register_write, - .register_write_lock = rt2x00usb_register_write_lock, - - .register_multiread = rt2x00usb_register_multiread, - .register_multiwrite = rt2x00usb_register_multiwrite, - - .regbusy_read = rt2x00usb_regbusy_read, - - .drv_write_firmware = rt2800usb_write_firmware, - .drv_init_registers = rt2800usb_init_registers, -}; -static int rt2800usb_probe_hw (struct rt2x00_dev *rt2x00dev) {int retval; - rt2x00dev->priv = (void *)&rt2800usb_rt2800_ops; -/* * Allocate eeprom data. */
@@ -556,6 +539,18 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = { .ampdu_action = rt2800_ampdu_action, }; +static const struct rt2800_ops rt2800usb_rt2800_ops = { + .register_read = rt2x00usb_register_read, + .register_read_lock = rt2x00usb_register_read_lock, + .register_write = rt2x00usb_register_write, + .register_write_lock = rt2x00usb_register_write_lock, + .register_multiread = rt2x00usb_register_multiread, + .register_multiwrite = rt2x00usb_register_multiwrite, + .regbusy_read = rt2x00usb_regbusy_read, + .drv_write_firmware = rt2800usb_write_firmware, + .drv_init_registers = rt2800usb_init_registers, +}; +static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .probe_hw = rt2800usb_probe_hw, .get_firmware_name = rt2800usb_get_firmware_name,
@@ -619,6 +614,7 @@ static const struct rt2x00_ops rt2800usb_ops = { .tx = &rt2800usb_queue_tx, .bcn = &rt2800usb_queue_bcn, .lib = &rt2800usb_rt2x00_ops, + .drv = &rt2800usb_rt2800_ops, .hw = &rt2800usb_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS .debugfs = &rt2800_rt2x00debug,
drivers/net/wireless/rt2x00/rt2x00.h +1 -5
@@ -621,6 +621,7 @@ struct rt2x00_ops {const struct data_queue_desc *bcn;const struct data_queue_desc *atim;const struct rt2x00lib_ops *lib; +const void *drv;const struct ieee80211_ops *hw;#ifdef CONFIG_RT2X00_LIB_DEBUGFS const struct rt2x00debug *debugfs;
@@ -881,11 +882,6 @@ struct rt2x00_dev {* and interrupt thread routine. */ u32 irqvalue[2 ]; - -/* -* Driver specific data. -*/ -void *priv; };/*
Signature · 1 line
1.7.1.1