From 626ede6b1aafb3a8cadfdd04b512fd1d3dc2113e Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Thu, 18 Feb 2010 20:28:02 -0500 Subject: ath5k: remove stale function declarations, make some functions static Remove all unnecessary function declarations from ath5k.h. Comment out unused functions. Remove ath5k_hw_get_tsf32(), which is too trivial to be commented out. Make functions static if suggested by sparse. Make ath5k_pm_ops static. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 16 ---------------- drivers/net/wireless/ath/ath5k/base.c | 2 +- drivers/net/wireless/ath/ath5k/pcu.c | 29 ++++++++++++----------------- drivers/net/wireless/ath/ath5k/phy.c | 6 ++++-- drivers/net/wireless/ath/ath5k/qcu.c | 2 ++ drivers/net/wireless/ath/ath5k/reset.c | 4 ++-- 6 files changed, 21 insertions(+), 38 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index ac67f02e26d8..9e4ea19e7208 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1172,7 +1172,6 @@ extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); extern int ath5k_hw_on_hold(struct ath5k_hw *ah); extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel); /* Power management functions */ -extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration); /* DMA Related Functions */ extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); @@ -1196,7 +1195,6 @@ extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_l extern int ath5k_eeprom_init(struct ath5k_hw *ah); extern void ath5k_eeprom_detach(struct ath5k_hw *ah); extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); -extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); /* Protocol Control Unit Functions */ extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); @@ -1210,12 +1208,9 @@ extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); /* RX Filter functions */ extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); -extern int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index); -extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index); extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); /* Beacon control functions */ -extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah); extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah); @@ -1227,18 +1222,12 @@ extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) #endif /* ACK bit rate */ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); -/* ACK/CTS Timeouts */ -extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout); -extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah); -extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout); -extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah); /* Clock rate related functions */ unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah); /* Key table (WEP) functions */ extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); -extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac); extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); @@ -1252,7 +1241,6 @@ extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); -extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah); extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); /* Hardware Descriptor Functions */ @@ -1292,8 +1280,6 @@ extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *chann /* PHY calibration */ void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); -extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); -extern s16 ath5k_hw_get_noise_floor(struct ath5k_hw *ah); extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah); /* Spur mitigation */ bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, @@ -1305,8 +1291,6 @@ extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); /* Antenna control */ extern void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); -extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant); -extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); /* TX power setup */ extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 8dce0077b023..c889d4992a67 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -198,7 +198,7 @@ static void __devexit ath5k_pci_remove(struct pci_dev *pdev); static int ath5k_pci_suspend(struct device *dev); static int ath5k_pci_resume(struct device *dev); -SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); +static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); #define ATH5K_PM_OPS (&ath5k_pm_ops) #else #define ATH5K_PM_OPS NULL diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index aefe84f9c04b..be69ebb2744e 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -178,6 +178,7 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) * ACK/CTS Timeouts * \******************/ +#if 0 /** * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec * @@ -190,6 +191,7 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TIME_OUT), AR5K_TIME_OUT_ACK)); } +#endif /** * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU @@ -197,7 +199,7 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) * @ah: The &struct ath5k_hw * @timeout: Timeout in usec */ -int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) +static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) { ATH5K_TRACE(ah->ah_sc); if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) @@ -210,6 +212,7 @@ int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) return 0; } +#if 0 /** * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec * @@ -221,6 +224,7 @@ unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TIME_OUT), AR5K_TIME_OUT_CTS)); } +#endif /** * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU @@ -228,7 +232,7 @@ unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) * @ah: The &struct ath5k_hw * @timeout: Timeout in usec */ -int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) +static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) { ATH5K_TRACE(ah->ah_sc); if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) @@ -290,7 +294,7 @@ unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah) * * @ah: The &struct ath5k_hw */ -unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) +static unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) { struct ieee80211_channel *channel = ah->ah_current_channel; @@ -308,7 +312,7 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) * * @ah: The &struct ath5k_hw */ -unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) +static unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) { struct ieee80211_channel *channel = ah->ah_current_channel; @@ -451,6 +455,7 @@ void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); } +#if 0 /* * Set multicast filter by index */ @@ -486,6 +491,7 @@ int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index) return 0; } +#endif /** * ath5k_hw_get_rx_filter - Get current rx filter @@ -571,19 +577,6 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) * Beacon control * \****************/ -/** - * ath5k_hw_get_tsf32 - Get a 32bit TSF - * - * @ah: The &struct ath5k_hw - * - * Returns lower 32 bits of current TSF - */ -u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - return ath5k_hw_reg_read(ah, AR5K_TSF_L32); -} - /** * ath5k_hw_get_tsf64 - Get the full 64bit TSF * @@ -971,6 +964,7 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) return 0; } +#if 0 /* * Check if a table entry is valid */ @@ -983,6 +977,7 @@ int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry) return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) & AR5K_KEYTABLE_VALID; } +#endif static int ath5k_keycache_type(const struct ieee80211_key_conf *key) diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 72474c0ccaff..ac2a57aba6a7 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1190,7 +1190,7 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) * The median of the values in the history is then loaded into the * hardware for its own use for RSSI and CCA measurements. */ -void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) +static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; u32 val; @@ -1767,7 +1767,7 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) * Antenna control * \*****************/ -void /*TODO:Boundary check*/ +static void /*TODO:Boundary check*/ ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) { ATH5K_TRACE(ah->ah_sc); @@ -1776,6 +1776,7 @@ ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); } +#if 0 unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) { ATH5K_TRACE(ah->ah_sc); @@ -1785,6 +1786,7 @@ unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) return false; /*XXX: What do we return for 5210 ?*/ } +#endif /* * Enable/disable fast rx antenna diversity diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 9122a8556f45..d9cab7c3cff7 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -516,6 +516,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) return 0; } +#if 0 /* * Get slot time from DCU */ @@ -532,6 +533,7 @@ unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) return ath5k_hw_clocktoh(ah, slot_time_clock & 0xffff); } +#endif /* * Set slot time on DCU diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index a35a7db0fc4c..8decf2126912 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -221,8 +221,8 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) /* * Sleep control */ -int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, - bool set_chip, u16 sleep_duration) +static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, + bool set_chip, u16 sleep_duration) { unsigned int i; u32 staid, data; -- cgit v1.2.3 From a25d1e4cd7799570ecea6b5dcc4dbf5a6d5336bf Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Thu, 18 Feb 2010 20:28:23 -0500 Subject: ath5k: remove useless "extern" from function declarations Adjust formatting of the affected lines to satisfy checkpatch.pl. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 181 +++++++++++++++++---------------- 1 file changed, 95 insertions(+), 86 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 9e4ea19e7208..f4e50ef84067 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1158,67 +1158,69 @@ struct ath5k_hw { */ /* Attach/Detach Functions */ -extern int ath5k_hw_attach(struct ath5k_softc *sc); -extern void ath5k_hw_detach(struct ath5k_hw *ah); +int ath5k_hw_attach(struct ath5k_softc *sc); +void ath5k_hw_detach(struct ath5k_hw *ah); /* LED functions */ -extern int ath5k_init_leds(struct ath5k_softc *sc); -extern void ath5k_led_enable(struct ath5k_softc *sc); -extern void ath5k_led_off(struct ath5k_softc *sc); -extern void ath5k_unregister_leds(struct ath5k_softc *sc); +int ath5k_init_leds(struct ath5k_softc *sc); +void ath5k_led_enable(struct ath5k_softc *sc); +void ath5k_led_off(struct ath5k_softc *sc); +void ath5k_unregister_leds(struct ath5k_softc *sc); /* Reset Functions */ -extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); -extern int ath5k_hw_on_hold(struct ath5k_hw *ah); -extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel); +int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); +int ath5k_hw_on_hold(struct ath5k_hw *ah); +int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, + struct ieee80211_channel *channel, bool change_channel); /* Power management functions */ /* DMA Related Functions */ -extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); -extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); -extern u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah); -extern void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); -extern int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue); -extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); -extern u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue); -extern int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, +void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); +int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); +u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah); +void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); +int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue); +int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); +u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue); +int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr); -extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); +int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); /* Interrupt handling */ -extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); -extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); -extern enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum -ath5k_int new_mask); -extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats); +bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); +int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); +enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask); +void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, + struct ieee80211_low_level_stats *stats); /* EEPROM access functions */ -extern int ath5k_eeprom_init(struct ath5k_hw *ah); -extern void ath5k_eeprom_detach(struct ath5k_hw *ah); -extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); +int ath5k_eeprom_init(struct ath5k_hw *ah); +void ath5k_eeprom_detach(struct ath5k_hw *ah); +int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); /* Protocol Control Unit Functions */ -extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); -extern void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); +int ath5k_hw_set_opmode(struct ath5k_hw *ah); +void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); /* BSSID Functions */ -extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); -extern void ath5k_hw_set_associd(struct ath5k_hw *ah); -extern void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); +int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); +void ath5k_hw_set_associd(struct ath5k_hw *ah); +void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); /* Receive start/stop functions */ -extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); -extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); +void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); +void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); /* RX Filter functions */ -extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); -extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); -extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); +void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); +u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); +void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); /* Beacon control functions */ -extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); -extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); -extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah); -extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); +u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); +void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); +void ath5k_hw_reset_tsf(struct ath5k_hw *ah); +void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); #if 0 -extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_beacon_state *state); -extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah); -extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr); +int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, + const struct ath5k_beacon_state *state); +void ath5k_hw_reset_beacon(struct ath5k_hw *ah); +int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr); #endif /* ACK bit rate */ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); @@ -1227,73 +1229,80 @@ unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah); /* Key table (WEP) functions */ -extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); -extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac); -extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); +int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); +int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, + const struct ieee80211_key_conf *key, const u8 *mac); +int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); /* Queue Control Unit, DFS Control Unit Functions */ -extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info); -extern int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, - const struct ath5k_txq_info *queue_info); -extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, - enum ath5k_tx_queue queue_type, - struct ath5k_txq_info *queue_info); -extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); -extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); -extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); -extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); +int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, + struct ath5k_txq_info *queue_info); +int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, + const struct ath5k_txq_info *queue_info); +int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, + enum ath5k_tx_queue queue_type, + struct ath5k_txq_info *queue_info); +u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); +void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); +int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); +int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); /* Hardware Descriptor Functions */ -extern int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); +int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); /* GPIO Functions */ -extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); -extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); -extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio); -extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio); -extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); -extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level); +void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); +int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); +int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio); +u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio); +int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); +void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, + u32 interrupt_level); /* rfkill Functions */ -extern void ath5k_rfkill_hw_start(struct ath5k_hw *ah); -extern void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); +void ath5k_rfkill_hw_start(struct ath5k_hw *ah); +void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); /* Misc functions */ int ath5k_hw_set_capabilities(struct ath5k_hw *ah); -extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result); -extern int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); -extern int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); +int ath5k_hw_get_capability(struct ath5k_hw *ah, + enum ath5k_capability_type cap_type, u32 capability, + u32 *result); +int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); +int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); /* Initial register settings functions */ -extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); +int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); /* Initialize RF */ -extern int ath5k_hw_rfregs_init(struct ath5k_hw *ah, - struct ieee80211_channel *channel, - unsigned int mode); -extern int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq); -extern enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); -extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); +int ath5k_hw_rfregs_init(struct ath5k_hw *ah, + struct ieee80211_channel *channel, + unsigned int mode); +int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq); +enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); +int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); /* PHY/RF channel functions */ -extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); -extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); +bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); +int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); /* PHY calibration */ void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); -extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); -extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah); +int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, + struct ieee80211_channel *channel); +void ath5k_hw_calibration_poll(struct ath5k_hw *ah); /* Spur mitigation */ bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, - struct ieee80211_channel *channel); + struct ieee80211_channel *channel); void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, - struct ieee80211_channel *channel); + struct ieee80211_channel *channel); /* Misc PHY functions */ -extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); -extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); +u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); +int ath5k_hw_phy_disable(struct ath5k_hw *ah); /* Antenna control */ -extern void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); +void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); /* TX power setup */ -extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); -extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); +int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, + u8 ee_mode, u8 txpower); +int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); /* * Functions used internaly -- cgit v1.2.3 From ec182d976345b5eb671fe879ad73b90fe29a34e9 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Thu, 18 Feb 2010 20:28:41 -0500 Subject: ath5k: move ath5k_hw_register_timeout() into reset.c ath5k_hw_register_timeout() was duplicated between phy.c and reset.c. Since it is too big and too much used to be an inline function, move it away from the ath5k.h header into reset.c. Remove _ATH5K_RESET and _ATH5K_PHY defines. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 25 ++----------------------- drivers/net/wireless/ath/ath5k/phy.c | 4 ---- drivers/net/wireless/ath/ath5k/reset.c | 25 +++++++++++++++++++++---- 3 files changed, 23 insertions(+), 31 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index f4e50ef84067..4de7fe03b9fc 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1172,6 +1172,8 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); int ath5k_hw_on_hold(struct ath5k_hw *ah); int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel); +int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, + bool is_set); /* Power management functions */ /* DMA Related Functions */ @@ -1328,29 +1330,6 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) iowrite32(val, ah->ah_iobase + reg); } -#if defined(_ATH5K_RESET) || defined(_ATH5K_PHY) -/* - * Check if a register write has been completed - */ -static int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, - u32 val, bool is_set) -{ - int i; - u32 data; - - for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { - data = ath5k_hw_reg_read(ah, reg); - if (is_set && (data & flag)) - break; - else if ((data & flag) == val) - break; - udelay(15); - } - - return (i <= 0) ? -EAGAIN : 0; -} -#endif - static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) { u32 retval = 0, bit, i; diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index ac2a57aba6a7..10ad877c2cdf 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -20,8 +20,6 @@ * */ -#define _ATH5K_PHY - #include #include "ath5k.h" @@ -3144,5 +3142,3 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) return ath5k_hw_txpower(ah, channel, ee_mode, txpower); } - -#undef _ATH5K_PHY diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 8decf2126912..8bd62c130b26 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -19,8 +19,6 @@ * */ -#define _ATH5K_RESET - /*****************************\ Reset functions and helpers \*****************************/ @@ -34,6 +32,27 @@ #include "base.h" #include "debug.h" +/* + * Check if a register write has been completed + */ +int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, + bool is_set) +{ + int i; + u32 data; + + for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { + data = ath5k_hw_reg_read(ah, reg); + if (is_set && (data & flag)) + break; + else if ((data & flag) == val) + break; + udelay(15); + } + + return (i <= 0) ? -EAGAIN : 0; +} + /** * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 * @@ -1386,5 +1405,3 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, return 0; } - -#undef _ATH5K_RESET -- cgit v1.2.3 From d57b87fde86a641da7782b99bec0a3130ed32f4a Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 19 Feb 2010 22:34:39 +0100 Subject: p54: Enable HW_REPORTS_TX_ACK_STATUS P54 devices always generate a full tx_status report (ACK, PSM, rate control, etc..) for every xmitted frame. Therefore, I think The driver qualifies for the REPORTS_TX_ACK_STATUS hardware feature flag. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 4f752a21495f..36f4c820ad01 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -545,6 +545,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_BEACON_FILTER | + IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_NOISE_DBM; dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | -- cgit v1.2.3 From 2d5e82b8bcda58ec1e2fae5277a81e5fd067e627 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Mon, 22 Feb 2010 08:38:21 +0200 Subject: wl1271: Moved module basics to wl1271_spi.c Moved wl1271 drivers probe, remove etc. functions and structres to wl1271_spi.c from wl1271_main.c in preparation of implementing SDIO interface. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_io.h | 8 ++ drivers/net/wireless/wl12xx/wl1271_main.c | 191 +----------------------------- drivers/net/wireless/wl12xx/wl1271_spi.c | 180 ++++++++++++++++++++++++++++ 3 files changed, 193 insertions(+), 186 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index fa9a0b35788f..38fce4caf4a1 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h @@ -65,4 +65,12 @@ static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) wl1271_raw_write(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32), false); } + +/* Functions from wl1271_main.c */ + +int wl1271_register_hw(struct wl1271 *wl); +int wl1271_init_ieee80211(struct wl1271 *wl); +struct ieee80211_hw *wl1271_alloc_hw(void); +int wl1271_free_hw(struct wl1271 *wl); + #endif diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 2a864b24291d..66319aabf263 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -22,16 +22,12 @@ */ #include -#include -#include #include #include -#include #include #include #include #include -#include #include #include "wl1271.h" @@ -484,28 +480,6 @@ out: mutex_unlock(&wl->mutex); } -static irqreturn_t wl1271_irq(int irq, void *cookie) -{ - struct wl1271 *wl; - unsigned long flags; - - wl1271_debug(DEBUG_IRQ, "IRQ"); - - wl = cookie; - - /* complete the ELP completion */ - spin_lock_irqsave(&wl->wl_lock, flags); - if (wl->elp_compl) { - complete(wl->elp_compl); - wl->elp_compl = NULL; - } - - ieee80211_queue_work(wl->hw, &wl->irq_work); - spin_unlock_irqrestore(&wl->wl_lock, flags); - - return IRQ_HANDLED; -} - static int wl1271_fetch_firmware(struct wl1271 *wl) { const struct firmware *fw; @@ -1959,7 +1933,7 @@ static const struct ieee80211_ops wl1271_ops = { CFG80211_TESTMODE_CMD(wl1271_tm_cmd) }; -static int wl1271_register_hw(struct wl1271 *wl) +int wl1271_register_hw(struct wl1271 *wl) { int ret; @@ -1981,7 +1955,7 @@ static int wl1271_register_hw(struct wl1271 *wl) return 0; } -static int wl1271_init_ieee80211(struct wl1271 *wl) +int wl1271_init_ieee80211(struct wl1271 *wl) { /* The tx descriptor buffer and the TKIP space. */ wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + @@ -2009,24 +1983,9 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) return 0; } -static void wl1271_device_release(struct device *dev) -{ - -} - -static struct platform_device wl1271_device = { - .name = "wl1271", - .id = -1, - - /* device model insists to have a release function */ - .dev = { - .release = wl1271_device_release, - }, -}; - #define WL1271_DEFAULT_CHANNEL 0 -static struct ieee80211_hw *wl1271_alloc_hw(void) +struct ieee80211_hw *wl1271_alloc_hw(void) { struct ieee80211_hw *hw; struct wl1271 *wl; @@ -2073,6 +2032,8 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) /* Apply default driver configuration. */ wl1271_conf_init(wl); + wl1271_debugfs_init(wl); + return hw; } @@ -2095,145 +2056,3 @@ int wl1271_free_hw(struct wl1271 *wl) return 0; } - -static int __devinit wl1271_probe(struct spi_device *spi) -{ - struct wl12xx_platform_data *pdata; - struct ieee80211_hw *hw; - struct wl1271 *wl; - int ret; - - pdata = spi->dev.platform_data; - if (!pdata) { - wl1271_error("no platform data"); - return -ENODEV; - } - - hw = wl1271_alloc_hw(); - if (IS_ERR(hw)) - return PTR_ERR(hw); - - wl = hw->priv; - - dev_set_drvdata(&spi->dev, wl); - wl->spi = spi; - - /* This is the only SPI value that we need to set here, the rest - * comes from the board-peripherals file */ - spi->bits_per_word = 32; - - ret = spi_setup(spi); - if (ret < 0) { - wl1271_error("spi_setup failed"); - goto out_free; - } - - wl->set_power = pdata->set_power; - if (!wl->set_power) { - wl1271_error("set power function missing in platform data"); - ret = -ENODEV; - goto out_free; - } - - wl->irq = spi->irq; - if (wl->irq < 0) { - wl1271_error("irq missing in platform data"); - ret = -ENODEV; - goto out_free; - } - - ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); - if (ret < 0) { - wl1271_error("request_irq() failed: %d", ret); - goto out_free; - } - - set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); - - disable_irq(wl->irq); - - ret = platform_device_register(&wl1271_device); - if (ret) { - wl1271_error("couldn't register platform device"); - goto out_irq; - } - dev_set_drvdata(&wl1271_device.dev, wl); - - ret = wl1271_init_ieee80211(wl); - if (ret) - goto out_platform; - - ret = wl1271_register_hw(wl); - if (ret) - goto out_platform; - - wl1271_debugfs_init(wl); - - wl1271_notice("initialized"); - - return 0; - - out_platform: - platform_device_unregister(&wl1271_device); - - out_irq: - free_irq(wl->irq, wl); - - out_free: - ieee80211_free_hw(hw); - - return ret; -} - -static int __devexit wl1271_remove(struct spi_device *spi) -{ - struct wl1271 *wl = dev_get_drvdata(&spi->dev); - - platform_device_unregister(&wl1271_device); - free_irq(wl->irq, wl); - - wl1271_free_hw(wl); - - return 0; -} - - -static struct spi_driver wl1271_spi_driver = { - .driver = { - .name = "wl1271", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = wl1271_probe, - .remove = __devexit_p(wl1271_remove), -}; - -static int __init wl1271_init(void) -{ - int ret; - - ret = spi_register_driver(&wl1271_spi_driver); - if (ret < 0) { - wl1271_error("failed to register spi driver: %d", ret); - goto out; - } - -out: - return ret; -} - -static void __exit wl1271_exit(void) -{ - spi_unregister_driver(&wl1271_spi_driver); - - wl1271_notice("unloaded"); -} - -module_init(wl1271_init); -module_exit(wl1271_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Luciano Coelho "); -MODULE_AUTHOR("Juuso Oikarinen "); -MODULE_FIRMWARE(WL1271_FW_NAME); diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 67a82934f36e..c26726a06237 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c @@ -21,14 +21,17 @@ * */ +#include #include #include #include #include +#include #include "wl1271.h" #include "wl12xx_80211.h" #include "wl1271_spi.h" +#include "wl1271_io.h" void wl1271_spi_reset(struct wl1271 *wl) @@ -255,3 +258,180 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); } + +static irqreturn_t wl1271_irq(int irq, void *cookie) +{ + struct wl1271 *wl; + unsigned long flags; + + wl1271_debug(DEBUG_IRQ, "IRQ"); + + wl = cookie; + + /* complete the ELP completion */ + spin_lock_irqsave(&wl->wl_lock, flags); + if (wl->elp_compl) { + complete(wl->elp_compl); + wl->elp_compl = NULL; + } + + ieee80211_queue_work(wl->hw, &wl->irq_work); + spin_unlock_irqrestore(&wl->wl_lock, flags); + + return IRQ_HANDLED; +} + +static void wl1271_device_release(struct device *dev) +{ + +} + +static struct platform_device wl1271_device = { + .name = "wl1271", + .id = -1, + + /* device model insists to have a release function */ + .dev = { + .release = wl1271_device_release, + }, +}; + +static int __devinit wl1271_probe(struct spi_device *spi) +{ + struct wl12xx_platform_data *pdata; + struct ieee80211_hw *hw; + struct wl1271 *wl; + int ret; + + pdata = spi->dev.platform_data; + if (!pdata) { + wl1271_error("no platform data"); + return -ENODEV; + } + + hw = wl1271_alloc_hw(); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + wl = hw->priv; + + dev_set_drvdata(&spi->dev, wl); + wl->spi = spi; + + /* This is the only SPI value that we need to set here, the rest + * comes from the board-peripherals file */ + spi->bits_per_word = 32; + + ret = spi_setup(spi); + if (ret < 0) { + wl1271_error("spi_setup failed"); + goto out_free; + } + + wl->set_power = pdata->set_power; + if (!wl->set_power) { + wl1271_error("set power function missing in platform data"); + ret = -ENODEV; + goto out_free; + } + + wl->irq = spi->irq; + if (wl->irq < 0) { + wl1271_error("irq missing in platform data"); + ret = -ENODEV; + goto out_free; + } + + ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); + if (ret < 0) { + wl1271_error("request_irq() failed: %d", ret); + goto out_free; + } + + set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); + + disable_irq(wl->irq); + + ret = platform_device_register(&wl1271_device); + if (ret) { + wl1271_error("couldn't register platform device"); + goto out_irq; + } + dev_set_drvdata(&wl1271_device.dev, wl); + + ret = wl1271_init_ieee80211(wl); + if (ret) + goto out_platform; + + ret = wl1271_register_hw(wl); + if (ret) + goto out_platform; + + wl1271_notice("initialized"); + + return 0; + + out_platform: + platform_device_unregister(&wl1271_device); + + out_irq: + free_irq(wl->irq, wl); + + out_free: + ieee80211_free_hw(hw); + + return ret; +} + +static int __devexit wl1271_remove(struct spi_device *spi) +{ + struct wl1271 *wl = dev_get_drvdata(&spi->dev); + + platform_device_unregister(&wl1271_device); + free_irq(wl->irq, wl); + + wl1271_free_hw(wl); + + return 0; +} + + +static struct spi_driver wl1271_spi_driver = { + .driver = { + .name = "wl1271", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + + .probe = wl1271_probe, + .remove = __devexit_p(wl1271_remove), +}; + +static int __init wl1271_init(void) +{ + int ret; + + ret = spi_register_driver(&wl1271_spi_driver); + if (ret < 0) { + wl1271_error("failed to register spi driver: %d", ret); + goto out; + } + +out: + return ret; +} + +static void __exit wl1271_exit(void) +{ + spi_unregister_driver(&wl1271_spi_driver); + + wl1271_notice("unloaded"); +} + +module_init(wl1271_init); +module_exit(wl1271_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Luciano Coelho "); +MODULE_AUTHOR("Juuso Oikarinen "); +MODULE_FIRMWARE(WL1271_FW_NAME); -- cgit v1.2.3 From 54f7e5037c95f2beff0252bfcf288f711c185799 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Mon, 22 Feb 2010 08:38:22 +0200 Subject: wl1271: Added functions to enable/disable interrupt handling Added/moved enable and disable interrupt handling functions. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_boot.c | 2 +- drivers/net/wireless/wl12xx/wl1271_io.c | 10 ++++++++++ drivers/net/wireless/wl12xx/wl1271_io.h | 3 +++ drivers/net/wireless/wl12xx/wl1271_main.c | 5 ----- drivers/net/wireless/wl12xx/wl1271_spi.c | 10 ++++++++++ drivers/net/wireless/wl12xx/wl1271_spi.h | 3 +++ 6 files changed, 27 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 2be76ee42bb9..7d6d2e6c467f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -299,7 +299,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) static void wl1271_boot_enable_interrupts(struct wl1271 *wl) { - enable_irq(wl->irq); + wl1271_enable_interrupts(wl); wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL); diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c index 5cd94d5666c2..b825cfa30ecf 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.c +++ b/drivers/net/wireless/wl12xx/wl1271_io.c @@ -31,6 +31,16 @@ #include "wl1271_spi.h" #include "wl1271_io.h" +void wl1271_disable_interrupts(struct wl1271 *wl) +{ + wl1271_spi_disable_interrupts(wl); +} + +void wl1271_enable_interrupts(struct wl1271 *wl) +{ + wl1271_spi_enable_interrupts(wl); +} + static int wl1271_translate_addr(struct wl1271 *wl, int addr) { /* diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index 38fce4caf4a1..c8b09718e185 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h @@ -27,6 +27,9 @@ struct wl1271; +void wl1271_disable_interrupts(struct wl1271 *wl); +void wl1271_enable_interrupts(struct wl1271 *wl); + void wl1271_io_reset(struct wl1271 *wl); void wl1271_io_init(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 66319aabf263..18347c3a5e19 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -360,11 +360,6 @@ static int wl1271_plt_init(struct wl1271 *wl) return ret; } -static void wl1271_disable_interrupts(struct wl1271 *wl) -{ - disable_irq(wl->irq); -} - static void wl1271_power_off(struct wl1271 *wl) { wl->set_power(false); diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index c26726a06237..b422c9fdcd22 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c @@ -34,6 +34,16 @@ #include "wl1271_io.h" +void wl1271_spi_disable_interrupts(struct wl1271 *wl) +{ + disable_irq(wl->irq); +} + +void wl1271_spi_enable_interrupts(struct wl1271 *wl) +{ + enable_irq(wl->irq); +} + void wl1271_spi_reset(struct wl1271 *wl) { u8 *cmd; diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.h b/drivers/net/wireless/wl12xx/wl1271_spi.h index a803596dad4a..86ff161ef243 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.h +++ b/drivers/net/wireless/wl12xx/wl1271_spi.h @@ -84,6 +84,9 @@ #define OCP_STATUS_REQ_FAILED 0x20000 #define OCP_STATUS_RESP_ERROR 0x30000 +void wl1271_spi_disable_interrupts(struct wl1271 *wl); +void wl1271_spi_enable_interrupts(struct wl1271 *wl); + /* Raw target IO, address is not translated */ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed); -- cgit v1.2.3 From 8197b7118add28f9aaa99c1fb73c0e201c8cde52 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Mon, 22 Feb 2010 08:38:23 +0200 Subject: wl1271: Implemented abstraction of IO functions. Changed the driver to use if_ops structure to abstract access to the IO layer (SPI or SDIO). Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 16 ++++++++++++- drivers/net/wireless/wl12xx/wl1271_io.c | 21 +++++++++++------- drivers/net/wireless/wl12xx/wl1271_io.h | 2 ++ drivers/net/wireless/wl12xx/wl1271_main.c | 6 ++--- drivers/net/wireless/wl12xx/wl1271_spi.c | 37 ++++++++++++++++++++++++------- 5 files changed, 62 insertions(+), 20 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 97ea5096bc8c..10135c94e20e 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -334,11 +334,25 @@ struct wl1271_scan { u8 probe_requests; }; +struct wl1271_if_operations { + void (*read)(struct wl1271 *wl, int addr, void *buf, size_t len, + bool fixed); + void (*write)(struct wl1271 *wl, int addr, void *buf, size_t len, + bool fixed); + void (*reset)(struct wl1271 *wl); + void (*init)(struct wl1271 *wl); + struct device* (*dev)(struct wl1271 *wl); + void (*enable_irq)(struct wl1271 *wl); + void (*disable_irq)(struct wl1271 *wl); +}; + struct wl1271 { struct ieee80211_hw *hw; bool mac80211_registered; - struct spi_device *spi; + void *if_priv; + + struct wl1271_if_operations *if_ops; void (*set_power)(bool enable); int irq; diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c index b825cfa30ecf..d00f7ed7f21c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.c +++ b/drivers/net/wireless/wl12xx/wl1271_io.c @@ -31,14 +31,19 @@ #include "wl1271_spi.h" #include "wl1271_io.h" +struct device *wl1271_wl_to_dev(struct wl1271 *wl) +{ + return wl->if_ops->dev(wl); +} + void wl1271_disable_interrupts(struct wl1271 *wl) { - wl1271_spi_disable_interrupts(wl); + wl->if_ops->disable_irq(wl); } void wl1271_enable_interrupts(struct wl1271 *wl) { - wl1271_spi_enable_interrupts(wl); + wl->if_ops->enable_irq(wl); } static int wl1271_translate_addr(struct wl1271 *wl, int addr) @@ -127,24 +132,24 @@ int wl1271_set_partition(struct wl1271 *wl, void wl1271_io_reset(struct wl1271 *wl) { - wl1271_spi_reset(wl); + wl->if_ops->reset(wl); } void wl1271_io_init(struct wl1271 *wl) { - wl1271_spi_init(wl); + wl->if_ops->init(wl); } void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { - wl1271_spi_raw_write(wl, addr, buf, len, fixed); + wl->if_ops->write(wl, addr, buf, len, fixed); } void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { - wl1271_spi_raw_read(wl, addr, buf, len, fixed); + wl->if_ops->read(wl, addr, buf, len, fixed); } void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len, @@ -154,7 +159,7 @@ void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len, physical = wl1271_translate_addr(wl, addr); - wl1271_spi_raw_read(wl, physical, buf, len, fixed); + wl1271_raw_read(wl, physical, buf, len, fixed); } void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len, @@ -164,7 +169,7 @@ void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len, physical = wl1271_translate_addr(wl, addr); - wl1271_spi_raw_write(wl, physical, buf, len, fixed); + wl1271_raw_write(wl, physical, buf, len, fixed); } u32 wl1271_read32(struct wl1271 *wl, int addr) diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index c8b09718e185..f2b6325ba2a7 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h @@ -33,6 +33,8 @@ void wl1271_enable_interrupts(struct wl1271 *wl); void wl1271_io_reset(struct wl1271 *wl); void wl1271_io_init(struct wl1271 *wl); +struct device *wl1271_wl_to_dev(struct wl1271 *wl); + /* Raw target IO, address is not translated */ void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed); diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 18347c3a5e19..6b3fd0005ce0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -480,7 +480,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) const struct firmware *fw; int ret; - ret = request_firmware(&fw, WL1271_FW_NAME, &wl->spi->dev); + ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); if (ret < 0) { wl1271_error("could not get firmware: %d", ret); @@ -552,7 +552,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) const struct firmware *fw; int ret; - ret = request_firmware(&fw, WL1271_NVS_NAME, &wl->spi->dev); + ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); if (ret < 0) { wl1271_error("could not get nvs file: %d", ret); @@ -1973,7 +1973,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) if (wl1271_11a_enabled()) wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; - SET_IEEE80211_DEV(wl->hw, &wl->spi->dev); + SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); return 0; } diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index b422c9fdcd22..a0f416972be2 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c @@ -33,6 +33,15 @@ #include "wl1271_spi.h" #include "wl1271_io.h" +static struct spi_device *wl_to_spi(struct wl1271 *wl) +{ + return wl->if_priv; +} + +static struct device *wl1271_spi_wl_to_dev(struct wl1271 *wl) +{ + return &(wl_to_spi(wl)->dev); +} void wl1271_spi_disable_interrupts(struct wl1271 *wl) { @@ -65,7 +74,7 @@ void wl1271_spi_reset(struct wl1271 *wl) t.len = WSPI_INIT_CMD_LEN; spi_message_add_tail(&t, &m); - spi_sync(wl->spi, &m); + spi_sync(wl_to_spi(wl), &m); wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); } @@ -119,7 +128,7 @@ void wl1271_spi_init(struct wl1271 *wl) t.len = WSPI_INIT_CMD_LEN; spi_message_add_tail(&t, &m); - spi_sync(wl->spi, &m); + spi_sync(wl_to_spi(wl), &m); wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); } @@ -151,7 +160,7 @@ static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) t[0].rx_buf = buf + (len - num_busy_bytes); t[0].len = num_busy_bytes; spi_message_add_tail(&t[0], &m); - spi_sync(wl->spi, &m); + spi_sync(wl_to_spi(wl), &m); return; } } @@ -171,7 +180,7 @@ static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) t[0].rx_buf = busy_buf; t[0].len = sizeof(u32); spi_message_add_tail(&t[0], &m); - spi_sync(wl->spi, &m); + spi_sync(wl_to_spi(wl), &m); if (*busy_buf & 0x1) { spi_message_init(&m); @@ -179,7 +188,7 @@ static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) t[0].rx_buf = buf; t[0].len = len; spi_message_add_tail(&t[0], &m); - spi_sync(wl->spi, &m); + spi_sync(wl_to_spi(wl), &m); return; } } @@ -225,7 +234,7 @@ void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, t[2].len = len; spi_message_add_tail(&t[2], &m); - spi_sync(wl->spi, &m); + spi_sync(wl_to_spi(wl), &m); /* FIXME: Check busy words, removed due to SPI bug */ /* if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1)) @@ -263,7 +272,7 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, t[1].len = len; spi_message_add_tail(&t[1], &m); - spi_sync(wl->spi, &m); + spi_sync(wl_to_spi(wl), &m); wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); @@ -306,6 +315,16 @@ static struct platform_device wl1271_device = { }, }; +static struct wl1271_if_operations spi_ops = { + .read = wl1271_spi_raw_read, + .write = wl1271_spi_raw_write, + .reset = wl1271_spi_reset, + .init = wl1271_spi_init, + .dev = wl1271_spi_wl_to_dev, + .enable_irq = wl1271_spi_enable_interrupts, + .disable_irq = wl1271_spi_disable_interrupts +}; + static int __devinit wl1271_probe(struct spi_device *spi) { struct wl12xx_platform_data *pdata; @@ -326,7 +345,9 @@ static int __devinit wl1271_probe(struct spi_device *spi) wl = hw->priv; dev_set_drvdata(&spi->dev, wl); - wl->spi = spi; + wl->if_priv = spi; + + wl->if_ops = &spi_ops; /* This is the only SPI value that we need to set here, the rest * comes from the board-peripherals file */ -- cgit v1.2.3 From b42f91ba49ff135392b8f6140e21f85fb0467285 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Mon, 22 Feb 2010 08:38:24 +0200 Subject: wl1271: Inlined IO functions Changed IO functions to static inline. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_io.c | 70 ----------------------- drivers/net/wireless/wl12xx/wl1271_io.h | 96 +++++++++++++++++++++++++------- drivers/net/wireless/wl12xx/wl1271_spi.c | 2 +- 3 files changed, 78 insertions(+), 90 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c index d00f7ed7f21c..c0826585a497 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.c +++ b/drivers/net/wireless/wl12xx/wl1271_io.c @@ -31,11 +31,6 @@ #include "wl1271_spi.h" #include "wl1271_io.h" -struct device *wl1271_wl_to_dev(struct wl1271 *wl) -{ - return wl->if_ops->dev(wl); -} - void wl1271_disable_interrupts(struct wl1271 *wl) { wl->if_ops->disable_irq(wl); @@ -46,29 +41,6 @@ void wl1271_enable_interrupts(struct wl1271 *wl) wl->if_ops->enable_irq(wl); } -static int wl1271_translate_addr(struct wl1271 *wl, int addr) -{ - /* - * To translate, first check to which window of addresses the - * particular address belongs. Then subtract the starting address - * of that window from the address. Then, add offset of the - * translated region. - * - * The translated regions occur next to each other in physical device - * memory, so just add the sizes of the preceeding address regions to - * get the offset to the new region. - * - * Currently, only the two first regions are addressed, and the - * assumption is that all addresses will fall into either of those - * two. - */ - if ((addr >= wl->part.reg.start) && - (addr < wl->part.reg.start + wl->part.reg.size)) - return addr - wl->part.reg.start + wl->part.mem.size; - else - return addr - wl->part.mem.start; -} - /* Set the SPI partitions to access the chip addresses * * To simplify driver code, a fixed (virtual) memory map is defined for @@ -140,48 +112,6 @@ void wl1271_io_init(struct wl1271 *wl) wl->if_ops->init(wl); } -void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed) -{ - wl->if_ops->write(wl, addr, buf, len, fixed); -} - -void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed) -{ - wl->if_ops->read(wl, addr, buf, len, fixed); -} - -void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len, - bool fixed) -{ - int physical; - - physical = wl1271_translate_addr(wl, addr); - - wl1271_raw_read(wl, physical, buf, len, fixed); -} - -void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len, - bool fixed) -{ - int physical; - - physical = wl1271_translate_addr(wl, addr); - - wl1271_raw_write(wl, physical, buf, len, fixed); -} - -u32 wl1271_read32(struct wl1271 *wl, int addr) -{ - return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); -} - -void wl1271_write32(struct wl1271 *wl, int addr, u32 val) -{ - wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); -} - void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) { /* write address >> 1 + 0x30000 to OCP_POR_CTR */ diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index f2b6325ba2a7..8501898950db 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h @@ -33,28 +33,24 @@ void wl1271_enable_interrupts(struct wl1271 *wl); void wl1271_io_reset(struct wl1271 *wl); void wl1271_io_init(struct wl1271 *wl); -struct device *wl1271_wl_to_dev(struct wl1271 *wl); - -/* Raw target IO, address is not translated */ -void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed); -void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed); +static inline struct device *wl1271_wl_to_dev(struct wl1271 *wl) +{ + return wl->if_ops->dev(wl); +} -/* Translated target IO */ -void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len, - bool fixed); -void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len, - bool fixed); -u32 wl1271_read32(struct wl1271 *wl, int addr); -void wl1271_write32(struct wl1271 *wl, int addr, u32 val); -/* Top Register IO */ -void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); -u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); +/* Raw target IO, address is not translated */ +static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed) +{ + wl->if_ops->write(wl, addr, buf, len, fixed); +} -int wl1271_set_partition(struct wl1271 *wl, - struct wl1271_partition_set *p); +static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed) +{ + wl->if_ops->read(wl, addr, buf, len, fixed); +} static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) { @@ -71,6 +67,68 @@ static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) sizeof(wl->buffer_32), false); } +/* Translated target IO */ +static inline int wl1271_translate_addr(struct wl1271 *wl, int addr) +{ + /* + * To translate, first check to which window of addresses the + * particular address belongs. Then subtract the starting address + * of that window from the address. Then, add offset of the + * translated region. + * + * The translated regions occur next to each other in physical device + * memory, so just add the sizes of the preceeding address regions to + * get the offset to the new region. + * + * Currently, only the two first regions are addressed, and the + * assumption is that all addresses will fall into either of those + * two. + */ + if ((addr >= wl->part.reg.start) && + (addr < wl->part.reg.start + wl->part.reg.size)) + return addr - wl->part.reg.start + wl->part.mem.size; + else + return addr - wl->part.mem.start; +} + +static inline void wl1271_read(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed) +{ + int physical; + + physical = wl1271_translate_addr(wl, addr); + + wl1271_raw_read(wl, physical, buf, len, fixed); +} + +static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed) +{ + int physical; + + physical = wl1271_translate_addr(wl, addr); + + wl1271_raw_write(wl, physical, buf, len, fixed); +} + +static inline u32 wl1271_read32(struct wl1271 *wl, int addr) +{ + return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); +} + +static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) +{ + wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); +} + + +/* Top Register IO */ +void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); +u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); + +int wl1271_set_partition(struct wl1271 *wl, + struct wl1271_partition_set *p); + /* Functions from wl1271_main.c */ int wl1271_register_hw(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index a0f416972be2..f89e1b3ac1bb 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c @@ -33,7 +33,7 @@ #include "wl1271_spi.h" #include "wl1271_io.h" -static struct spi_device *wl_to_spi(struct wl1271 *wl) +static inline struct spi_device *wl_to_spi(struct wl1271 *wl) { return wl->if_priv; } -- cgit v1.2.3 From 760d969f9e91a734161a5979a3b3818062e80b7e Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Mon, 22 Feb 2010 08:38:25 +0200 Subject: wl1271: Removed wl1271_spi.h and made some functions static Removed wl1271_spi.h header as there's no more need to access functions declared there outside of wl1271_spi.c. Also made those SPI access functions static. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.c | 1 - drivers/net/wireless/wl12xx/wl1271_boot.c | 1 - drivers/net/wireless/wl12xx/wl1271_cmd.c | 1 - drivers/net/wireless/wl12xx/wl1271_event.c | 1 - drivers/net/wireless/wl12xx/wl1271_io.c | 14 +++- drivers/net/wireless/wl12xx/wl1271_io.h | 17 +++++ drivers/net/wireless/wl12xx/wl1271_main.c | 1 - drivers/net/wireless/wl12xx/wl1271_ps.c | 1 - drivers/net/wireless/wl12xx/wl1271_rx.c | 1 - drivers/net/wireless/wl12xx/wl1271_spi.c | 44 ++++++++++-- drivers/net/wireless/wl12xx/wl1271_spi.h | 99 --------------------------- drivers/net/wireless/wl12xx/wl1271_testmode.c | 1 - drivers/net/wireless/wl12xx/wl1271_tx.c | 1 - 13 files changed, 67 insertions(+), 116 deletions(-) delete mode 100644 drivers/net/wireless/wl12xx/wl1271_spi.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 60f10dce4800..f41f886741f1 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -31,7 +31,6 @@ #include "wl1271.h" #include "wl12xx_80211.h" #include "wl1271_reg.h" -#include "wl1271_spi.h" #include "wl1271_ps.h" int wl1271_acx_wake_up_conditions(struct wl1271 *wl) diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 7d6d2e6c467f..f88d52e87e82 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -26,7 +26,6 @@ #include "wl1271_acx.h" #include "wl1271_reg.h" #include "wl1271_boot.h" -#include "wl1271_spi.h" #include "wl1271_io.h" #include "wl1271_event.h" diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 36a64e06f290..6759aa11c132 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -29,7 +29,6 @@ #include "wl1271.h" #include "wl1271_reg.h" -#include "wl1271_spi.h" #include "wl1271_io.h" #include "wl1271_acx.h" #include "wl12xx_80211.h" diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 7468ef10194b..5533519a1418 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -23,7 +23,6 @@ #include "wl1271.h" #include "wl1271_reg.h" -#include "wl1271_spi.h" #include "wl1271_io.h" #include "wl1271_event.h" #include "wl1271_ps.h" diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c index c0826585a497..c8759acef131 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.c +++ b/drivers/net/wireless/wl12xx/wl1271_io.c @@ -28,9 +28,21 @@ #include "wl1271.h" #include "wl12xx_80211.h" -#include "wl1271_spi.h" #include "wl1271_io.h" +#define OCP_CMD_LOOP 32 + +#define OCP_CMD_WRITE 0x1 +#define OCP_CMD_READ 0x2 + +#define OCP_READY_MASK BIT(18) +#define OCP_STATUS_MASK (BIT(16) | BIT(17)) + +#define OCP_STATUS_NO_RESP 0x00000 +#define OCP_STATUS_OK 0x10000 +#define OCP_STATUS_REQ_FAILED 0x20000 +#define OCP_STATUS_RESP_ERROR 0x30000 + void wl1271_disable_interrupts(struct wl1271 *wl) { wl->if_ops->disable_irq(wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index 8501898950db..95d2168f8af4 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h @@ -25,6 +25,23 @@ #ifndef __WL1271_IO_H__ #define __WL1271_IO_H__ +#include "wl1271_reg.h" + +#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 + +#define HW_PARTITION_REGISTERS_ADDR 0x1FFC0 +#define HW_PART0_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR) +#define HW_PART0_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 4) +#define HW_PART1_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 8) +#define HW_PART1_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 12) +#define HW_PART2_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 16) +#define HW_PART2_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 20) +#define HW_PART3_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 24) + +#define HW_ACCESS_REGISTER_SIZE 4 + +#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 + struct wl1271; void wl1271_disable_interrupts(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 6b3fd0005ce0..54bc1e961cba 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -33,7 +33,6 @@ #include "wl1271.h" #include "wl12xx_80211.h" #include "wl1271_reg.h" -#include "wl1271_spi.h" #include "wl1271_io.h" #include "wl1271_event.h" #include "wl1271_tx.h" diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index e2b1ebf096e8..5a04482b9353 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c @@ -23,7 +23,6 @@ #include "wl1271_reg.h" #include "wl1271_ps.h" -#include "wl1271_spi.h" #include "wl1271_io.h" #define WL1271_WAKEUP_TIMEOUT 500 diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index 6730f5b96e76..b7a7c0621ec1 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c @@ -25,7 +25,6 @@ #include "wl1271_acx.h" #include "wl1271_reg.h" #include "wl1271_rx.h" -#include "wl1271_spi.h" #include "wl1271_io.h" static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index f89e1b3ac1bb..51171d7d5da3 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c @@ -30,9 +30,39 @@ #include "wl1271.h" #include "wl12xx_80211.h" -#include "wl1271_spi.h" #include "wl1271_io.h" +#include "wl1271_reg.h" + +#define WSPI_CMD_READ 0x40000000 +#define WSPI_CMD_WRITE 0x00000000 +#define WSPI_CMD_FIXED 0x20000000 +#define WSPI_CMD_BYTE_LENGTH 0x1FFE0000 +#define WSPI_CMD_BYTE_LENGTH_OFFSET 17 +#define WSPI_CMD_BYTE_ADDR 0x0001FFFF + +#define WSPI_INIT_CMD_CRC_LEN 5 + +#define WSPI_INIT_CMD_START 0x00 +#define WSPI_INIT_CMD_TX 0x40 +/* the extra bypass bit is sampled by the TNET as '1' */ +#define WSPI_INIT_CMD_BYPASS_BIT 0x80 +#define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07 +#define WSPI_INIT_CMD_EN_FIXEDBUSY 0x80 +#define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00 +#define WSPI_INIT_CMD_IOD 0x40 +#define WSPI_INIT_CMD_IP 0x20 +#define WSPI_INIT_CMD_CS 0x10 +#define WSPI_INIT_CMD_WS 0x08 +#define WSPI_INIT_CMD_WSPI 0x01 +#define WSPI_INIT_CMD_END 0x01 + +#define WSPI_INIT_CMD_LEN 8 + +#define HW_ACCESS_WSPI_FIXED_BUSY_LEN \ + ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) +#define HW_ACCESS_WSPI_INIT_CMD_MASK 0 + static inline struct spi_device *wl_to_spi(struct wl1271 *wl) { return wl->if_priv; @@ -43,17 +73,17 @@ static struct device *wl1271_spi_wl_to_dev(struct wl1271 *wl) return &(wl_to_spi(wl)->dev); } -void wl1271_spi_disable_interrupts(struct wl1271 *wl) +static void wl1271_spi_disable_interrupts(struct wl1271 *wl) { disable_irq(wl->irq); } -void wl1271_spi_enable_interrupts(struct wl1271 *wl) +static void wl1271_spi_enable_interrupts(struct wl1271 *wl) { enable_irq(wl->irq); } -void wl1271_spi_reset(struct wl1271 *wl) +static void wl1271_spi_reset(struct wl1271 *wl) { u8 *cmd; struct spi_transfer t; @@ -79,7 +109,7 @@ void wl1271_spi_reset(struct wl1271 *wl) wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); } -void wl1271_spi_init(struct wl1271 *wl) +static void wl1271_spi_init(struct wl1271 *wl) { u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; struct spi_transfer t; @@ -199,7 +229,7 @@ static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) } #endif -void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, +static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { struct spi_transfer t[3]; @@ -244,7 +274,7 @@ void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); } -void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, +static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { struct spi_transfer t[2]; diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.h b/drivers/net/wireless/wl12xx/wl1271_spi.h deleted file mode 100644 index 86ff161ef243..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_spi.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1271_SPI_H__ -#define __WL1271_SPI_H__ - -#include "wl1271_reg.h" - -#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 - -#define HW_PARTITION_REGISTERS_ADDR 0x1ffc0 -#define HW_PART0_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR) -#define HW_PART0_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 4) -#define HW_PART1_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 8) -#define HW_PART1_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 12) -#define HW_PART2_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 16) -#define HW_PART2_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 20) -#define HW_PART3_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 24) - -#define HW_ACCESS_REGISTER_SIZE 4 - -#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 - -#define WSPI_CMD_READ 0x40000000 -#define WSPI_CMD_WRITE 0x00000000 -#define WSPI_CMD_FIXED 0x20000000 -#define WSPI_CMD_BYTE_LENGTH 0x1FFE0000 -#define WSPI_CMD_BYTE_LENGTH_OFFSET 17 -#define WSPI_CMD_BYTE_ADDR 0x0001FFFF - -#define WSPI_INIT_CMD_CRC_LEN 5 - -#define WSPI_INIT_CMD_START 0x00 -#define WSPI_INIT_CMD_TX 0x40 -/* the extra bypass bit is sampled by the TNET as '1' */ -#define WSPI_INIT_CMD_BYPASS_BIT 0x80 -#define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07 -#define WSPI_INIT_CMD_EN_FIXEDBUSY 0x80 -#define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00 -#define WSPI_INIT_CMD_IOD 0x40 -#define WSPI_INIT_CMD_IP 0x20 -#define WSPI_INIT_CMD_CS 0x10 -#define WSPI_INIT_CMD_WS 0x08 -#define WSPI_INIT_CMD_WSPI 0x01 -#define WSPI_INIT_CMD_END 0x01 - -#define WSPI_INIT_CMD_LEN 8 - -#define HW_ACCESS_WSPI_FIXED_BUSY_LEN \ - ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) -#define HW_ACCESS_WSPI_INIT_CMD_MASK 0 - -#define OCP_CMD_LOOP 32 - -#define OCP_CMD_WRITE 0x1 -#define OCP_CMD_READ 0x2 - -#define OCP_READY_MASK BIT(18) -#define OCP_STATUS_MASK (BIT(16) | BIT(17)) - -#define OCP_STATUS_NO_RESP 0x00000 -#define OCP_STATUS_OK 0x10000 -#define OCP_STATUS_REQ_FAILED 0x20000 -#define OCP_STATUS_RESP_ERROR 0x30000 - -void wl1271_spi_disable_interrupts(struct wl1271 *wl); -void wl1271_spi_enable_interrupts(struct wl1271 *wl); - -/* Raw target IO, address is not translated */ -void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed); -void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed); - -/* INIT and RESET words */ -void wl1271_spi_reset(struct wl1271 *wl); -void wl1271_spi_init(struct wl1271 *wl); -#endif /* __WL1271_SPI_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c index 3919102e942e..2401e6035d51 100644 --- a/drivers/net/wireless/wl12xx/wl1271_testmode.c +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c @@ -25,7 +25,6 @@ #include #include "wl1271.h" -#include "wl1271_spi.h" #include "wl1271_acx.h" #define WL1271_TM_MAX_DATA_LENGTH 1024 diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 811e739d05bf..2b7dd9b76fe1 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -25,7 +25,6 @@ #include #include "wl1271.h" -#include "wl1271_spi.h" #include "wl1271_io.h" #include "wl1271_reg.h" #include "wl1271_ps.h" -- cgit v1.2.3 From 50b3eb4bdda4690fc2848079f209b8d605c89fb5 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Mon, 22 Feb 2010 08:38:26 +0200 Subject: wl1271: Divided driver to two separate modules Divided wl1271 driver to wl1271 "core" and wl1271_spi modules in preparation of integration of the SDIO implementation. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/Kconfig | 12 ++++++++++++ drivers/net/wireless/wl12xx/Makefile | 5 +++-- drivers/net/wireless/wl12xx/wl1271_main.c | 8 ++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 785e0244e305..9c6fdccf00f1 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig @@ -51,3 +51,15 @@ config WL1271 If you choose to build a module, it'll be called wl1271. Say N if unsure. + +config WL1271_SPI + tristate "TI wl1251 SPI support" + depends on WL1271 && SPI_MASTER + ---help--- + This module adds support for the SPI interface of adapters using + TI wl1271 chipset. Select this if your platform is using + the SPI bus. + + If you choose to build a module, it'll be called wl1251_spi. + Say N if unsure. + diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index f47ec94c16dc..473a1e287997 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile @@ -7,10 +7,11 @@ obj-$(CONFIG_WL1251) += wl1251.o obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o -wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ +wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \ wl1271_event.o wl1271_tx.o wl1271_rx.o \ wl1271_ps.o wl1271_acx.o wl1271_boot.o \ - wl1271_init.o wl1271_debugfs.o wl1271_io.o + wl1271_init.o wl1271_debugfs.o wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o obj-$(CONFIG_WL1271) += wl1271.o +obj-$(CONFIG_WL1271_SPI) += wl1271_spi.o diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 54bc1e961cba..ea49cede4cb1 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1948,6 +1948,7 @@ int wl1271_register_hw(struct wl1271 *wl) return 0; } +EXPORT_SYMBOL_GPL(wl1271_register_hw); int wl1271_init_ieee80211(struct wl1271 *wl) { @@ -1976,6 +1977,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) return 0; } +EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); #define WL1271_DEFAULT_CHANNEL 0 @@ -2030,6 +2032,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) return hw; } +EXPORT_SYMBOL_GPL(wl1271_alloc_hw); int wl1271_free_hw(struct wl1271 *wl) { @@ -2050,3 +2053,8 @@ int wl1271_free_hw(struct wl1271 *wl) return 0; } +EXPORT_SYMBOL_GPL(wl1271_free_hw); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Luciano Coelho "); +MODULE_AUTHOR("Juuso Oikarinen "); -- cgit v1.2.3 From 5129dffebd4eab1749e63bb4a1b7abdc92903227 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Mon, 22 Feb 2010 08:38:27 +0200 Subject: wl1271: Initial SDIO implementation Added initial implementation of SDIO interfacte to the wl1271 driver. When selected, this adds new module called "wl1271_sdio". Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/Kconfig | 12 ++ drivers/net/wireless/wl12xx/Makefile | 1 + drivers/net/wireless/wl12xx/wl1271_sdio.c | 302 ++++++++++++++++++++++++++++++ 3 files changed, 315 insertions(+) create mode 100644 drivers/net/wireless/wl12xx/wl1271_sdio.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 9c6fdccf00f1..2f6733526f7f 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig @@ -63,3 +63,15 @@ config WL1271_SPI If you choose to build a module, it'll be called wl1251_spi. Say N if unsure. +config WL1271_SDIO + tristate "TI wl1271 SDIO support" + depends on WL1271 && MMC + ---help--- + This module adds support for the SDIO interface of adapters using + TI wl1271 chipset. Select this if your platform is using + the SDIO bus. + + If you choose to build a module, it'll be called + wl1271_sdio. Say N if unsure. + + diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index 473a1e287997..27ddd2be0a91 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile @@ -15,3 +15,4 @@ wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \ wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o obj-$(CONFIG_WL1271) += wl1271.o obj-$(CONFIG_WL1271_SPI) += wl1271_spi.o +obj-$(CONFIG_WL1271_SDIO) += wl1271_sdio.o diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c new file mode 100644 index 000000000000..be5c14935bc3 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c @@ -0,0 +1,302 @@ +/* + * This file is part of wl1271 + * + * Copyright (C) 2009-2010 Nokia Corporation + * + * Contact: Luciano Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wl1271.h" +#include "wl12xx_80211.h" +#include "wl1271_io.h" + + +#define RX71_WL1271_IRQ_GPIO 42 + +#ifndef SDIO_VENDOR_ID_TI +#define SDIO_VENDOR_ID_TI 0x0097 +#endif + +#ifndef SDIO_DEVICE_ID_TI_WL1271 +#define SDIO_DEVICE_ID_TI_WL1271 0x4076 +#endif + +static const struct sdio_device_id wl1271_devices[] = { + { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) }, + {} +}; +MODULE_DEVICE_TABLE(sdio, wl1271_devices); + +static inline struct sdio_func *wl_to_func(struct wl1271 *wl) +{ + return wl->if_priv; +} + +static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl) +{ + return &(wl_to_func(wl)->dev); +} + +static irqreturn_t wl1271_irq(int irq, void *cookie) +{ + struct wl1271 *wl = cookie; + unsigned long flags; + + wl1271_debug(DEBUG_IRQ, "IRQ"); + + /* complete the ELP completion */ + spin_lock_irqsave(&wl->wl_lock, flags); + if (wl->elp_compl) { + complete(wl->elp_compl); + wl->elp_compl = NULL; + } + + ieee80211_queue_work(wl->hw, &wl->irq_work); + spin_unlock_irqrestore(&wl->wl_lock, flags); + + return IRQ_HANDLED; +} + +static void wl1271_sdio_disable_interrupts(struct wl1271 *wl) +{ + disable_irq(wl->irq); +} + +static void wl1271_sdio_enable_interrupts(struct wl1271 *wl) +{ + enable_irq(wl->irq); +} + +static void wl1271_sdio_reset(struct wl1271 *wl) +{ +} + +static void wl1271_sdio_init(struct wl1271 *wl) +{ +} + +static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed) +{ + int ret; + struct sdio_func *func = wl_to_func(wl); + + sdio_claim_host(func); + if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { + ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); + wl1271_debug(DEBUG_SPI, "sdio read 52 addr 0x%x, byte 0x%02x", + addr, ((u8 *)buf)[0]); + } else { + if (fixed) + ret = sdio_readsb(func, buf, addr, len); + else + ret = sdio_memcpy_fromio(func, buf, addr, len); + + wl1271_debug(DEBUG_SPI, "sdio read 53 addr 0x%x, %d bytes", + addr, len); + wl1271_dump_ascii(DEBUG_SPI, "data: ", buf, len); + } + + if (ret) + wl1271_error("sdio read failed (%d)", ret); + + sdio_release_host(func); +} + +static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed) +{ + int ret; + struct sdio_func *func = wl_to_func(wl); + + sdio_claim_host(func); + if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { + sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); + wl1271_debug(DEBUG_SPI, "sdio write 52 addr 0x%x, byte 0x%02x", + addr, ((u8 *)buf)[0]); + } else { + wl1271_debug(DEBUG_SPI, "sdio write 53 addr 0x%x, %d bytes", + addr, len); + wl1271_dump_ascii(DEBUG_SPI, "data: ", buf, len); + + if (fixed) + ret = sdio_writesb(func, addr, buf, len); + else + ret = sdio_memcpy_toio(func, addr, buf, len); + } + if (ret) + wl1271_error("sdio write failed (%d)", ret); + + sdio_release_host(func); +} + +static struct wl1271_if_operations sdio_ops = { + .read = wl1271_sdio_raw_read, + .write = wl1271_sdio_raw_write, + .reset = wl1271_sdio_reset, + .init = wl1271_sdio_init, + .dev = wl1271_sdio_wl_to_dev, + .enable_irq = wl1271_sdio_enable_interrupts, + .disable_irq = wl1271_sdio_disable_interrupts +}; + +static void wl1271_sdio_set_power(bool enable) +{ +} + +static int __devinit wl1271_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + struct ieee80211_hw *hw; + struct wl1271 *wl; + int ret; + + /* We are only able to handle the wlan function */ + if (func->num != 0x02) + return -ENODEV; + + hw = wl1271_alloc_hw(); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + wl = hw->priv; + + wl->if_priv = func; + wl->if_ops = &sdio_ops; + + wl->set_power = wl1271_sdio_set_power; + + /* Grab access to FN0 for ELP reg. */ + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + + wl->irq = gpio_to_irq(RX71_WL1271_IRQ_GPIO); + if (wl->irq < 0) { + ret = wl->irq; + wl1271_error("could not get irq!"); + goto out_free; + } + + ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); + if (ret < 0) { + wl1271_error("request_irq() failed: %d", ret); + goto out_free; + } + + set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); + + disable_irq(wl->irq); + + ret = wl1271_init_ieee80211(wl); + if (ret) + goto out_irq; + + ret = wl1271_register_hw(wl); + if (ret) + goto out_irq; + + sdio_claim_host(func); + ret = sdio_enable_func(func); + if (ret) + goto out_release; + + sdio_release_host(func); + + wl1271_notice("initialized"); + + return 0; + + out_release: + sdio_release_host(func); + + out_irq: + free_irq(wl->irq, wl); + + + out_free: + ieee80211_free_hw(hw); + + return ret; +} + +static void __devexit wl1271_remove(struct sdio_func *func) +{ + struct wl1271 *wl = sdio_get_drvdata(func); + + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); + ieee80211_unregister_hw(wl->hw); + + free_irq(wl->irq, wl); + + kfree(wl->target_mem_map); + vfree(wl->fw); + wl->fw = NULL; + kfree(wl->nvs); + wl->nvs = NULL; + + kfree(wl->fw_status); + kfree(wl->tx_res_if); + + ieee80211_free_hw(wl->hw); +} + +static struct sdio_driver wl1271_sdio_driver = { + .name = "wl1271", + .id_table = wl1271_devices, + .probe = wl1271_probe, + .remove = __devexit_p(wl1271_remove), +}; + +static int __init wl1271_init(void) +{ + int ret; + + ret = sdio_register_driver(&wl1271_sdio_driver); + if (ret < 0) { + wl1271_error("failed to register sdio driver: %d", ret); + goto out; + } + +out: + return ret; +} + +static void __exit wl1271_exit(void) +{ + sdio_unregister_driver(&wl1271_sdio_driver); + + wl1271_notice("unloaded"); +} + +module_init(wl1271_init); +module_exit(wl1271_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Luciano Coelho "); +MODULE_AUTHOR("Juuso Oikarinen "); +MODULE_FIRMWARE(WL1271_FW_NAME); -- cgit v1.2.3 From 09a9c2b3f464e757b6597f621cc3bedb6f040a27 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Mon, 22 Feb 2010 08:38:28 +0200 Subject: wl1271: Changed access to fw status register to use raw read Changed access to fw status register to use raw read instead of translated addressing. On SDIO access by translated addressing was not working and raw access is working also on SPI. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index ea49cede4cb1..310f58c66231 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -377,7 +377,7 @@ static void wl1271_fw_status(struct wl1271 *wl, u32 total = 0; int i; - wl1271_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); + wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " "drv_rx_counter = %d, tx_results_counter = %d)", -- cgit v1.2.3 From 49d7f6d8113a04abacdf99525db9c17d872c1efa Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Mon, 22 Feb 2010 08:38:29 +0200 Subject: wl1271: Fixed unloading of the wl1271_sdio module Fixed two bugs causing problems when unloding wl1271 module. First was missing sdio_set_drvdata call from the probe function, second was order of function calls in the remove function. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_sdio.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index be5c14935bc3..7d7c85041859 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c @@ -219,6 +219,8 @@ static int __devinit wl1271_probe(struct sdio_func *func, goto out_irq; sdio_claim_host(func); + sdio_set_drvdata(func, wl); + ret = sdio_enable_func(func); if (ret) goto out_release; @@ -246,10 +248,11 @@ static void __devexit wl1271_remove(struct sdio_func *func) { struct wl1271 *wl = sdio_get_drvdata(func); + ieee80211_unregister_hw(wl->hw); + sdio_claim_host(func); sdio_disable_func(func); sdio_release_host(func); - ieee80211_unregister_hw(wl->hw); free_irq(wl->irq, wl); -- cgit v1.2.3 From 93c5bb68c89eff0cd41afce8ac932d12cc9d7ae8 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 22 Feb 2010 08:38:30 +0200 Subject: wl1271: don't get received frames from hardware in PLT mode Most probably patch "wl1271: add most of the normal initialization commands to PLT mode" enabled the RX path in firmware so that now driver received frames and passed them to mac80211, which warned about them. Workaround this by not retrieving frames from the hardware, just ignore them. Signed-off-by: Kalle Valo Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_rx.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index b7a7c0621ec1..2df7852db9a5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c @@ -159,6 +159,13 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) u8 *buf; u8 beacon = 0; + /* + * In PLT mode we seem to get frames and mac80211 warns about them, + * workaround this by not retrieving them at all. + */ + if (unlikely(wl->state == WL1271_STATE_PLT)) + return; + skb = __dev_alloc_skb(length, GFP_KERNEL); if (!skb) { wl1271_error("Couldn't allocate RX frame"); -- cgit v1.2.3 From ffb591cd0e32d817bdbd359dead3baa770b999f8 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Mon, 22 Feb 2010 08:38:31 +0200 Subject: wl1271: Improvements to the TX path - Fix a TX result overflow problem that was present in the TX path and visible with at least linksys AP's (probably any AP with high throughput capability.) - Optimize TX by writing FW trigger for a group of TX frames instead of each and every frame. - Slightly optimize the TX path code. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 4 ++-- drivers/net/wireless/wl12xx/wl1271_main.c | 8 +++---- drivers/net/wireless/wl12xx/wl1271_tx.c | 38 +++++++++++++++++++------------ drivers/net/wireless/wl12xx/wl1271_tx.h | 2 +- 4 files changed, 29 insertions(+), 23 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 10135c94e20e..cc974eae009e 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -396,10 +396,10 @@ struct wl1271 { /* Accounting for allocated / available TX blocks on HW */ u32 tx_blocks_freed[NUM_TX_QUEUES]; u32 tx_blocks_available; - u8 tx_results_count; + u32 tx_results_count; /* Transmitted TX packets counter for chipset interface */ - int tx_packets_count; + u32 tx_packets_count; /* Time-offset between host and chipset clocks */ int time_offset; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 310f58c66231..5cc778f658b9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -453,14 +453,12 @@ static void wl1271_irq_work(struct work_struct *work) wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); if (intr & WL1271_ACX_INTR_DATA) { - u8 tx_res_cnt = wl->fw_status->tx_results_counter - - wl->tx_results_count; - wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); /* check for tx results */ - if (tx_res_cnt) - wl1271_tx_complete(wl, tx_res_cnt); + if (wl->fw_status->tx_results_counter != + (wl->tx_results_count & 0xff)) + wl1271_tx_complete(wl); wl1271_rx(wl, wl->fw_status); } diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 2b7dd9b76fe1..2e057b0e3257 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -169,7 +169,6 @@ static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb, /* write packet new counter into the write access register */ wl->tx_packets_count++; - wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); desc = (struct wl1271_tx_hw_descr *) skb->data; wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", @@ -244,6 +243,7 @@ void wl1271_tx_work(struct work_struct *work) struct sk_buff *skb; bool woken_up = false; u32 sta_rates = 0; + u32 prev_tx_packets_count; int ret; /* check if the rates supported by the AP have changed */ @@ -260,6 +260,8 @@ void wl1271_tx_work(struct work_struct *work) if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; + prev_tx_packets_count = wl->tx_packets_count; + /* if rates have changed, re-configure the rate policy */ if (unlikely(sta_rates)) { wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); @@ -270,7 +272,7 @@ void wl1271_tx_work(struct work_struct *work) if (!woken_up) { ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) - goto out; + goto out_ack; woken_up = true; } @@ -282,10 +284,10 @@ void wl1271_tx_work(struct work_struct *work) ieee80211_stop_queues(wl->hw); set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); skb_queue_head(&wl->tx_queue, skb); - goto out; + goto out_ack; } else if (ret < 0) { dev_kfree_skb(skb); - goto out; + goto out_ack; } else if (test_and_clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags)) { /* firmware buffer has space, restart queues */ @@ -295,6 +297,11 @@ void wl1271_tx_work(struct work_struct *work) } } +out_ack: + /* interrupt the firmware with the new packets */ + if (prev_tx_packets_count != wl->tx_packets_count) + wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); + out: if (woken_up) wl1271_ps_elp_sleep(wl); @@ -311,7 +318,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, int id = result->id; /* check for id legality */ - if (id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL) { + if (unlikely(id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL)) { wl1271_warning("TX result illegal id: %d", id); return; } @@ -366,10 +373,11 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, } /* Called upon reception of a TX complete interrupt */ -void wl1271_tx_complete(struct wl1271 *wl, u32 count) +void wl1271_tx_complete(struct wl1271 *wl) { struct wl1271_acx_mem_map *memmap = (struct wl1271_acx_mem_map *)wl->target_mem_map; + u32 count, fw_counter; u32 i; wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); @@ -377,12 +385,18 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count) /* read the tx results from the chipset */ wl1271_read(wl, le32_to_cpu(memmap->tx_result), wl->tx_res_if, sizeof(*wl->tx_res_if), false); + fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter); + + /* write host counter to chipset (to ack) */ + wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + + offsetof(struct wl1271_tx_hw_res_if, + tx_result_host_counter), fw_counter); + + count = fw_counter - wl->tx_results_count; /* verify that the result buffer is not getting overrun */ - if (count > TX_HW_RESULT_QUEUE_LEN) { + if (unlikely(count > TX_HW_RESULT_QUEUE_LEN)) wl1271_warning("TX result overflow from chipset: %d", count); - count = TX_HW_RESULT_QUEUE_LEN; - } /* process the results */ for (i = 0; i < count; i++) { @@ -395,12 +409,6 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count) wl->tx_results_count++; } - - /* write host counter to chipset (to ack) */ - wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + - offsetof(struct wl1271_tx_hw_res_if, - tx_result_host_counter), - le32_to_cpu(wl->tx_res_if->tx_result_fw_counter)); } /* caller must hold wl->mutex */ diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 17e405a09caa..ca92bd811292 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h @@ -160,7 +160,7 @@ static inline int wl1271_tx_ac_to_tid(int ac) } void wl1271_tx_work(struct work_struct *work); -void wl1271_tx_complete(struct wl1271 *wl, u32 count); +void wl1271_tx_complete(struct wl1271 *wl); void wl1271_tx_flush(struct wl1271 *wl); #endif -- cgit v1.2.3 From 15305498a443c181c8fb5deafb94eae585fe3ad5 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Mon, 22 Feb 2010 08:38:32 +0200 Subject: wl1271: Fix ad-hoc mode neighborhood detection This patch fixes a bug in ad-hoc mode preventing mac80211 from properly detecting other ad-hoc networks with the same SSID. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 4 ++-- drivers/net/wireless/wl12xx/wl1271_cmd.h | 2 +- drivers/net/wireless/wl12xx/wl1271_main.c | 15 +++++++-------- 3 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 6759aa11c132..e029bf03809d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -247,7 +247,7 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) return ret; } -int wl1271_cmd_join(struct wl1271 *wl) +int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) { static bool do_cal = true; struct wl1271_cmd_join *join; @@ -278,7 +278,7 @@ int wl1271_cmd_join(struct wl1271 *wl) join->rx_config_options = cpu_to_le32(wl->rx_config); join->rx_filter_options = cpu_to_le32(wl->rx_filter); - join->bss_type = wl->bss_type; + join->bss_type = bss_type; /* * FIXME: disable temporarily all filters because after commit diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 2dc06c73532b..4297205b8d6d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -33,7 +33,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, size_t res_len); int wl1271_cmd_general_parms(struct wl1271 *wl); int wl1271_cmd_radio_parms(struct wl1271 *wl); -int wl1271_cmd_join(struct wl1271 *wl); +int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 5cc778f658b9..81fb02e82923 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1093,7 +1093,7 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw, memcpy(wl->bssid, conf->bssid, ETH_ALEN); - ret = wl1271_cmd_join(wl); + ret = wl1271_cmd_join(wl, wl->bss_type); if (ret < 0) goto out_sleep; @@ -1142,17 +1142,16 @@ static int wl1271_join_channel(struct wl1271 *wl, int channel) static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, 0xad, 0xbe, 0xef }; - /* the dummy join is not required for ad-hoc */ - if (wl->bss_type == BSS_TYPE_IBSS) - goto out; - /* disable mac filter, so we hear everything */ wl->rx_config &= ~CFG_BSSID_FILTER_EN; wl->channel = channel; memcpy(wl->bssid, dummy_bssid, ETH_ALEN); - ret = wl1271_cmd_join(wl); + /* the dummy join is performed always with STATION BSS type to allow + also ad-hoc mode to listen to the surroundings without sending any + beacons yet. */ + ret = wl1271_cmd_join(wl, BSS_TYPE_STA_BSS); if (ret < 0) goto out; @@ -1221,7 +1220,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) test_bit(WL1271_FLAG_JOINED, &wl->flags)) { wl->channel = channel; /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ - ret = wl1271_cmd_join(wl); + ret = wl1271_cmd_join(wl, wl->bss_type); if (ret < 0) wl1271_warning("cmd join to update channel failed %d", ret); @@ -1704,7 +1703,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } if (do_join) { - ret = wl1271_cmd_join(wl); + ret = wl1271_cmd_join(wl, wl->bss_type); if (ret < 0) { wl1271_warning("cmd join failed %d", ret); goto out_sleep; -- cgit v1.2.3 From 06f7bc7db79fabe6b2ec16eff0f59e4acc21eb72 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Mon, 22 Feb 2010 08:38:33 +0200 Subject: wl1271: Fix queue stopping/waking for TX path The queue stopping/waking functionality was broken in a way that could cause huge latencies in TX transfers and even cause the TX to stall in the right circumstances. Correct these problems. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 3 ++- drivers/net/wireless/wl12xx/wl1271_main.c | 12 +++++------- drivers/net/wireless/wl12xx/wl1271_tx.c | 28 +++++++++++++++------------- 3 files changed, 22 insertions(+), 21 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index cc974eae009e..7f03f899b2b0 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -491,7 +491,8 @@ int wl1271_plt_stop(struct wl1271 *wl); #define WL1271_DEFAULT_POWER_LEVEL 0 -#define WL1271_TX_QUEUE_MAX_LENGTH 20 +#define WL1271_TX_QUEUE_LOW_WATERMARK 10 +#define WL1271_TX_QUEUE_HIGH_WATERMARK 25 /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power on in case is has been shut down shortly before */ diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 81fb02e82923..184264a53b20 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -791,15 +791,13 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * The workqueue is slow to process the tx_queue and we need stop * the queue here, otherwise the queue will get too long. */ - if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_MAX_LENGTH) { - ieee80211_stop_queues(wl->hw); + if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_HIGH_WATERMARK) { + wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); - /* - * FIXME: this is racy, the variable is not properly - * protected. Maybe fix this by removing the stupid - * variable altogether and checking the real queue state? - */ + spin_lock_irqsave(&wl->wl_lock, flags); + ieee80211_stop_queues(wl->hw); set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); + spin_unlock_irqrestore(&wl->wl_lock, flags); } return NETDEV_TX_OK; diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 2e057b0e3257..7926471cd095 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -278,22 +278,12 @@ void wl1271_tx_work(struct work_struct *work) ret = wl1271_tx_frame(wl, skb); if (ret == -EBUSY) { - /* firmware buffer is full, stop queues */ - wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, " - "stop queues"); - ieee80211_stop_queues(wl->hw); - set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); + /* firmware buffer is full, lets stop transmitting. */ skb_queue_head(&wl->tx_queue, skb); goto out_ack; } else if (ret < 0) { dev_kfree_skb(skb); goto out_ack; - } else if (test_and_clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, - &wl->flags)) { - /* firmware buffer has space, restart queues */ - wl1271_debug(DEBUG_TX, - "complete_packet: waking queues"); - ieee80211_wake_queues(wl->hw); } } @@ -380,8 +370,6 @@ void wl1271_tx_complete(struct wl1271 *wl) u32 count, fw_counter; u32 i; - wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); - /* read the tx results from the chipset */ wl1271_read(wl, le32_to_cpu(memmap->tx_result), wl->tx_res_if, sizeof(*wl->tx_res_if), false); @@ -393,6 +381,7 @@ void wl1271_tx_complete(struct wl1271 *wl) tx_result_host_counter), fw_counter); count = fw_counter - wl->tx_results_count; + wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); /* verify that the result buffer is not getting overrun */ if (unlikely(count > TX_HW_RESULT_QUEUE_LEN)) @@ -409,6 +398,19 @@ void wl1271_tx_complete(struct wl1271 *wl) wl->tx_results_count++; } + + if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && + skb_queue_len(&wl->tx_queue) <= WL1271_TX_QUEUE_LOW_WATERMARK) { + unsigned long flags; + + /* firmware buffer has space, restart queues */ + wl1271_debug(DEBUG_TX, "tx_complete: waking queues"); + spin_lock_irqsave(&wl->wl_lock, flags); + ieee80211_wake_queues(wl->hw); + clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); + spin_unlock_irqrestore(&wl->wl_lock, flags); + ieee80211_queue_work(wl->hw, &wl->tx_work); + } } /* caller must hold wl->mutex */ -- cgit v1.2.3 From 18f8d468919da89185e2ab90cefa6c4a1936038e Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Mon, 22 Feb 2010 08:38:34 +0200 Subject: wl1271: Remove annoying PSM entry/exit kernel traces Remove the annoying and dmesg-flooding WLAN PSM entry/exit traces. Instead, only output them if PSM traces are enabled. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 184264a53b20..4d091ebd3403 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1235,13 +1235,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) * through the bss_info_changed() hook. */ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { - wl1271_info("psm enabled"); + wl1271_debug(DEBUG_PSM, "psm enabled"); ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, true); } } else if (!(conf->flags & IEEE80211_CONF_PS) && test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { - wl1271_info("psm disabled"); + wl1271_debug(DEBUG_PSM, "psm disabled"); clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); -- cgit v1.2.3 From 295cc0bff60bee988028dc431fa1f1a353fd18a7 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Mon, 22 Feb 2010 08:38:35 +0200 Subject: wl1271: Aggregate RX acknowledgements to FW This patch will ack RX frames read from the firmware in one single write, instead of acking all the frames separately. This will reduce the amount of required communication per frame. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_rx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index 2df7852db9a5..b824c6cc2cc5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c @@ -224,6 +224,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) wl->rx_counter++; drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; - wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); } + + wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); } -- cgit v1.2.3 From 4aa05917051b01da037a80c3207b48aee252eed2 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Mon, 22 Feb 2010 08:38:36 +0200 Subject: wl1271: Don't mask interrupts while handling interrupt Don't mask firmware interrupts while processing interrupts. This allows the interrupt handler looping to work efficiently thus reducing interrupt processing latency. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 4d091ebd3403..a46d323f8a6e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -424,8 +424,6 @@ static void wl1271_irq_work(struct work_struct *work) if (ret < 0) goto out; - wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); - wl1271_fw_status(wl, wl->fw_status); intr = le32_to_cpu(wl->fw_status->intr); if (!intr) { @@ -464,8 +462,6 @@ static void wl1271_irq_work(struct work_struct *work) } out_sleep: - wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, - WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); wl1271_ps_elp_sleep(wl); out: -- cgit v1.2.3 From 1e73eb62cec7cf78b7295769b6e51a915518f5a1 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Mon, 22 Feb 2010 08:38:37 +0200 Subject: wl1271: Implement looped IRQ handling This patch implements looped IRQ handling. In essence, if a new interrupt is asserted by the FW while the host is processing the previous one, the host will directly proceed processing the new IRQ without leaving the handling function. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 2 + drivers/net/wireless/wl12xx/wl1271_main.c | 76 +++++++++++++++++++------------ drivers/net/wireless/wl12xx/wl1271_sdio.c | 4 +- drivers/net/wireless/wl12xx/wl1271_spi.c | 4 +- 4 files changed, 55 insertions(+), 31 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 7f03f899b2b0..457ce725027a 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -371,6 +371,8 @@ struct wl1271 { #define WL1271_FLAG_IN_ELP (6) #define WL1271_FLAG_PSM (7) #define WL1271_FLAG_PSM_REQUESTED (8) +#define WL1271_FLAG_IRQ_PENDING (9) +#define WL1271_FLAG_IRQ_RUNNING (10) unsigned long flags; struct wl1271_partition_set part; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index a46d323f8a6e..9f7416864053 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -406,10 +406,14 @@ static void wl1271_fw_status(struct wl1271 *wl, le32_to_cpu(status->fw_localtime); } +#define WL1271_IRQ_MAX_LOOPS 10 + static void wl1271_irq_work(struct work_struct *work) { int ret; u32 intr; + int loopcount = WL1271_IRQ_MAX_LOOPS; + unsigned long flags; struct wl1271 *wl = container_of(work, struct wl1271, irq_work); @@ -417,51 +421,65 @@ static void wl1271_irq_work(struct work_struct *work) wl1271_debug(DEBUG_IRQ, "IRQ work"); - if (wl->state == WL1271_STATE_OFF) + if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; ret = wl1271_ps_elp_wakeup(wl, true); if (ret < 0) goto out; - wl1271_fw_status(wl, wl->fw_status); - intr = le32_to_cpu(wl->fw_status->intr); - if (!intr) { - wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); - goto out_sleep; - } + spin_lock_irqsave(&wl->wl_lock, flags); + while (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags) && loopcount) { + clear_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags); + spin_unlock_irqrestore(&wl->wl_lock, flags); + loopcount--; - intr &= WL1271_INTR_MASK; + wl1271_fw_status(wl, wl->fw_status); + intr = le32_to_cpu(wl->fw_status->intr); + if (!intr) { + wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); + continue; + } - if (intr & WL1271_ACX_INTR_EVENT_A) { - wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); - wl1271_event_handle(wl, 0); - } + intr &= WL1271_INTR_MASK; - if (intr & WL1271_ACX_INTR_EVENT_B) { - wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); - wl1271_event_handle(wl, 1); - } + if (intr & WL1271_ACX_INTR_DATA) { + wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); - if (intr & WL1271_ACX_INTR_INIT_COMPLETE) - wl1271_debug(DEBUG_IRQ, - "WL1271_ACX_INTR_INIT_COMPLETE"); + /* check for tx results */ + if (wl->fw_status->tx_results_counter != + (wl->tx_results_count & 0xff)) + wl1271_tx_complete(wl); - if (intr & WL1271_ACX_INTR_HW_AVAILABLE) - wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); + wl1271_rx(wl, wl->fw_status); + } + + if (intr & WL1271_ACX_INTR_EVENT_A) { + wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); + wl1271_event_handle(wl, 0); + } + + if (intr & WL1271_ACX_INTR_EVENT_B) { + wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); + wl1271_event_handle(wl, 1); + } - if (intr & WL1271_ACX_INTR_DATA) { - wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); + if (intr & WL1271_ACX_INTR_INIT_COMPLETE) + wl1271_debug(DEBUG_IRQ, + "WL1271_ACX_INTR_INIT_COMPLETE"); - /* check for tx results */ - if (wl->fw_status->tx_results_counter != - (wl->tx_results_count & 0xff)) - wl1271_tx_complete(wl); + if (intr & WL1271_ACX_INTR_HW_AVAILABLE) + wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); - wl1271_rx(wl, wl->fw_status); + spin_lock_irqsave(&wl->wl_lock, flags); } -out_sleep: + if (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags)) + ieee80211_queue_work(wl->hw, &wl->irq_work); + else + clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); + spin_unlock_irqrestore(&wl->wl_lock, flags); + wl1271_ps_elp_sleep(wl); out: diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index 7d7c85041859..1f204db30c27 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c @@ -75,7 +75,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) wl->elp_compl = NULL; } - ieee80211_queue_work(wl->hw, &wl->irq_work); + if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags)) + ieee80211_queue_work(wl->hw, &wl->irq_work); + set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags); spin_unlock_irqrestore(&wl->wl_lock, flags); return IRQ_HANDLED; diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 51171d7d5da3..ed285fec2a08 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c @@ -324,7 +324,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) wl->elp_compl = NULL; } - ieee80211_queue_work(wl->hw, &wl->irq_work); + if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags)) + ieee80211_queue_work(wl->hw, &wl->irq_work); + set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags); spin_unlock_irqrestore(&wl->wl_lock, flags); return IRQ_HANDLED; -- cgit v1.2.3 From ac5e1e39c1eeaaff7e6f03bf7cf7a444b42fbc23 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Mon, 22 Feb 2010 08:38:38 +0200 Subject: wl1271: Update TX packet life time handling with higher resolution time This patch uses a higher precision timer to synchronize with the firmware clock. Improved precision is needed as on some platforms a jiffy may be up to tens of milliseconds, and the required precision is closer to TU's. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 2 +- drivers/net/wireless/wl12xx/wl1271_main.c | 6 ++++-- drivers/net/wireless/wl12xx/wl1271_tx.c | 7 +++++-- 3 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 457ce725027a..41de47caa201 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -404,7 +404,7 @@ struct wl1271 { u32 tx_packets_count; /* Time-offset between host and chipset clocks */ - int time_offset; + s64 time_offset; /* Session counter for the chipset */ int session_counter; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 9f7416864053..4c4d22acaeea 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -374,6 +374,7 @@ static void wl1271_power_on(struct wl1271 *wl) static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status) { + struct timespec ts; u32 total = 0; int i; @@ -402,8 +403,9 @@ static void wl1271_fw_status(struct wl1271 *wl, ieee80211_queue_work(wl->hw, &wl->tx_work); /* update the host-chipset time offset */ - wl->time_offset = jiffies_to_usecs(jiffies) - - le32_to_cpu(status->fw_localtime); + getnstimeofday(&ts); + wl->time_offset = (timespec_to_ns(&ts) >> 10) - + (s64)le32_to_cpu(status->fw_localtime); } #define WL1271_IRQ_MAX_LOOPS 10 diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 7926471cd095..a32d3014781d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -86,8 +86,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, u32 extra, struct ieee80211_tx_info *control) { + struct timespec ts; struct wl1271_tx_hw_descr *desc; int pad, ac; + s64 hosttime; u16 tx_attr; desc = (struct wl1271_tx_hw_descr *) skb->data; @@ -101,8 +103,9 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, } /* configure packet life time */ - desc->start_time = cpu_to_le32(jiffies_to_usecs(jiffies) - - wl->time_offset); + getnstimeofday(&ts); + hosttime = (timespec_to_ns(&ts) >> 10); + desc->start_time = cpu_to_le32(hosttime - wl->time_offset); desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); /* configure the tx attributes */ -- cgit v1.2.3 From 5c9417f1656b0f415f4be5a7cd7195ecadd7dd1a Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Mon, 22 Feb 2010 08:38:39 +0200 Subject: wl1271: Clean up firmware block allocation calculation This patch simplifies the required block count calculation. Though it introduces a division operator, it greatly simplifies the formula. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_tx.c | 10 +++------- drivers/net/wireless/wl12xx/wl1271_tx.h | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index a32d3014781d..d3ed63e92cf4 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -46,7 +46,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) { struct wl1271_tx_hw_descr *desc; u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; - u32 total_blocks, excluded; + u32 total_blocks; int id, ret = -EBUSY; /* allocate free identifier for the packet */ @@ -56,12 +56,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) /* approximate the number of blocks required for this packet in the firmware */ - /* FIXME: try to figure out what is done here and make it cleaner */ - total_blocks = (total_len + 20) >> TX_HW_BLOCK_SHIFT_DIV; - excluded = (total_blocks << 2) + ((total_len + 20) & 0xff) + 34; - total_blocks += (excluded > 252) ? 2 : 1; - total_blocks += TX_HW_BLOCK_SPARE; - + total_blocks = total_len + TX_HW_BLOCK_SIZE - 1; + total_blocks = total_blocks / TX_HW_BLOCK_SIZE + TX_HW_BLOCK_SPARE; if (total_blocks <= wl->tx_blocks_available) { desc = (struct wl1271_tx_hw_descr *)skb_push( skb, total_len - skb->len); diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index ca92bd811292..8b9f6b4f5652 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h @@ -26,7 +26,7 @@ #define __WL1271_TX_H__ #define TX_HW_BLOCK_SPARE 2 -#define TX_HW_BLOCK_SHIFT_DIV 8 +#define TX_HW_BLOCK_SIZE 252 #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 /* The chipset reference driver states, that the "aid" value 1 -- cgit v1.2.3 From 04e36fc5f1ff4e349ea21de8d15e4e1844d04197 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Mon, 22 Feb 2010 08:38:40 +0200 Subject: wl1271: Clean up TX security sequence number handling Instead of managing the TX security sequence number as two variables, use one 64 bit variable. This greatly simplifies the handling of the number. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 6 ++++-- drivers/net/wireless/wl12xx/wl1271_cmd.c | 3 +-- drivers/net/wireless/wl12xx/wl1271_main.c | 11 +++++------ drivers/net/wireless/wl12xx/wl1271_tx.c | 10 ++-------- 4 files changed, 12 insertions(+), 18 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 41de47caa201..0deb4fdf916b 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -110,6 +110,9 @@ enum { #define WL1271_FW_NAME "wl1271-fw.bin" #define WL1271_NVS_NAME "wl1271-nvs.bin" +#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) +#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) + /* NVS data structure */ #define WL1271_NVS_SECTION_SIZE 468 @@ -419,8 +422,7 @@ struct wl1271 { /* Security sequence number counters */ u8 tx_security_last_seq; - u16 tx_security_seq_16; - u32 tx_security_seq_32; + s64 tx_security_seq; /* FW Rx counter */ u32 rx_counter; diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index e029bf03809d..d59b3830a6a5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -318,8 +318,7 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) /* reset TX security counters */ wl->tx_security_last_seq = 0; - wl->tx_security_seq_16 = 0; - wl->tx_security_seq_32 = 0; + wl->tx_security_seq = 0; ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); if (ret < 0) { diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 4c4d22acaeea..f10ba847689d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1020,8 +1020,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->tx_results_count = 0; wl->tx_packets_count = 0; wl->tx_security_last_seq = 0; - wl->tx_security_seq_16 = 0; - wl->tx_security_seq_32 = 0; + wl->tx_security_seq = 0; wl->time_offset = 0; wl->session_counter = 0; wl->rate_set = CONF_TX_RATE_MASK_BASIC; @@ -1428,15 +1427,15 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, key_type = KEY_TKIP; key_conf->hw_key_idx = key_conf->keyidx; - tx_seq_32 = wl->tx_security_seq_32; - tx_seq_16 = wl->tx_security_seq_16; + tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); + tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); break; case ALG_CCMP: key_type = KEY_AES; key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - tx_seq_32 = wl->tx_security_seq_32; - tx_seq_16 = wl->tx_security_seq_16; + tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); + tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); break; default: wl1271_error("Unknown key algo 0x%x", key_conf->alg); diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index d3ed63e92cf4..1b11e2caabd6 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -303,7 +303,6 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, { struct ieee80211_tx_info *info; struct sk_buff *skb; - u16 seq; int id = result->id; /* check for id legality */ @@ -331,15 +330,10 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, wl->stats.retry_count += result->ack_failures; /* update security sequence number */ - seq = wl->tx_security_seq_16 + - (result->lsb_security_sequence_number - - wl->tx_security_last_seq); + wl->tx_security_seq += (result->lsb_security_sequence_number - + wl->tx_security_last_seq); wl->tx_security_last_seq = result->lsb_security_sequence_number; - if (seq < wl->tx_security_seq_16) - wl->tx_security_seq_32++; - wl->tx_security_seq_16 = seq; - /* remove private header from packet */ skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); -- cgit v1.2.3 From 0a34332f669dbcd9efc13a45b30985c30ba8f65e Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Mon, 22 Feb 2010 08:38:41 +0200 Subject: wl1271: Disable host TX rate control Disable host TX rate control. The wl1271 firmware is already managing rate control, so this eliminate unnecessary host processing. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 3 ++- drivers/net/wireless/wl12xx/wl1271_tx.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index f10ba847689d..0a4ff7b02f59 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1973,7 +1973,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl) wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM | IEEE80211_HW_BEACON_FILTER | - IEEE80211_HW_SUPPORTS_PS; + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_HAS_RATE_CONTROL; wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 1b11e2caabd6..6d109df9a0a0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -350,6 +350,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, result->id, skb, result->ack_failures, result->rate_class_index, result->status); + /* FIXME: do we need to tell the stack about the used rate? */ + /* return the packet to the stack */ ieee80211_tx_status(wl->hw, skb); wl->tx_frames[result->id] = NULL; -- cgit v1.2.3 From 6f6b5d49105eba1be0b2ef0c04a4571f20793778 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Mon, 22 Feb 2010 08:38:42 +0200 Subject: wl1271: Remove tx-power level workaround This patch removes the workaround limiting chipset TX power to 12dB, instead using the value configured by the mac80211. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index f41f886741f1..60e20876e6d8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -135,12 +135,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power) goto out; } - /* - * FIXME: This is a workaround needed while we don't the correct - * calibration, to avoid distortions - */ - /* acx->current_tx_power = power * 10; */ - acx->current_tx_power = 120; + acx->current_tx_power = power * 10; ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); if (ret < 0) { -- cgit v1.2.3 From 74bad5cb497080514c4a945f38589bdb574fdfb7 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Tue, 23 Feb 2010 18:15:27 -0500 Subject: ath9k: never read from the AR_IMR_S2 register The AR_IMR_S2 register sometimes cannot be read correctly. Instead of a valid value, 0xdeadbeef is returned. The driver has been observed writing that value back to AR_IMR_S2 after changing a few bits. Cache the register value in ah->imrs2_reg and always write chached value to the register. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 16 +++++++--------- drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/mac.c | 6 ++++-- 3 files changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2e767cf22f1e..1fb14edfcb2a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1151,7 +1151,8 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, ah->mask_reg |= AR_IMR_MIB; REG_WRITE(ah, AR_IMR, ah->mask_reg); - REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT); + ah->imrs2_reg |= AR_IMR_S2_GTT; + REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); if (!AR_SREV_9100(ah)) { REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); @@ -2920,14 +2921,11 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); REG_WRITE(ah, AR_IMR, mask); - mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM | - AR_IMR_S2_DTIM | - AR_IMR_S2_DTIMSYNC | - AR_IMR_S2_CABEND | - AR_IMR_S2_CABTO | - AR_IMR_S2_TSFOOR | - AR_IMR_S2_GTT | AR_IMR_S2_CST); - REG_WRITE(ah, AR_IMR_S2, mask | mask2); + ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | + AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | + AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST); + ah->imrs2_reg |= mask2; + REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); ah->mask_reg = ints; if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index dbbf7ca5f97d..20d90268ce31 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -479,6 +479,7 @@ struct ath_hw { int16_t curchan_rad_index; u32 mask_reg; + u32 imrs2_reg; u32 txok_interrupt_mask; u32 txerr_interrupt_mask; u32 txdesc_interrupt_mask; diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index efc420cd42bf..589490b69ddc 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -31,8 +31,10 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, REG_WRITE(ah, AR_IMR_S1, SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR) | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL)); - REG_RMW_FIELD(ah, AR_IMR_S2, - AR_IMR_S2_QCU_TXURN, ah->txurn_interrupt_mask); + + ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN; + ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN); + REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); } u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) -- cgit v1.2.3 From 9734485c8d2064f39ff77acf615e87da0766ce76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 27 Feb 2010 13:03:32 +0100 Subject: b43: N-PHY: add some registers and structs definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 1 + drivers/net/wireless/b43/phy_n.h | 9 +++++++++ drivers/net/wireless/b43/tables_nphy.h | 9 +++++++++ 3 files changed, 19 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index b8807fb12c92..3a003e6803a5 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -104,6 +104,7 @@ #define B43_MMIO_MACFILTER_CONTROL 0x420 #define B43_MMIO_MACFILTER_DATA 0x422 #define B43_MMIO_RCMTA_COUNT 0x43C +#define B43_MMIO_PSM_PHY_HDR 0x492 #define B43_MMIO_RADIO_HWENABLED_LO 0x49A #define B43_MMIO_GPIO_CONTROL 0x49C #define B43_MMIO_GPIO_MASK 0x49E diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index 403aad3f894f..47d20dcafbf6 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -711,6 +711,8 @@ #define B43_NPHY_PAPD_EN1 B43_PHY_N(0x29B) /* PAPD Enable1 TBD */ #define B43_NPHY_EPS_TABLE_ADJ1 B43_PHY_N(0x29C) /* EPS Table Adj1 TBD */ +#define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */ +#define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A) /* Broadcom 2055 radio registers */ @@ -924,6 +926,13 @@ struct b43_wldev; +struct b43_chanspec { + u8 channel; + u8 sideband; + u8 b_width; + u8 b_freq; +}; + struct b43_phy_n_iq_comp { s16 a0; s16 b0; diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 9c1c6ecd3672..b23036f7dc19 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -4,6 +4,15 @@ #include +struct b43_phy_n_sfo_cfg { + u16 phy_bw1a; + u16 phy_bw2; + u16 phy_bw3; + u16 phy_bw4; + u16 phy_bw5; + u16 phy_bw6; +}; + struct b43_nphy_channeltab_entry { /* The channel number */ u8 channel; -- cgit v1.2.3 From 8987a9e98fbc6a8b74c0dfc96a69d5e8c200492a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 27 Feb 2010 13:03:33 +0100 Subject: b43: N-PHY: initialize super switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 795bb1e3345d..2d8eda145cb8 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -646,6 +646,41 @@ static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */ +static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init) +{ + if (dev->phy.rev >= 3) { + if (!init) + return; + if (0 /* FIXME */) { + b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211); + b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222); + b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144); + b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188); + } + } else { + b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0); + b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0); + + ssb_chipco_gpio_control(&dev->dev->bus->chipco, 0xFC00, + 0xFC00); + b43_write32(dev, B43_MMIO_MACCTL, + b43_read32(dev, B43_MMIO_MACCTL) & + ~B43_MACCTL_GPOUTSMSK); + b43_write16(dev, B43_MMIO_GPIO_MASK, + b43_read16(dev, B43_MMIO_GPIO_MASK) | 0xFC00); + b43_write16(dev, B43_MMIO_GPIO_CONTROL, + b43_read16(dev, B43_MMIO_GPIO_CONTROL) & ~0xFC00); + + if (init) { + b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); + b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); + b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); + b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); + } + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) { @@ -3116,7 +3151,7 @@ int b43_phy_initn(struct b43_wldev *dev) target = b43_nphy_get_tx_gains(dev); if (nphy->antsel_type == 2) - ;/*TODO NPHY Superswitch Init with argument 1*/ + b43_nphy_superswitch_init(dev, true); if (nphy->perical != 2) { b43_nphy_rssi_cal(dev); if (phy->rev >= 3) { -- cgit v1.2.3 From c2b7aefdc9b10c64a4e4be2303131006f9dc7013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 27 Feb 2010 13:03:34 +0100 Subject: b43: N-PHY: turn radio on/off (rfkill) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 50 +++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 2d8eda145cb8..dd81e8aec912 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -218,7 +218,10 @@ static void b43_radio_init2055_post(struct b43_wldev *dev) b43_radio_write16(dev, B2055_C2_RX_BB_MIDACHP, 0x83); } -/* Initialize a Broadcom 2055 N-radio */ +/* + * Initialize a Broadcom 2055 N-radio + * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init + */ static void b43_radio_init2055(struct b43_wldev *dev) { b43_radio_init2055_pre(dev); @@ -229,17 +232,6 @@ static void b43_radio_init2055(struct b43_wldev *dev) b43_radio_init2055_post(dev); } -void b43_nphy_radio_turn_on(struct b43_wldev *dev) -{ - b43_radio_init2055(dev); -} - -void b43_nphy_radio_turn_off(struct b43_wldev *dev) -{ - b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, - ~B43_NPHY_RFCTL_CMD_EN); -} - /* * Upload the N-PHY tables. * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables @@ -3277,9 +3269,41 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); } +/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, bool blocked) -{//TODO +{ + if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) + b43err(dev->wl, "MAC not suspended\n"); + + if (blocked) { + b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, + ~B43_NPHY_RFCTL_CMD_CHIP0PU); + if (dev->phy.rev >= 3) { + b43_radio_mask(dev, 0x09, ~0x2); + + b43_radio_write(dev, 0x204D, 0); + b43_radio_write(dev, 0x2053, 0); + b43_radio_write(dev, 0x2058, 0); + b43_radio_write(dev, 0x205E, 0); + b43_radio_mask(dev, 0x2062, ~0xF0); + b43_radio_write(dev, 0x2064, 0); + + b43_radio_write(dev, 0x304D, 0); + b43_radio_write(dev, 0x3053, 0); + b43_radio_write(dev, 0x3058, 0); + b43_radio_write(dev, 0x305E, 0); + b43_radio_mask(dev, 0x3062, ~0xF0); + b43_radio_write(dev, 0x3064, 0); + } + } else { + if (dev->phy.rev >= 3) { + /* TODO: b43_radio_init2056(dev); */ + /* TODO: PHY Set Channel Spec (dev, radio_chanspec) */ + } else { + b43_radio_init2055(dev); + } + } } static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) -- cgit v1.2.3 From e5255cccb26e88d0c7dd2d25b5ec2f26a3c6301d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 27 Feb 2010 13:03:35 +0100 Subject: b43: N-PHY: update writing channel-specific radio registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 54 ++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index dd81e8aec912..2c592d2dba93 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -90,28 +90,38 @@ static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev, static void b43_chantab_radio_upload(struct b43_wldev *dev, const struct b43_nphy_channeltab_entry *e) { - b43_radio_write16(dev, B2055_PLL_REF, e->radio_pll_ref); - b43_radio_write16(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); - b43_radio_write16(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); - b43_radio_write16(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail); - b43_radio_write16(dev, B2055_VCO_CAL1, e->radio_vco_cal1); - b43_radio_write16(dev, B2055_VCO_CAL2, e->radio_vco_cal2); - b43_radio_write16(dev, B2055_PLL_LFC1, e->radio_pll_lfc1); - b43_radio_write16(dev, B2055_PLL_LFR1, e->radio_pll_lfr1); - b43_radio_write16(dev, B2055_PLL_LFC2, e->radio_pll_lfc2); - b43_radio_write16(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); - b43_radio_write16(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1); - b43_radio_write16(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2); - b43_radio_write16(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); - b43_radio_write16(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); - b43_radio_write16(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); - b43_radio_write16(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); - b43_radio_write16(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); - b43_radio_write16(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); - b43_radio_write16(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); - b43_radio_write16(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); - b43_radio_write16(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); - b43_radio_write16(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); + b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref); + b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); + b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); + b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail); + b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ + + b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1); + b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2); + b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1); + b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1); + b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ + + b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2); + b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); + b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1); + b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2); + b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ + + b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); + b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); + b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); + b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); + b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ + + b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); + b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); + b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); + b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); + b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ + + b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); + b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); } static void b43_chantab_phy_upload(struct b43_wldev *dev, -- cgit v1.2.3 From 036cafe4212a7d71d415b2f02cc5d6cad690dc27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 27 Feb 2010 13:03:36 +0100 Subject: b43: N-PHY: update post init of 2055 radio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 61 +++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 26 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 2c592d2dba93..67748976ae79 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -183,49 +183,58 @@ static void b43_radio_init2055_pre(struct b43_wldev *dev) static void b43_radio_init2055_post(struct b43_wldev *dev) { + struct b43_phy_n *nphy = dev->phy.n; struct ssb_sprom *sprom = &(dev->dev->bus->sprom); struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo); int i; u16 val; + bool workaround = false; + + if (sprom->revision < 4) + workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM || + binfo->type != 0x46D || + binfo->rev < 0x41); + else + workaround = ((sprom->boardflags_hi & B43_BFH_NOPA) == 0); b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); - msleep(1); - if ((sprom->revision != 4) || - !(sprom->boardflags_hi & B43_BFH_RSSIINV)) { - if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) || - (binfo->type != 0x46D) || - (binfo->rev < 0x41)) { - b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); - b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); - msleep(1); - } + if (workaround) { + b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); + b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F); } - b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0x3F, 0x2C); - msleep(1); - b43_radio_write16(dev, B2055_CAL_MISC, 0x3C); - msleep(1); + b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C); + b43_radio_write(dev, B2055_CAL_MISC, 0x3C); b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE); - msleep(1); b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80); - msleep(1); b43_radio_set(dev, B2055_CAL_MISC, 0x1); msleep(1); b43_radio_set(dev, B2055_CAL_MISC, 0x40); - msleep(1); - for (i = 0; i < 100; i++) { - val = b43_radio_read16(dev, B2055_CAL_COUT2); - if (val & 0x80) + for (i = 0; i < 200; i++) { + val = b43_radio_read(dev, B2055_CAL_COUT2); + if (val & 0x80) { + i = 0; break; + } udelay(10); } - msleep(1); + if (i) + b43err(dev->wl, "radio post init timeout\n"); b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); - msleep(1); nphy_channel_switch(dev, dev->phy.channel); - b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9); - b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9); - b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83); - b43_radio_write16(dev, B2055_C2_RX_BB_MIDACHP, 0x83); + b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9); + b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9); + b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83); + b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83); + b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6); + b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6); + if (!nphy->gain_boost) { + b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2); + b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2); + } else { + b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD); + b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD); + } + udelay(2); } /* -- cgit v1.2.3 From 902db91d969c0eaf70245b6d3db5be5e3cff35f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 27 Feb 2010 13:03:37 +0100 Subject: b43: N-PHY: switch to chanspec struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 45 ++++++++++++++++++++++++++-------------- drivers/net/wireless/b43/phy_n.h | 11 +++++----- 2 files changed, 36 insertions(+), 20 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 67748976ae79..1952acc3c385 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -73,6 +73,21 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, u16 value, u8 core); +static inline bool b43_empty_chanspec(struct b43_chanspec *chanspec) +{ + return !chanspec->channel && !chanspec->sideband && + !chanspec->b_width && !chanspec->b_freq; +} + +static inline bool b43_eq_chanspecs(struct b43_chanspec *chanspec1, + struct b43_chanspec *chanspec2) +{ + return (chanspec1->channel == chanspec2->channel && + chanspec1->sideband == chanspec2->sideband && + chanspec1->b_width == chanspec2->b_width && + chanspec1->b_freq == chanspec2->b_freq); +} + void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) {//TODO } @@ -768,7 +783,7 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev) { struct b43_phy_n *nphy = dev->phy.n; - unsigned int channel; + u8 channel = nphy->radio_chanspec.channel; int tone[2] = { 57, 58 }; u32 noise[2] = { 0x3FF, 0x3FF }; @@ -777,8 +792,6 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev) if (nphy->hang_avoid) b43_nphy_stay_in_carrier_search(dev, 1); - /* FIXME: channel = radio_chanspec */ - if (nphy->gband_spurwar_en) { /* TODO: N PHY Adjust Analog Pfbw (7) */ if (channel == 11 && dev->phy.is_40mhz) @@ -2015,12 +2028,12 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev) u16 *rssical_phy_regs = NULL; if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - if (!nphy->rssical_chanspec_2G) + if (b43_empty_chanspec(&nphy->rssical_chanspec_2G)) return; rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; } else { - if (!nphy->rssical_chanspec_5G) + if (b43_empty_chanspec(&nphy->rssical_chanspec_5G)) return; rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; @@ -2440,7 +2453,7 @@ static void b43_nphy_save_cal(struct b43_wldev *dev) struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; u16 *txcal_radio_regs = NULL; - u8 *iqcal_chanspec; + struct b43_chanspec *iqcal_chanspec; u16 *table = NULL; if (nphy->hang_avoid) @@ -2496,12 +2509,12 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev) struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - if (nphy->iqcal_chanspec_2G == 0) + if (b43_empty_chanspec(&nphy->iqcal_chanspec_2G)) return; table = nphy->cal_cache.txcal_coeffs_2G; loft = &nphy->cal_cache.txcal_coeffs_2G[5]; } else { - if (nphy->iqcal_chanspec_5G == 0) + if (b43_empty_chanspec(&nphy->iqcal_chanspec_5G)) return; table = nphy->cal_cache.txcal_coeffs_5G; loft = &nphy->cal_cache.txcal_coeffs_5G[5]; @@ -2746,8 +2759,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, nphy->txiqlocal_bestc); nphy->txiqlocal_coeffsvalid = true; - /* TODO: Set nphy->txiqlocal_chanspec to - the current channel */ + nphy->txiqlocal_chanspec = nphy->radio_chanspec; } else { length = 11; if (dev->phy.rev < 3) @@ -2782,7 +2794,8 @@ static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev) u16 buffer[7]; bool equal = true; - if (!nphy->txiqlocal_coeffsvalid || 1 /* FIXME */) + if (!nphy->txiqlocal_coeffsvalid || + b43_eq_chanspecs(&nphy->txiqlocal_chanspec, &nphy->radio_chanspec)) return; b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); @@ -3137,9 +3150,11 @@ int b43_phy_initn(struct b43_wldev *dev) do_rssi_cal = false; if (phy->rev >= 3) { if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - do_rssi_cal = (nphy->rssical_chanspec_2G == 0); + do_rssi_cal = + b43_empty_chanspec(&nphy->rssical_chanspec_2G); else - do_rssi_cal = (nphy->rssical_chanspec_5G == 0); + do_rssi_cal = + b43_empty_chanspec(&nphy->rssical_chanspec_5G); if (do_rssi_cal) b43_nphy_rssi_cal(dev); @@ -3151,9 +3166,9 @@ int b43_phy_initn(struct b43_wldev *dev) if (!((nphy->measure_hold & 0x6) != 0)) { if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - do_cal = (nphy->iqcal_chanspec_2G == 0); + do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_2G); else - do_cal = (nphy->iqcal_chanspec_5G == 0); + do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_5G); if (nphy->mute) do_cal = false; diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index 47d20dcafbf6..e7acae278be0 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -984,7 +984,7 @@ struct b43_phy_n { u16 papd_epsilon_offset[2]; s32 preamble_override; u32 bb_mult_save; - u16 radio_chanspec; + struct b43_chanspec radio_chanspec; bool gain_boost; bool elna_gain_config; @@ -1000,6 +1000,7 @@ struct b43_phy_n { u16 txiqlocal_bestc[11]; bool txiqlocal_coeffsvalid; struct b43_phy_n_txpwrindex txpwrindex[2]; + struct b43_chanspec txiqlocal_chanspec; u8 txrx_chain; u16 tx_rx_cal_phy_saveregs[11]; @@ -1015,12 +1016,12 @@ struct b43_phy_n { bool gband_spurwar_en; bool ipa2g_on; - u8 iqcal_chanspec_2G; - u8 rssical_chanspec_2G; + struct b43_chanspec iqcal_chanspec_2G; + struct b43_chanspec rssical_chanspec_2G; bool ipa5g_on; - u8 iqcal_chanspec_5G; - u8 rssical_chanspec_5G; + struct b43_chanspec iqcal_chanspec_5G; + struct b43_chanspec rssical_chanspec_5G; struct b43_phy_n_rssical_cache rssical_cache; struct b43_phy_n_cal_cache cal_cache; -- cgit v1.2.3 From d24019adaae5a6498c189b42431000cf24d4d355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 27 Feb 2010 13:03:38 +0100 Subject: b43: N-PHY: adjust gain table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 58 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 1952acc3c385..30f8bf24ac69 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -837,6 +837,62 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev) b43_nphy_stay_in_carrier_search(dev, 0); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */ +static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + + u8 i; + s16 tmp; + u16 data[4]; + s16 gain[2]; + u16 minmax[2]; + u16 lna_gain[4] = { -2, 10, 19, 25 }; + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 1); + + if (nphy->gain_boost) { + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + gain[0] = 6; + gain[1] = 6; + } else { + tmp = 40370 - 315 * nphy->radio_chanspec.channel; + gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1)); + tmp = 23242 - 224 * nphy->radio_chanspec.channel; + gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1)); + } + } else { + gain[0] = 0; + gain[1] = 0; + } + + for (i = 0; i < 2; i++) { + if (nphy->elna_gain_config) { + data[0] = 19 + gain[i]; + data[1] = 25 + gain[i]; + data[2] = 25 + gain[i]; + data[3] = 25 + gain[i]; + } else { + data[0] = lna_gain[0] + gain[i]; + data[1] = lna_gain[1] + gain[i]; + data[2] = lna_gain[2] + gain[i]; + data[3] = lna_gain[3] + gain[i]; + } + b43_ntab_write_bulk(dev, B43_NTAB16(10, 8), 4, data); + + minmax[i] = 23 + gain[i]; + } + + b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN, + minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT); + b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN, + minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT); + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 0); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) { @@ -921,7 +977,7 @@ static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_TABLE_DATALO, (code << 8 | 0x7C)); - /* TODO: b43_nphy_adjust_lna_gain_table(dev); */ + b43_nphy_adjust_lna_gain_table(dev); if (nphy->elna_gain_config) { b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808); -- cgit v1.2.3 From 7955de0caf70e4aefd51d68e42f78d4bd82f26a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 27 Feb 2010 13:03:39 +0100 Subject: b43: N-PHY: isloate 2055 radio setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 30f8bf24ac69..ffe262270664 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -155,6 +155,22 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) //TODO } + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */ +static void b43_radio_2055_setup(struct b43_wldev *dev, + const struct b43_nphy_channeltab_entry *e) +{ + B43_WARN_ON(dev->phy.rev >= 3); + + b43_chantab_radio_upload(dev, e); + udelay(50); + b43_radio_write(dev, B2055_VCO_CAL10, 5); + b43_radio_write(dev, B2055_VCO_CAL10, 45); + b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ + b43_radio_write(dev, B2055_VCO_CAL10, 65); + udelay(300); +} + /* Tune the hardware to a new channel. */ static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel) { @@ -169,12 +185,7 @@ static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel) b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x20); else b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x50); - b43_chantab_radio_upload(dev, tabent); - udelay(50); - b43_radio_write16(dev, B2055_VCO_CAL10, 5); - b43_radio_write16(dev, B2055_VCO_CAL10, 45); - b43_radio_write16(dev, B2055_VCO_CAL10, 65); - udelay(300); + b43_radio_2055_setup(dev, tabent); if (0 /*FIXME 5Ghz*/) b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); else -- cgit v1.2.3 From 1b69ec7bac9cc0688ecf1411d167d1b8a34aeb07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 27 Feb 2010 13:03:40 +0100 Subject: b43: N-PHY: implement chanspec setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index ffe262270664..862223fdde4d 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -3282,6 +3282,68 @@ int b43_phy_initn(struct b43_wldev *dev) return 0; } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ +static void b43_nphy_chanspec_setup(struct b43_wldev *dev, + const struct b43_nphy_channeltab_entry *e, + struct b43_chanspec chanspec) +{ + struct b43_phy *phy = &dev->phy; + struct b43_phy_n *nphy = dev->phy.n; + + u16 tmp; + u32 tmp32; + + tmp = b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ; + if (chanspec.b_freq == 1 && tmp == 0) { + tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); + b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); + b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000); + b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32); + b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); + } else if (chanspec.b_freq == 1) { + b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); + tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); + b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); + b43_phy_mask(dev, B43_PHY_B_BBCFG, (u16)~0xC000); + b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32); + } + + b43_chantab_phy_upload(dev, e); + + tmp = chanspec.channel; + if (chanspec.b_freq == 1) + tmp |= 0x0100; + if (chanspec.b_width == 3) + tmp |= 0x0200; + b43_shm_write16(dev, B43_SHM_SHARED, 0xA0, tmp); + + if (nphy->radio_chanspec.channel == 14) { + b43_nphy_classifier(dev, 2, 0); + b43_phy_set(dev, B43_PHY_B_TEST, 0x0800); + } else { + b43_nphy_classifier(dev, 2, 2); + if (chanspec.b_freq == 2) + b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840); + } + + if (nphy->txpwrctrl) + b43_nphy_tx_power_fix(dev); + + if (dev->phy.rev < 3) + b43_nphy_adjust_lna_gain_table(dev); + + b43_nphy_tx_lp_fbw(dev); + + if (dev->phy.rev >= 3 && 0) { + /* TODO */ + } + + b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830); + + if (phy->rev >= 3) + b43_nphy_spur_workaround(dev); +} + static int b43_nphy_op_allocate(struct b43_wldev *dev) { struct b43_phy_n *nphy; -- cgit v1.2.3 From eff66c519e8087e18526a6e0c5ee3dd1de1bc792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 27 Feb 2010 13:03:41 +0100 Subject: b43: N-PHY: switch to chanspec ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 87 ++++++++++++++++++++++++++++------------ drivers/net/wireless/b43/phy_n.h | 1 + 2 files changed, 63 insertions(+), 25 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 862223fdde4d..6fd140ac7f9e 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -72,6 +72,7 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, u16 value, u8 core, bool off); static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, u16 value, u8 core); +static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel); static inline bool b43_empty_chanspec(struct b43_chanspec *chanspec) { @@ -171,31 +172,6 @@ static void b43_radio_2055_setup(struct b43_wldev *dev, udelay(300); } -/* Tune the hardware to a new channel. */ -static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel) -{ - const struct b43_nphy_channeltab_entry *tabent; - - tabent = b43_nphy_get_chantabent(dev, channel); - if (!tabent) - return -ESRCH; - - //FIXME enable/disable band select upper20 in RXCTL - if (0 /*FIXME 5Ghz*/) - b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x20); - else - b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x50); - b43_radio_2055_setup(dev, tabent); - if (0 /*FIXME 5Ghz*/) - b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); - else - b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); - b43_chantab_phy_upload(dev, tabent); - b43_nphy_tx_power_fix(dev); - - return 0; -} - static void b43_radio_init2055_pre(struct b43_wldev *dev) { b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, @@ -3344,6 +3320,67 @@ static void b43_nphy_chanspec_setup(struct b43_wldev *dev, b43_nphy_spur_workaround(dev); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */ +static int b43_nphy_set_chanspec(struct b43_wldev *dev, + struct b43_chanspec chanspec) +{ + struct b43_phy_n *nphy = dev->phy.n; + + const struct b43_nphy_channeltab_entry *tabent; + + u8 tmp; + u8 channel = chanspec.channel; + + if (dev->phy.rev >= 3) { + /* TODO */ + } + + nphy->radio_chanspec = chanspec; + + if (chanspec.b_width != nphy->b_width) + ; /* TODO: BMAC BW Set (chanspec.b_width) */ + + /* TODO: use defines */ + if (chanspec.b_width == 3) { + if (chanspec.sideband == 2) + b43_phy_set(dev, B43_NPHY_RXCTL, + B43_NPHY_RXCTL_BSELU20); + else + b43_phy_mask(dev, B43_NPHY_RXCTL, + ~B43_NPHY_RXCTL_BSELU20); + } + + if (dev->phy.rev >= 3) { + tmp = (chanspec.b_freq == 1) ? 4 : 0; + b43_radio_maskset(dev, 0x08, 0xFFFB, tmp); + /* TODO: PHY Radio2056 Setup (chan_info_ptr[i]) */ + /* TODO: N PHY Chanspec Setup (chan_info_ptr[i]) */ + } else { + tabent = b43_nphy_get_chantabent(dev, channel); + if (!tabent) + return -ESRCH; + + tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050; + b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp); + b43_radio_2055_setup(dev, tabent); + b43_nphy_chanspec_setup(dev, tabent, chanspec); + } + + return 0; +} + +/* Tune the hardware to a new channel */ +static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel) +{ + struct b43_phy_n *nphy = dev->phy.n; + + struct b43_chanspec chanspec; + chanspec = nphy->radio_chanspec; + chanspec.channel = channel; + + return b43_nphy_set_chanspec(dev, chanspec); +} + static int b43_nphy_op_allocate(struct b43_wldev *dev) { struct b43_phy_n *nphy; diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index e7acae278be0..8b6d570dd0aa 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -984,6 +984,7 @@ struct b43_phy_n { u16 papd_epsilon_offset[2]; s32 preamble_override; u32 bb_mult_save; + u8 b_width; struct b43_chanspec radio_chanspec; bool gain_boost; -- cgit v1.2.3 From a1175124f34a4b859b5064efb84a197e4f6794a6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 06:21:10 -0800 Subject: iwlagn: move ICT code into separate file All the ICT ISR code is iwlagn specific, and doesn't need to be in iwlcore. So create a new iwl-agn.h header file that will hold agn specific function declarations etc., and move the ICT code into a new iwl-agn-ict.c file that is linked into iwlagn. This also gets rid of exporting those symbols. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/Makefile | 2 +- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + drivers/net/wireless/iwlwifi/iwl-6000.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn-ict.c | 303 +++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn.h | 74 +++++++ drivers/net/wireless/iwlwifi/iwl-core.c | 273 -------------------------- drivers/net/wireless/iwlwifi/iwl-core.h | 5 - drivers/net/wireless/iwlwifi/iwl-helpers.h | 3 + 10 files changed, 385 insertions(+), 279 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-ict.c create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 4e378faee650..e31a5ccebea2 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -9,7 +9,7 @@ CFLAGS_iwl-devtrace.o := -I$(src) # AGN obj-$(CONFIG_IWLAGN) += iwlagn.o -iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o +iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o iwlagn-$(CONFIG_IWL5000) += iwl-5000.o diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 3bf2e6e9b2d9..59b092eaa829 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -42,6 +42,7 @@ #include "iwl-core.h" #include "iwl-io.h" #include "iwl-sta.h" +#include "iwl-agn.h" #include "iwl-helpers.h" #include "iwl-5000-hw.h" #include "iwl-agn-led.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index e476acb53aa7..f59628c1c1ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -43,6 +43,7 @@ #include "iwl-io.h" #include "iwl-sta.h" #include "iwl-helpers.h" +#include "iwl-agn.h" #include "iwl-agn-led.h" #include "iwl-5000-hw.h" #include "iwl-6000-hw.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index c4844adff92a..4b7bc008220f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -42,6 +42,7 @@ #include "iwl-core.h" #include "iwl-io.h" #include "iwl-sta.h" +#include "iwl-agn.h" #include "iwl-helpers.h" #include "iwl-5000-hw.h" #include "iwl-6000-hw.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c new file mode 100644 index 000000000000..d6b028b1b6ef --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c @@ -0,0 +1,303 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-agn.h" +#include "iwl-helpers.h" + +#define ICT_COUNT (PAGE_SIZE/sizeof(u32)) + +/* Free dram table */ +void iwl_free_isr_ict(struct iwl_priv *priv) +{ + if (priv->ict_tbl_vir) { + dma_free_coherent(&priv->pci_dev->dev, + (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, + priv->ict_tbl_vir, priv->ict_tbl_dma); + priv->ict_tbl_vir = NULL; + } +} + + +/* allocate dram shared table it is a PAGE_SIZE aligned + * also reset all data related to ICT table interrupt. + */ +int iwl_alloc_isr_ict(struct iwl_priv *priv) +{ + + if (priv->cfg->use_isr_legacy) + return 0; + /* allocate shrared data table */ + priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev, + (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, + &priv->ict_tbl_dma, GFP_KERNEL); + if (!priv->ict_tbl_vir) + return -ENOMEM; + + /* align table to PAGE_SIZE boundry */ + priv->aligned_ict_tbl_dma = ALIGN(priv->ict_tbl_dma, PAGE_SIZE); + + IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", + (unsigned long long)priv->ict_tbl_dma, + (unsigned long long)priv->aligned_ict_tbl_dma, + (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); + + priv->ict_tbl = priv->ict_tbl_vir + + (priv->aligned_ict_tbl_dma - priv->ict_tbl_dma); + + IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", + priv->ict_tbl, priv->ict_tbl_vir, + (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); + + /* reset table and index to all 0 */ + memset(priv->ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); + priv->ict_index = 0; + + /* add periodic RX interrupt */ + priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; + return 0; +} + +/* Device is going up inform it about using ICT interrupt table, + * also we need to tell the driver to start using ICT interrupt. + */ +int iwl_reset_ict(struct iwl_priv *priv) +{ + u32 val; + unsigned long flags; + + if (!priv->ict_tbl_vir) + return 0; + + spin_lock_irqsave(&priv->lock, flags); + iwl_disable_interrupts(priv); + + memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); + + val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT; + + val |= CSR_DRAM_INT_TBL_ENABLE; + val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; + + IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " + "aligned dma address %Lx\n", + val, (unsigned long long)priv->aligned_ict_tbl_dma); + + iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); + priv->use_ict = true; + priv->ict_index = 0; + iwl_write32(priv, CSR_INT, priv->inta_mask); + iwl_enable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +/* Device is going down disable ict interrupt usage */ +void iwl_disable_ict(struct iwl_priv *priv) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + priv->use_ict = false; + spin_unlock_irqrestore(&priv->lock, flags); +} + +static irqreturn_t iwl_isr(int irq, void *data) +{ + struct iwl_priv *priv = data; + u32 inta, inta_mask; +#ifdef CONFIG_IWLWIFI_DEBUG + u32 inta_fh; +#endif + if (!priv) + return IRQ_NONE; + + spin_lock(&priv->lock); + + /* Disable (but don't clear!) interrupts here to avoid + * back-to-back ISRs and sporadic interrupts from our NIC. + * If we have something to service, the tasklet will re-enable ints. + * If we *don't* have something, we'll re-enable before leaving here. */ + inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); + + /* Discover which interrupts are active/pending */ + inta = iwl_read32(priv, CSR_INT); + + /* Ignore interrupt if there's nothing in NIC to service. + * This may be due to IRQ shared with another device, + * or due to sporadic interrupts thrown from our NIC. */ + if (!inta) { + IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); + goto none; + } + + if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { + /* Hardware disappeared. It might have already raised + * an interrupt */ + IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); + goto unplugged; + } + +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { + inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); + IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " + "fh 0x%08x\n", inta, inta_mask, inta_fh); + } +#endif + + priv->inta |= inta; + /* iwl_irq_tasklet() will service interrupts and re-enable them */ + if (likely(inta)) + tasklet_schedule(&priv->irq_tasklet); + else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + iwl_enable_interrupts(priv); + + unplugged: + spin_unlock(&priv->lock); + return IRQ_HANDLED; + + none: + /* re-enable interrupts here since we don't have anything to service. */ + /* only Re-enable if diabled by irq and no schedules tasklet. */ + if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + iwl_enable_interrupts(priv); + + spin_unlock(&priv->lock); + return IRQ_NONE; +} + +/* interrupt handler using ict table, with this interrupt driver will + * stop using INTA register to get device's interrupt, reading this register + * is expensive, device will write interrupts in ICT dram table, increment + * index then will fire interrupt to driver, driver will OR all ICT table + * entries from current index up to table entry with 0 value. the result is + * the interrupt we need to service, driver will set the entries back to 0 and + * set index. + */ +irqreturn_t iwl_isr_ict(int irq, void *data) +{ + struct iwl_priv *priv = data; + u32 inta, inta_mask; + u32 val = 0; + + if (!priv) + return IRQ_NONE; + + /* dram interrupt table not set yet, + * use legacy interrupt. + */ + if (!priv->use_ict) + return iwl_isr(irq, data); + + spin_lock(&priv->lock); + + /* Disable (but don't clear!) interrupts here to avoid + * back-to-back ISRs and sporadic interrupts from our NIC. + * If we have something to service, the tasklet will re-enable ints. + * If we *don't* have something, we'll re-enable before leaving here. + */ + inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); + + + /* Ignore interrupt if there's nothing in NIC to service. + * This may be due to IRQ shared with another device, + * or due to sporadic interrupts thrown from our NIC. */ + if (!priv->ict_tbl[priv->ict_index]) { + IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); + goto none; + } + + /* read all entries that not 0 start with ict_index */ + while (priv->ict_tbl[priv->ict_index]) { + + val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]); + IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", + priv->ict_index, + le32_to_cpu(priv->ict_tbl[priv->ict_index])); + priv->ict_tbl[priv->ict_index] = 0; + priv->ict_index = iwl_queue_inc_wrap(priv->ict_index, + ICT_COUNT); + + } + + /* We should not get this value, just ignore it. */ + if (val == 0xffffffff) + val = 0; + + /* + * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit + * (bit 15 before shifting it to 31) to clear when using interrupt + * coalescing. fortunately, bits 18 and 19 stay set when this happens + * so we use them to decide on the real state of the Rx bit. + * In order words, bit 15 is set if bit 18 or bit 19 are set. + */ + if (val & 0xC0000) + val |= 0x8000; + + inta = (0xff & val) | ((0xff00 & val) << 16); + IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", + inta, inta_mask, val); + + inta &= priv->inta_mask; + priv->inta |= inta; + + /* iwl_irq_tasklet() will service interrupts and re-enable them */ + if (likely(inta)) + tasklet_schedule(&priv->irq_tasklet); + else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) { + /* Allow interrupt if was disabled by this handler and + * no tasklet was schedules, We should not enable interrupt, + * tasklet will enable it. + */ + iwl_enable_interrupts(priv); + } + + spin_unlock(&priv->lock); + return IRQ_HANDLED; + + none: + /* re-enable interrupts here since we don't have anything to service. + * only Re-enable if disabled by irq. + */ + if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + iwl_enable_interrupts(priv); + + spin_unlock(&priv->lock); + return IRQ_NONE; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 47b021477967..d7b8e44985b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -54,6 +54,7 @@ #include "iwl-helpers.h" #include "iwl-sta.h" #include "iwl-calib.h" +#include "iwl-agn.h" /****************************************************************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h new file mode 100644 index 000000000000..26eeb586ee00 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -0,0 +1,74 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef __iwl_agn_h__ +#define __iwl_agn_h__ + +#include "iwl-dev.h" + +int iwl_reset_ict(struct iwl_priv *priv); +void iwl_disable_ict(struct iwl_priv *priv); +int iwl_alloc_isr_ict(struct iwl_priv *priv); +void iwl_free_isr_ict(struct iwl_priv *priv); +irqreturn_t iwl_isr_ict(int irq, void *data); + +#endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 112149e9b31e..b994eee771a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -114,8 +114,6 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { u32 iwl_debug_level; EXPORT_SYMBOL(iwl_debug_level); -static irqreturn_t iwl_isr(int irq, void *data); - /* * Parameter order: * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate @@ -1664,277 +1662,6 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) } EXPORT_SYMBOL(iwl_set_tx_power); -#define ICT_COUNT (PAGE_SIZE/sizeof(u32)) - -/* Free dram table */ -void iwl_free_isr_ict(struct iwl_priv *priv) -{ - if (priv->ict_tbl_vir) { - dma_free_coherent(&priv->pci_dev->dev, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - priv->ict_tbl_vir, priv->ict_tbl_dma); - priv->ict_tbl_vir = NULL; - } -} -EXPORT_SYMBOL(iwl_free_isr_ict); - - -/* allocate dram shared table it is a PAGE_SIZE aligned - * also reset all data related to ICT table interrupt. - */ -int iwl_alloc_isr_ict(struct iwl_priv *priv) -{ - - if (priv->cfg->use_isr_legacy) - return 0; - /* allocate shrared data table */ - priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - &priv->ict_tbl_dma, GFP_KERNEL); - if (!priv->ict_tbl_vir) - return -ENOMEM; - - /* align table to PAGE_SIZE boundry */ - priv->aligned_ict_tbl_dma = ALIGN(priv->ict_tbl_dma, PAGE_SIZE); - - IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", - (unsigned long long)priv->ict_tbl_dma, - (unsigned long long)priv->aligned_ict_tbl_dma, - (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); - - priv->ict_tbl = priv->ict_tbl_vir + - (priv->aligned_ict_tbl_dma - priv->ict_tbl_dma); - - IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", - priv->ict_tbl, priv->ict_tbl_vir, - (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); - - /* reset table and index to all 0 */ - memset(priv->ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); - priv->ict_index = 0; - - /* add periodic RX interrupt */ - priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; - return 0; -} -EXPORT_SYMBOL(iwl_alloc_isr_ict); - -/* Device is going up inform it about using ICT interrupt table, - * also we need to tell the driver to start using ICT interrupt. - */ -int iwl_reset_ict(struct iwl_priv *priv) -{ - u32 val; - unsigned long flags; - - if (!priv->ict_tbl_vir) - return 0; - - spin_lock_irqsave(&priv->lock, flags); - iwl_disable_interrupts(priv); - - memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); - - val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT; - - val |= CSR_DRAM_INT_TBL_ENABLE; - val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; - - IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " - "aligned dma address %Lx\n", - val, (unsigned long long)priv->aligned_ict_tbl_dma); - - iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); - priv->use_ict = true; - priv->ict_index = 0; - iwl_write32(priv, CSR_INT, priv->inta_mask); - iwl_enable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} -EXPORT_SYMBOL(iwl_reset_ict); - -/* Device is going down disable ict interrupt usage */ -void iwl_disable_ict(struct iwl_priv *priv) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - priv->use_ict = false; - spin_unlock_irqrestore(&priv->lock, flags); -} -EXPORT_SYMBOL(iwl_disable_ict); - -/* interrupt handler using ict table, with this interrupt driver will - * stop using INTA register to get device's interrupt, reading this register - * is expensive, device will write interrupts in ICT dram table, increment - * index then will fire interrupt to driver, driver will OR all ICT table - * entries from current index up to table entry with 0 value. the result is - * the interrupt we need to service, driver will set the entries back to 0 and - * set index. - */ -irqreturn_t iwl_isr_ict(int irq, void *data) -{ - struct iwl_priv *priv = data; - u32 inta, inta_mask; - u32 val = 0; - - if (!priv) - return IRQ_NONE; - - /* dram interrupt table not set yet, - * use legacy interrupt. - */ - if (!priv->use_ict) - return iwl_isr(irq, data); - - spin_lock(&priv->lock); - - /* Disable (but don't clear!) interrupts here to avoid - * back-to-back ISRs and sporadic interrupts from our NIC. - * If we have something to service, the tasklet will re-enable ints. - * If we *don't* have something, we'll re-enable before leaving here. - */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ - iwl_write32(priv, CSR_INT_MASK, 0x00000000); - - - /* Ignore interrupt if there's nothing in NIC to service. - * This may be due to IRQ shared with another device, - * or due to sporadic interrupts thrown from our NIC. */ - if (!priv->ict_tbl[priv->ict_index]) { - IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); - goto none; - } - - /* read all entries that not 0 start with ict_index */ - while (priv->ict_tbl[priv->ict_index]) { - - val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]); - IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", - priv->ict_index, - le32_to_cpu(priv->ict_tbl[priv->ict_index])); - priv->ict_tbl[priv->ict_index] = 0; - priv->ict_index = iwl_queue_inc_wrap(priv->ict_index, - ICT_COUNT); - - } - - /* We should not get this value, just ignore it. */ - if (val == 0xffffffff) - val = 0; - - /* - * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit - * (bit 15 before shifting it to 31) to clear when using interrupt - * coalescing. fortunately, bits 18 and 19 stay set when this happens - * so we use them to decide on the real state of the Rx bit. - * In order words, bit 15 is set if bit 18 or bit 19 are set. - */ - if (val & 0xC0000) - val |= 0x8000; - - inta = (0xff & val) | ((0xff00 & val) << 16); - IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", - inta, inta_mask, val); - - inta &= priv->inta_mask; - priv->inta |= inta; - - /* iwl_irq_tasklet() will service interrupts and re-enable them */ - if (likely(inta)) - tasklet_schedule(&priv->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) { - /* Allow interrupt if was disabled by this handler and - * no tasklet was schedules, We should not enable interrupt, - * tasklet will enable it. - */ - iwl_enable_interrupts(priv); - } - - spin_unlock(&priv->lock); - return IRQ_HANDLED; - - none: - /* re-enable interrupts here since we don't have anything to service. - * only Re-enable if disabled by irq. - */ - if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) - iwl_enable_interrupts(priv); - - spin_unlock(&priv->lock); - return IRQ_NONE; -} -EXPORT_SYMBOL(iwl_isr_ict); - - -static irqreturn_t iwl_isr(int irq, void *data) -{ - struct iwl_priv *priv = data; - u32 inta, inta_mask; -#ifdef CONFIG_IWLWIFI_DEBUG - u32 inta_fh; -#endif - if (!priv) - return IRQ_NONE; - - spin_lock(&priv->lock); - - /* Disable (but don't clear!) interrupts here to avoid - * back-to-back ISRs and sporadic interrupts from our NIC. - * If we have something to service, the tasklet will re-enable ints. - * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ - iwl_write32(priv, CSR_INT_MASK, 0x00000000); - - /* Discover which interrupts are active/pending */ - inta = iwl_read32(priv, CSR_INT); - - /* Ignore interrupt if there's nothing in NIC to service. - * This may be due to IRQ shared with another device, - * or due to sporadic interrupts thrown from our NIC. */ - if (!inta) { - IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); - goto none; - } - - if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { - /* Hardware disappeared. It might have already raised - * an interrupt */ - IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); - goto unplugged; - } - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { - inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " - "fh 0x%08x\n", inta, inta_mask, inta_fh); - } -#endif - - priv->inta |= inta; - /* iwl_irq_tasklet() will service interrupts and re-enable them */ - if (likely(inta)) - tasklet_schedule(&priv->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) - iwl_enable_interrupts(priv); - - unplugged: - spin_unlock(&priv->lock); - return IRQ_HANDLED; - - none: - /* re-enable interrupts here since we don't have anything to service. */ - /* only Re-enable if diabled by irq and no schedules tasklet. */ - if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) - iwl_enable_interrupts(priv); - - spin_unlock(&priv->lock); - return IRQ_NONE; -} - irqreturn_t iwl_isr_legacy(int irq, void *data) { struct iwl_priv *priv = data; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4ef7739f9e8e..f493248d4727 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -560,11 +560,6 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags, * PCI * *****************************************************/ irqreturn_t iwl_isr_legacy(int irq, void *data); -int iwl_reset_ict(struct iwl_priv *priv); -void iwl_disable_ict(struct iwl_priv *priv); -int iwl_alloc_isr_ict(struct iwl_priv *priv); -void iwl_free_isr_ict(struct iwl_priv *priv); -irqreturn_t iwl_isr_ict(int irq, void *data); static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) { diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 51a67fb2e185..3ff6b9d25a10 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -31,6 +31,9 @@ #define __iwl_helpers_h__ #include +#include + +#include "iwl-io.h" #define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) -- cgit v1.2.3 From ee525d13f501baeaa33209620398adaf0a820629 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 06:09:28 -0800 Subject: iwlwifi: move 3945 specific data into union To be obviously correct, this patch only modifies 3945 files and the struct definition. A follow-up patch will create the AGN part of the union. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-3945.c | 27 +++++++++++++------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 30 +++++++++++++++-------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 22 ++++++++++----------- 5 files changed, 45 insertions(+), 40 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 3a876a8ece38..074f42a7dcad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -78,6 +78,8 @@ /* RSSI to dBm */ #define IWL39_RSSI_OFFSET 95 +#define IWL_DEFAULT_TX_POWER 0x0F + /* * EEPROM related constants, enums, and structures. */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 47909f94271e..effdd3670da4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -372,11 +372,11 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, } } - priv->sta_supp_rates = sta->supp_rates[sband->band]; + priv->_3945.sta_supp_rates = sta->supp_rates[sband->band]; /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ if (sband->band == IEEE80211_BAND_5GHZ) { rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; - priv->sta_supp_rates = priv->sta_supp_rates << + priv->_3945.sta_supp_rates = priv->_3945.sta_supp_rates << IWL_FIRST_OFDM_RATE; } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 303cc8193adc..867bd69270f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -242,7 +242,7 @@ int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate) next_rate = IWL_RATE_6M_INDEX; break; case IEEE80211_BAND_2GHZ: - if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) && + if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) && iwl_is_associated(priv)) { if (rate == IWL_RATE_11M_INDEX) next_rate = IWL_RATE_5M_INDEX; @@ -359,7 +359,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv, (int)sizeof(struct iwl3945_notif_statistics), le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); - memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); + memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics)); } /****************************************************************************** @@ -956,7 +956,7 @@ static int iwl3945_tx_reset(struct iwl_priv *priv) iwl_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005); iwl_write_direct32(priv, FH39_TSSR_CBB_BASE, - priv->shared_phys); + priv->_3945.shared_phys); iwl_write_direct32(priv, FH39_TSSR_MSG_CONFIG, FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON | @@ -1997,13 +1997,13 @@ void iwl3945_reg_txpower_periodic(struct iwl_priv *priv) reschedule: queue_delayed_work(priv->workqueue, - &priv->thermal_periodic, REG_RECALIB_PERIOD * HZ); + &priv->_3945.thermal_periodic, REG_RECALIB_PERIOD * HZ); } static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, - thermal_periodic.work); + _3945.thermal_periodic.work); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -2331,7 +2331,7 @@ int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) { int txq_id = txq->q.id; - struct iwl3945_shared *shared_data = priv->shared_virt; + struct iwl3945_shared *shared_data = priv->_3945.shared_virt; shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr); @@ -2431,7 +2431,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv) /* If an OFDM rate is used, have it fall back to the * 1M CCK rates */ - if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) && + if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) && iwl_is_associated(priv)) { index = IWL_FIRST_CCK_RATE; @@ -2470,10 +2470,11 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) memset((void *)&priv->hw_params, 0, sizeof(struct iwl_hw_params)); - priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev, - sizeof(struct iwl3945_shared), - &priv->shared_phys, GFP_KERNEL); - if (!priv->shared_virt) { + priv->_3945.shared_virt = + dma_alloc_coherent(&priv->pci_dev->dev, + sizeof(struct iwl3945_shared), + &priv->_3945.shared_phys, GFP_KERNEL); + if (!priv->_3945.shared_virt) { IWL_ERR(priv, "failed to allocate pci memory\n"); mutex_unlock(&priv->mutex); return -ENOMEM; @@ -2536,13 +2537,13 @@ void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv) void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv) { - INIT_DELAYED_WORK(&priv->thermal_periodic, + INIT_DELAYED_WORK(&priv->_3945.thermal_periodic, iwl3945_bg_reg_txpower_periodic); } void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv) { - cancel_delayed_work(&priv->thermal_periodic); + cancel_delayed_work(&priv->_3945.thermal_periodic); } /* check contents of special bootstrap uCode SRAM */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 6054c5fba0c1..e6cae3884879 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1262,10 +1262,22 @@ struct iwl_priv { u16 beacon_int; struct ieee80211_vif *vif; - /*Added for 3945 */ - void *shared_virt; - dma_addr_t shared_phys; - /*End*/ + union { +#if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE) + struct { + void *shared_virt; + dma_addr_t shared_phys; + + struct delayed_work thermal_periodic; + struct delayed_work rfkill_poll; + + struct iwl3945_notif_statistics statistics; + + u32 sta_supp_rates; + } _3945; +#endif + }; + struct iwl_hw_params hw_params; /* INT ICT Table */ @@ -1303,10 +1315,6 @@ struct iwl_priv { struct delayed_work alive_start; struct delayed_work scan_check; - /*For 3945 only*/ - struct delayed_work thermal_periodic; - struct delayed_work rfkill_poll; - /* TX Power */ s8 tx_power_user_lmt; s8 tx_power_device_lmt; @@ -1339,12 +1347,6 @@ struct iwl_priv { struct timer_list statistics_periodic; struct timer_list ucode_trace; bool hw_ready; - /*For 3945*/ -#define IWL_DEFAULT_TX_POWER 0x0F - - struct iwl3945_notif_statistics statistics_39; - - u32 sta_supp_rates; struct iwl_event_log event_log; }; /*iwl_priv */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 54daa38ecba3..1b3a1ba4ed96 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -351,11 +351,11 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) static void iwl3945_unset_hw_params(struct iwl_priv *priv) { - if (priv->shared_virt) + if (priv->_3945.shared_virt) dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl3945_shared), - priv->shared_virt, - priv->shared_phys); + priv->_3945.shared_virt, + priv->_3945.shared_phys); } static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, @@ -2786,7 +2786,7 @@ static void iwl3945_bg_alive_start(struct work_struct *data) static void iwl3945_rfkill_poll(struct work_struct *data) { struct iwl_priv *priv = - container_of(data, struct iwl_priv, rfkill_poll.work); + container_of(data, struct iwl_priv, _3945.rfkill_poll.work); bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status); bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); @@ -2805,7 +2805,7 @@ static void iwl3945_rfkill_poll(struct work_struct *data) /* Keep this running, even if radio now enabled. This will be * cancelled in mac_start() if system decides to start again */ - queue_delayed_work(priv->workqueue, &priv->rfkill_poll, + queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll, round_jiffies_relative(2 * HZ)); } @@ -3212,7 +3212,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) /* ucode is running and will send rfkill notifications, * no need to poll the killswitch state anymore */ - cancel_delayed_work(&priv->rfkill_poll); + cancel_delayed_work(&priv->_3945.rfkill_poll); iwl_led_start(priv); @@ -3253,7 +3253,7 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw) flush_workqueue(priv->workqueue); /* start polling the killswitch state again */ - queue_delayed_work(priv->workqueue, &priv->rfkill_poll, + queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll, round_jiffies_relative(2 * HZ)); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -3660,7 +3660,7 @@ static ssize_t show_statistics(struct device *d, struct iwl_priv *priv = dev_get_drvdata(d); u32 size = sizeof(struct iwl3945_notif_statistics); u32 len = 0, ofs = 0; - u8 *data = (u8 *)&priv->statistics_39; + u8 *data = (u8 *)&priv->_3945.statistics; int rc = 0; if (!iwl_is_alive(priv)) @@ -3773,7 +3773,7 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); - INIT_DELAYED_WORK(&priv->rfkill_poll, iwl3945_rfkill_poll); + INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll); INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan); INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); @@ -4129,7 +4129,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); /* Start monitoring the killswitch */ - queue_delayed_work(priv->workqueue, &priv->rfkill_poll, + queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll, 2 * HZ); return 0; @@ -4203,7 +4203,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); - cancel_delayed_work_sync(&priv->rfkill_poll); + cancel_delayed_work_sync(&priv->_3945.rfkill_poll); iwl3945_dealloc_ucode_pci(priv); -- cgit v1.2.3 From a4c8b2a692601de0a7bcb032b69f806050944dff Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 06:25:54 -0800 Subject: iwlwifi: move ICT data to agn part of union Since the ICT data is all AGN specific, it can be the first data to create the _agn part of the device-specific union in the priv struct. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-ict.c | 78 +++++++++++++++--------------- drivers/net/wireless/iwlwifi/iwl-agn.c | 8 +-- drivers/net/wireless/iwlwifi/iwl-dev.h | 21 ++++---- 3 files changed, 56 insertions(+), 51 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c index d6b028b1b6ef..4c5395eae956 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c @@ -42,11 +42,12 @@ /* Free dram table */ void iwl_free_isr_ict(struct iwl_priv *priv) { - if (priv->ict_tbl_vir) { + if (priv->_agn.ict_tbl_vir) { dma_free_coherent(&priv->pci_dev->dev, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - priv->ict_tbl_vir, priv->ict_tbl_dma); - priv->ict_tbl_vir = NULL; + priv->_agn.ict_tbl_vir, + priv->_agn.ict_tbl_dma); + priv->_agn.ict_tbl_vir = NULL; } } @@ -60,30 +61,31 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv) if (priv->cfg->use_isr_legacy) return 0; /* allocate shrared data table */ - priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - &priv->ict_tbl_dma, GFP_KERNEL); - if (!priv->ict_tbl_vir) + priv->_agn.ict_tbl_vir = + dma_alloc_coherent(&priv->pci_dev->dev, + (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, + &priv->_agn.ict_tbl_dma, GFP_KERNEL); + if (!priv->_agn.ict_tbl_vir) return -ENOMEM; /* align table to PAGE_SIZE boundry */ - priv->aligned_ict_tbl_dma = ALIGN(priv->ict_tbl_dma, PAGE_SIZE); + priv->_agn.aligned_ict_tbl_dma = ALIGN(priv->_agn.ict_tbl_dma, PAGE_SIZE); IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", - (unsigned long long)priv->ict_tbl_dma, - (unsigned long long)priv->aligned_ict_tbl_dma, - (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); + (unsigned long long)priv->_agn.ict_tbl_dma, + (unsigned long long)priv->_agn.aligned_ict_tbl_dma, + (int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma)); - priv->ict_tbl = priv->ict_tbl_vir + - (priv->aligned_ict_tbl_dma - priv->ict_tbl_dma); + priv->_agn.ict_tbl = priv->_agn.ict_tbl_vir + + (priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma); IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", - priv->ict_tbl, priv->ict_tbl_vir, - (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); + priv->_agn.ict_tbl, priv->_agn.ict_tbl_vir, + (int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma)); /* reset table and index to all 0 */ - memset(priv->ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); - priv->ict_index = 0; + memset(priv->_agn.ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); + priv->_agn.ict_index = 0; /* add periodic RX interrupt */ priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; @@ -98,26 +100,26 @@ int iwl_reset_ict(struct iwl_priv *priv) u32 val; unsigned long flags; - if (!priv->ict_tbl_vir) + if (!priv->_agn.ict_tbl_vir) return 0; spin_lock_irqsave(&priv->lock, flags); iwl_disable_interrupts(priv); - memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); + memset(&priv->_agn.ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); - val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT; + val = priv->_agn.aligned_ict_tbl_dma >> PAGE_SHIFT; val |= CSR_DRAM_INT_TBL_ENABLE; val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " "aligned dma address %Lx\n", - val, (unsigned long long)priv->aligned_ict_tbl_dma); + val, (unsigned long long)priv->_agn.aligned_ict_tbl_dma); iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); - priv->use_ict = true; - priv->ict_index = 0; + priv->_agn.use_ict = true; + priv->_agn.ict_index = 0; iwl_write32(priv, CSR_INT, priv->inta_mask); iwl_enable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); @@ -131,7 +133,7 @@ void iwl_disable_ict(struct iwl_priv *priv) unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - priv->use_ict = false; + priv->_agn.use_ict = false; spin_unlock_irqrestore(&priv->lock, flags); } @@ -180,11 +182,11 @@ static irqreturn_t iwl_isr(int irq, void *data) } #endif - priv->inta |= inta; + priv->_agn.inta |= inta; /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) tasklet_schedule(&priv->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) iwl_enable_interrupts(priv); unplugged: @@ -194,7 +196,7 @@ static irqreturn_t iwl_isr(int irq, void *data) none: /* re-enable interrupts here since we don't have anything to service. */ /* only Re-enable if diabled by irq and no schedules tasklet. */ - if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) iwl_enable_interrupts(priv); spin_unlock(&priv->lock); @@ -221,7 +223,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) /* dram interrupt table not set yet, * use legacy interrupt. */ - if (!priv->use_ict) + if (!priv->_agn.use_ict) return iwl_isr(irq, data); spin_lock(&priv->lock); @@ -238,20 +240,20 @@ irqreturn_t iwl_isr_ict(int irq, void *data) /* Ignore interrupt if there's nothing in NIC to service. * This may be due to IRQ shared with another device, * or due to sporadic interrupts thrown from our NIC. */ - if (!priv->ict_tbl[priv->ict_index]) { + if (!priv->_agn.ict_tbl[priv->_agn.ict_index]) { IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); goto none; } /* read all entries that not 0 start with ict_index */ - while (priv->ict_tbl[priv->ict_index]) { + while (priv->_agn.ict_tbl[priv->_agn.ict_index]) { - val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]); + val |= le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index]); IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", - priv->ict_index, - le32_to_cpu(priv->ict_tbl[priv->ict_index])); - priv->ict_tbl[priv->ict_index] = 0; - priv->ict_index = iwl_queue_inc_wrap(priv->ict_index, + priv->_agn.ict_index, + le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index])); + priv->_agn.ict_tbl[priv->_agn.ict_index] = 0; + priv->_agn.ict_index = iwl_queue_inc_wrap(priv->_agn.ict_index, ICT_COUNT); } @@ -275,12 +277,12 @@ irqreturn_t iwl_isr_ict(int irq, void *data) inta, inta_mask, val); inta &= priv->inta_mask; - priv->inta |= inta; + priv->_agn.inta |= inta; /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) tasklet_schedule(&priv->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) { + else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) { /* Allow interrupt if was disabled by this handler and * no tasklet was schedules, We should not enable interrupt, * tasklet will enable it. @@ -295,7 +297,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) /* re-enable interrupts here since we don't have anything to service. * only Re-enable if disabled by irq. */ - if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) iwl_enable_interrupts(priv); spin_unlock(&priv->lock); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d7b8e44985b3..d0fab876df05 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1259,9 +1259,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) /* Ack/clear/reset pending uCode interrupts. * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, */ - iwl_write32(priv, CSR_INT, priv->inta); + iwl_write32(priv, CSR_INT, priv->_agn.inta); - inta = priv->inta; + inta = priv->_agn.inta; #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_get_debug_level(priv) & IWL_DL_ISR) { @@ -1274,8 +1274,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); - /* saved interrupt in inta variable now we can reset priv->inta */ - priv->inta = 0; + /* saved interrupt in inta variable now we can reset priv->_agn.inta */ + priv->_agn.inta = 0; /* Now service all interrupt bits discovered above. */ if (inta & CSR_INT_BIT_HW_ERR) { diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index e6cae3884879..f9210b78ffc1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1275,20 +1275,23 @@ struct iwl_priv { u32 sta_supp_rates; } _3945; +#endif +#if defined(CONFIG_IWLAGN) || defined(CONFIG_IWLAGN_MODULE) + struct { + /* INT ICT Table */ + __le32 *ict_tbl; + void *ict_tbl_vir; + dma_addr_t ict_tbl_dma; + dma_addr_t aligned_ict_tbl_dma; + int ict_index; + u32 inta; + bool use_ict; + } _agn; #endif }; struct iwl_hw_params hw_params; - /* INT ICT Table */ - __le32 *ict_tbl; - dma_addr_t ict_tbl_dma; - dma_addr_t aligned_ict_tbl_dma; - int ict_index; - void *ict_tbl_vir; - u32 inta; - bool use_ict; - u32 inta_mask; /* Current association information needed to configure the * hardware */ -- cgit v1.2.3 From e99f168c7cc2f78c07c23250fe933362847cb3e0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 19 Jan 2010 10:04:28 -0800 Subject: iwlagn: remove write-only variables Updating the variables last_rx_rssi, last_tsf and last_beacon_time needs a lot of code but they are not actually used in iwlagn (only in 3945) so we can move them to the 3945 specific data. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 8 ++------ drivers/net/wireless/iwlwifi/iwl-dev.h | 10 +++++----- drivers/net/wireless/iwlwifi/iwl-rx.c | 24 ------------------------ drivers/net/wireless/iwlwifi/iwl3945-base.c | 6 +++--- 6 files changed, 15 insertions(+), 42 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index effdd3670da4..b588cb69536a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -946,7 +946,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) spin_unlock_irqrestore(&rs_sta->lock, flags); - rssi = priv->last_rx_rssi; + rssi = priv->_3945.last_rx_rssi; if (rssi == 0) rssi = IWL_MIN_RSSI_VAL; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 867bd69270f8..9a5a7b100e6b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -705,9 +705,10 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header); if (network_packet) { - priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp); - priv->last_tsf = le64_to_cpu(rx_end->timestamp); - priv->last_rx_rssi = rx_status.signal; + priv->_3945.last_beacon_time = + le32_to_cpu(rx_end->beacon_timestamp); + priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp); + priv->_3945.last_rx_rssi = rx_status.signal; priv->last_rx_noise = rx_status.noise; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 8bf7c20b9d39..696e668b801d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2956,12 +2956,8 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, desc += sprintf(buff+desc, "Bit Rate= %d Mb/s\n", iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); - desc += sprintf(buff+desc, - "Signal Level= %d dBm\tNoise Level= %d dBm\n", - priv->last_rx_rssi, priv->last_rx_noise); - desc += sprintf(buff+desc, - "Tsf= 0x%llx\tBeacon time= 0x%08X\n", - priv->last_tsf, priv->last_beacon_time); + desc += sprintf(buff+desc, "Noise Level= %d dBm\n", + priv->last_rx_noise); ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f9210b78ffc1..c277e4e8cf87 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1197,7 +1197,6 @@ struct iwl_priv { unsigned long status; - int last_rx_rssi; /* From Rx packet statistics */ int last_rx_noise; /* From beacon statistics */ /* counts mgmt, ctl, and data packets */ @@ -1244,10 +1243,6 @@ struct iwl_priv { u8 mac80211_registered; - /* Rx'd packet timing information */ - u32 last_beacon_time; - u64 last_tsf; - /* eeprom -- this is in the card's little endian byte order */ u8 *eeprom; int nvm_device_type; @@ -1274,6 +1269,11 @@ struct iwl_priv { struct iwl3945_notif_statistics statistics; u32 sta_supp_rates; + int last_rx_rssi; /* From Rx packet statistics */ + + /* Rx'd packet timing information */ + u32 last_beacon_time; + u64 last_tsf; } _3945; #endif #if defined(CONFIG_IWLAGN) || defined(CONFIG_IWLAGN_MODULE) diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index df257bc15f49..8116aa0d7678 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -1036,24 +1036,6 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, rxb->page = NULL; } -/* This is necessary only for a number of statistics, see the caller. */ -static int iwl_is_network_packet(struct iwl_priv *priv, - struct ieee80211_hdr *header) -{ - /* Filter incoming packets to determine if they are targeted toward - * this network, discarding packets coming from ourselves */ - switch (priv->iw_mode) { - case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */ - /* packets to our IBSS update information */ - return !compare_ether_addr(header->addr3, priv->bssid); - case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */ - /* packets to our IBSS update information */ - return !compare_ether_addr(header->addr2, priv->bssid); - default: - return 1; - } -} - /* Called for REPLY_RX (legacy ABG frames), or * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ void iwl_rx_reply_rx(struct iwl_priv *priv, @@ -1190,12 +1172,6 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, if (rate_n_flags & RATE_MCS_SGI_MSK) rx_status.flag |= RX_FLAG_SHORT_GI; - if (iwl_is_network_packet(priv, header)) { - priv->last_rx_rssi = rx_status.signal; - priv->last_beacon_time = priv->ucode_beacon_time; - priv->last_tsf = le64_to_cpu(phy_res->timestamp); - } - iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, rxb, &rx_status); } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 1b3a1ba4ed96..a825092fff90 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -753,7 +753,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, if (iwl_is_associated(priv)) add_time = iwl3945_usecs_to_beacons( - le64_to_cpu(params->start_time) - priv->last_tsf, + le64_to_cpu(params->start_time) - priv->_3945.last_tsf, le16_to_cpu(priv->rxon_timing.beacon_interval)); memset(&spectrum, 0, sizeof(spectrum)); @@ -767,7 +767,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, if (iwl_is_associated(priv)) spectrum.start_time = - iwl3945_add_beacon_time(priv->last_beacon_time, + iwl3945_add_beacon_time(priv->_3945.last_beacon_time, add_time, le16_to_cpu(priv->rxon_timing.beacon_interval)); else @@ -3590,7 +3590,7 @@ static ssize_t store_measurement(struct device *d, struct iwl_priv *priv = dev_get_drvdata(d); struct ieee80211_measurement_params params = { .channel = le16_to_cpu(priv->active_rxon.channel), - .start_time = cpu_to_le64(priv->last_tsf), + .start_time = cpu_to_le64(priv->_3945.last_tsf), .duration = cpu_to_le16(1), }; u8 type = IWL_MEASURE_BASIC; -- cgit v1.2.3 From d6bde7d9508f9ce9a5d57b1c0fa48f43fc5defa8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 07:26:26 -0800 Subject: iwlwifi: remove superfluous channel check mac80211 will not allow using channels not marked as allowing IBSS for IBSS mode. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b994eee771a0..166087d6f72c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1238,14 +1238,6 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) if (!ch_info) ch_info = &priv->channel_info[0]; - /* - * in some case A channels are all non IBSS - * in this case force B/G channel - */ - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && - !(is_channel_ibss(ch_info))) - ch_info = &priv->channel_info[0]; - priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); priv->band = ch_info->band; -- cgit v1.2.3 From b4665df448b316fd5282f4947e27eaf92dc105bb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 07:32:58 -0800 Subject: iwlwifi: remove dead code from iwl_mac_reset_tsf iwl_mac_reset_tsf will only ever be called in IBSS mode, so checking for other modes is not useful and the code that depends on that will not be executed. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 166087d6f72c..1cfcc9fe9dc3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2597,8 +2597,6 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) priv->beacon_int = priv->vif->bss_conf.beacon_int; priv->timestamp = 0; - if ((priv->iw_mode == NL80211_IFTYPE_STATION)) - priv->beacon_int = 0; spin_unlock_irqrestore(&priv->lock, flags); @@ -2611,17 +2609,9 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) /* we are restarting association process * clear RXON_FILTER_ASSOC_MSK bit */ - if (priv->iw_mode != NL80211_IFTYPE_AP) { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - } - - if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); - mutex_unlock(&priv->mutex); - return; - } + iwl_scan_cancel_timeout(priv, 100); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv); iwl_set_rate(priv); -- cgit v1.2.3 From 254aebf3d0439e7b0a8318f1604b3fdb4144f689 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Feb 2010 10:56:57 -0800 Subject: iwlwifi: remove frame dropping With some of the new code in mac80211, public action frames can be exchanged as non-injected frames even while not associated. Aside from that, dropping frames here is pointless since we do deal with arbitrary frames that were injected already, so let mac80211 make the decision about which frames to allow or not. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-tx.c | 10 ---------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 9 --------- 2 files changed, 19 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 1ed5206721ec..08b33fcc0792 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -761,16 +761,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); #endif - /* drop all non-injected data frame if we are not associated */ - if (ieee80211_is_data(fc) && - !(info->flags & IEEE80211_TX_CTL_INJECTED) && - (!iwl_is_associated(priv) || - ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) || - !priv->assoc_station_added)) { - IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n"); - goto drop_unlock; - } - hdr_len = ieee80211_hdrlen(fc); /* Find (or create) index into station table for destination station */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index a825092fff90..2b2c96bf5a53 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -504,15 +504,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); #endif - /* drop all non-injected data frame if we are not associated */ - if (ieee80211_is_data(fc) && - !(info->flags & IEEE80211_TX_CTL_INJECTED) && - (!iwl_is_associated(priv) || - ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) { - IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n"); - goto drop_unlock; - } - spin_unlock_irqrestore(&priv->lock, flags); hdr_len = ieee80211_hdrlen(fc); -- cgit v1.2.3 From 470ab2dd6a7b0719e59830e11d7bc2e710867b94 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 11:23:30 -0800 Subject: iwlwifi: remove never-changing priv->rates_mask variable It's always just IWL_RATES_MASK. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 5 ++--- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 -- drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 ++--- 3 files changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d0fab876df05..e7e4bf71568c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2103,8 +2103,8 @@ static void iwl_alive_start(struct iwl_priv *priv) ieee80211_wake_queues(priv->hw); - priv->active_rate = priv->rates_mask; - priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; + priv->active_rate = IWL_RATES_MASK; + priv->active_rate_basic = IWL_RATES_MASK & IWL_BASIC_RATES_MASK; /* Configure Tx antenna selection based on H/W config */ if (priv->cfg->ops->hcmd->set_tx_ant) @@ -3392,7 +3392,6 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->qos_data.qos_active = 0; priv->qos_data.qos_cap.val = 0; - priv->rates_mask = IWL_RATES_MASK; /* Set the tx_power_user_lmt to the lowest power level * this value will get overwritten by channel max power avg * from eeprom */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c277e4e8cf87..4d6558fbebe5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1217,8 +1217,6 @@ struct iwl_priv { #endif /* context information */ - u16 rates_mask; - u8 bssid[ETH_ALEN]; u16 rts_threshold; u8 mac_addr[ETH_ALEN]; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 2b2c96bf5a53..b2b050592bc1 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2508,8 +2508,8 @@ static void iwl3945_alive_start(struct iwl_priv *priv) ieee80211_wake_queues(priv->hw); - priv->active_rate = priv->rates_mask; - priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; + priv->active_rate = IWL_RATES_MASK; + priv->active_rate_basic = IWL_RATES_MASK & IWL_BASIC_RATES_MASK; iwl_power_update_mode(priv, true); @@ -3855,7 +3855,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) priv->qos_data.qos_active = 0; priv->qos_data.qos_cap.val = 0; - priv->rates_mask = IWL_RATES_MASK; priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { -- cgit v1.2.3 From 4a02886bae3f2362d4e6efc6fb25dd3507bde8b9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 11:33:19 -0800 Subject: iwlwifi: remove priv->active_rate_basic This variable is assigned a default value, but then assigned zero as soon as mac80211 calls a change channel (which will happen right after the hw is started) and after that it never changes again. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 5 --- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 1 - drivers/net/wireless/iwlwifi/iwl-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl-core.c | 51 ++++++----------------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 - 6 files changed, 10 insertions(+), 50 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 696e668b801d..84271cc62afa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -597,10 +597,6 @@ static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, struct ieee80211_hdr *hdr, enum iwl_table_type rate_type) { - if (hdr && is_multicast_ether_addr(hdr->addr1) && - lq_sta->active_rate_basic) - return lq_sta->active_rate_basic; - if (is_legacy(rate_type)) { return lq_sta->active_legacy_rate; } else { @@ -2552,7 +2548,6 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); - lq_sta->active_rate_basic = priv->active_rate_basic; lq_sta->band = priv->band; /* * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index e71923961e69..e182f5a0f736 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -411,7 +411,6 @@ struct iwl_lq_sta { u16 active_siso_rate; u16 active_mimo2_rate; u16 active_mimo3_rate; - u16 active_rate_basic; s8 max_rate_idx; /* Max rate set by user */ u8 missed_rate_counter; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e7e4bf71568c..fbbe99859662 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2104,7 +2104,6 @@ static void iwl_alive_start(struct iwl_priv *priv) ieee80211_wake_queues(priv->hw); priv->active_rate = IWL_RATES_MASK; - priv->active_rate_basic = IWL_RATES_MASK & IWL_BASIC_RATES_MASK; /* Configure Tx antenna selection based on H/W config */ if (priv->cfg->ops->hcmd->set_tx_ant) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 1cfcc9fe9dc3..8e8f5282c01c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -897,23 +897,10 @@ EXPORT_SYMBOL(iwl_full_rxon_required); u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) { - int i; - int rate_mask; - - /* Set rate mask*/ - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) - rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK; - else - rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK; - - /* Find lowest valid rate */ - for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID; - i = iwl_rates[i].next_ieee) { - if (rate_mask & (1 << i)) - return iwl_rates[i].plcp; - } - - /* No valid rate was found. Assign the lowest one */ + /* + * Assign the lowest rate -- should really get this from + * the beacon skb from mac80211. + */ if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) return IWL_RATE_1M_PLCP; else @@ -1272,7 +1259,6 @@ static void iwl_set_rate(struct iwl_priv *priv) } priv->active_rate = 0; - priv->active_rate_basic = 0; for (i = 0; i < hw->n_bitrates; i++) { rate = &(hw->bitrates[i]); @@ -1280,30 +1266,13 @@ static void iwl_set_rate(struct iwl_priv *priv) priv->active_rate |= (1 << rate->hw_value); } - IWL_DEBUG_RATE(priv, "Set active_rate = %0x, active_rate_basic = %0x\n", - priv->active_rate, priv->active_rate_basic); + IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate); - /* - * If a basic rate is configured, then use it (adding IWL_RATE_1M_MASK) - * otherwise set it to the default of all CCK rates and 6, 12, 24 for - * OFDM - */ - if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK) - priv->staging_rxon.cck_basic_rates = - ((priv->active_rate_basic & - IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF; - else - priv->staging_rxon.cck_basic_rates = - (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; - - if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK) - priv->staging_rxon.ofdm_basic_rates = - ((priv->active_rate_basic & - (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >> - IWL_FIRST_OFDM_RATE) & 0xFF; - else - priv->staging_rxon.ofdm_basic_rates = - (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; + priv->staging_rxon.cck_basic_rates = + (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; + + priv->staging_rxon.ofdm_basic_rates = + (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; } void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 4d6558fbebe5..ba404b99f4fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1168,7 +1168,6 @@ struct iwl_priv { u64 led_tpt; u16 active_rate; - u16 active_rate_basic; u8 assoc_station_added; u8 start_calib; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b2b050592bc1..9cc15f96d208 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2509,7 +2509,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv) ieee80211_wake_queues(priv->hw); priv->active_rate = IWL_RATES_MASK; - priv->active_rate_basic = IWL_RATES_MASK & IWL_BASIC_RATES_MASK; iwl_power_update_mode(priv, true); -- cgit v1.2.3 From b2f30e8bdd8ef5f3b5a7ef9146509585a15347d3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 07:32:20 -0800 Subject: iwlwifi: remove IBSS channel sanity check mac80211 will always enforce using a channel that the driver allowed for IBSS use. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8e8f5282c01c..4365e853f4b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2436,15 +2436,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) goto set_ch_out; } - if (priv->iw_mode == NL80211_IFTYPE_ADHOC && - !is_channel_ibss(ch_info)) { - IWL_ERR(priv, "channel %d in band %d not " - "IBSS channel\n", - conf->channel->hw_value, conf->channel->band); - ret = -EINVAL; - goto set_ch_out; - } - spin_lock_irqsave(&priv->lock, flags); /* Configure HT40 channels */ -- cgit v1.2.3 From fbc66daa82b0f0aaae393323bcb9766a8b64e632 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 07:31:07 -0800 Subject: iwlwifi: remove sanity check iwl_mac_beacon_update can only be called when the operating mode is IBSS, so it doesn't need to verify that again. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 4365e853f4b4..5fa1da1f59c9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2252,11 +2252,6 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) return -EIO; } - if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n"); - return -EIO; - } - spin_lock_irqsave(&priv->lock, flags); if (priv->ibss_beacon) -- cgit v1.2.3 From 949cd92c85fbdf9550582fc09271fa91cc802069 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 22 Jan 2010 04:06:41 -0800 Subject: iwlwifi: clear up AC/FIFO debug output Not all queues are mapped for frame transmission, so saying "AC" is misleading. They are all mapped to FIFOs, obviously, though, so use that term and also say AC/CMD instead of just AC for the queue type. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index f59628c1c1ce..4c0ef013acbf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -580,9 +580,9 @@ static void iwl5000_tx_queue_set_status(struct iwl_priv *priv, txq->sched_retry = scd_retry; - IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n", + IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", active ? "Activate" : "Deactivate", - scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); + scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); } int iwl5000_alive_notify(struct iwl_priv *priv) -- cgit v1.2.3 From 67d613aed70194387edb1f8bf990f9cf197d3717 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 17 Feb 2010 02:39:19 -0800 Subject: iwlwifi: move 3945 clip groups to 3945 data Only used on 3945, so it can be in the 3945-specific part of the data. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945.c | 8 ++++---- drivers/net/wireless/iwlwifi/iwl-dev.h | 12 ++++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 9a5a7b100e6b..ed59e2744ca4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1607,7 +1607,7 @@ static int iwl3945_hw_reg_set_new_power(struct iwl_priv *priv, int power; /* Get this chnlgrp's rate-to-max/clip-powers table */ - clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; + clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers; /* Get this channel's rate-to-current-power settings table */ power_info = ch_info->power_info; @@ -1733,7 +1733,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv) } /* Get this chnlgrp's rate-to-max/clip-powers table */ - clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; + clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers; /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */ for (scan_tbl_index = 0; @@ -2140,7 +2140,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv) * power peaks, without too much distortion (clipping). */ /* we'll fill in this array with h/w max power levels */ - clip_pwrs = (s8 *) priv->clip39_groups[i].clip_powers; + clip_pwrs = (s8 *) priv->_3945.clip_groups[i].clip_powers; /* divide factory saturation power by 2 to find -3dB level */ satur_pwr = (s8) (group->saturation_power >> 1); @@ -2224,7 +2224,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) iwl3945_hw_reg_get_ch_grp_index(priv, ch_info); /* Get this chnlgrp's rate->max/clip-powers table */ - clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; + clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers; /* calculate power index *adjustment* value according to * diff between current temperature and factory temperature */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index ba404b99f4fe..90d2b6e0df76 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1092,10 +1092,6 @@ struct iwl_priv { struct iwl_channel_info *channel_info; /* channel info array */ u8 channel_count; /* # of channels */ - /* each calibration channel group in the EEPROM has a derived - * clip setting for each rate. 3945 only.*/ - const struct iwl3945_clip_group clip39_groups[5]; - /* thermal calibration */ s32 temperature; /* degrees Kelvin */ s32 last_temperature; @@ -1271,6 +1267,14 @@ struct iwl_priv { /* Rx'd packet timing information */ u32 last_beacon_time; u64 last_tsf; + + /* + * each calibration channel group in the + * EEPROM has a derived clip setting for + * each rate. + */ + const struct iwl3945_clip_group clip_groups[5]; + } _3945; #endif #if defined(CONFIG_IWLAGN) || defined(CONFIG_IWLAGN_MODULE) -- cgit v1.2.3 From 76c9cc18fd2c8cfa5a7f66d5496d469db00eaf54 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 17 Feb 2010 01:43:41 -0800 Subject: iwlwifi: remove alive start adhoc restart This code will never trigger, because when we call this during interface start, neither priv->vif nor priv->iw_mode conditions will be true, and when it happens during reset then priv->vif is also NULL. Also, in both cases the same code will be executed as part of iwl_bss_info_changed(), which contains a copy of this code. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 9 --------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 8 -------- 2 files changed, 17 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index fbbe99859662..b07c013e273b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2144,15 +2144,6 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl_power_update_mode(priv, true); - /* reassociate for ADHOC mode */ - if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { - struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, - priv->vif); - if (beacon) - iwl_mac_beacon_update(priv->hw, beacon); - } - - if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) iwl_set_mode(priv, priv->iw_mode); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 9cc15f96d208..bdd5fc74bce4 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2537,14 +2537,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv) set_bit(STATUS_READY, &priv->status); wake_up_interruptible(&priv->wait_command_queue); - /* reassociate for ADHOC mode */ - if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { - struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, - priv->vif); - if (beacon) - iwl_mac_beacon_update(priv->hw, beacon); - } - if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) iwl_set_mode(priv, priv->iw_mode); -- cgit v1.2.3 From b55e75ed926ded110293b0d1e24eb6a878883115 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 17 Feb 2010 04:54:08 -0800 Subject: iwlwifi: remove STATUS_MODE_PENDING Since rfkill integration, mac80211 can no longer add an interface while the hardware is not ready, so STATUS_MODE_PENDING can never be set. Also, remove another superfluous channel sanity check and return the commit_rxon return value in case it failed. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 3 -- drivers/net/wireless/iwlwifi/iwl-core.c | 53 +++++++++++------------------ drivers/net/wireless/iwlwifi/iwl-core.h | 2 -- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 -- drivers/net/wireless/iwlwifi/iwl3945-base.c | 3 -- 5 files changed, 19 insertions(+), 44 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b07c013e273b..6c816d9b5240 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2144,9 +2144,6 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl_power_update_mode(priv, true); - if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) - iwl_set_mode(priv, priv->iw_mode); - return; restart: diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5fa1da1f59c9..a962fb3cb35c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2275,23 +2275,9 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) } EXPORT_SYMBOL(iwl_mac_beacon_update); -int iwl_set_mode(struct iwl_priv *priv, int mode) +static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) { - if (mode == NL80211_IFTYPE_ADHOC) { - const struct iwl_channel_info *ch_info; - - ch_info = iwl_get_channel_info(priv, - priv->band, - le16_to_cpu(priv->staging_rxon.channel)); - - if (!ch_info || !is_channel_ibss(ch_info)) { - IWL_ERR(priv, "channel %d not IBSS channel\n", - le16_to_cpu(priv->staging_rxon.channel)); - return -EINVAL; - } - } - - iwl_connection_init_rx_config(priv, mode); + iwl_connection_init_rx_config(priv, vif->type); if (priv->cfg->ops->hcmd->set_rxon_chain) priv->cfg->ops->hcmd->set_rxon_chain(priv); @@ -2300,18 +2286,10 @@ int iwl_set_mode(struct iwl_priv *priv, int mode) iwl_clear_stations_table(priv); - /* dont commit rxon if rf-kill is on*/ - if (!iwl_is_ready_rf(priv)) - return -EAGAIN; - - iwlcore_commit_rxon(priv); - - return 0; + return iwlcore_commit_rxon(priv); } -EXPORT_SYMBOL(iwl_set_mode); -int iwl_mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; int err = 0; @@ -2320,6 +2298,11 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); + if (WARN_ON(!iwl_is_ready_rf(priv))) { + err = -EINVAL; + goto out; + } + if (priv->vif) { IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); err = -EOPNOTSUPP; @@ -2329,15 +2312,17 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, priv->vif = vif; priv->iw_mode = vif->type; - if (vif->addr) { - IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); - memcpy(priv->mac_addr, vif->addr, ETH_ALEN); - } + IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); + memcpy(priv->mac_addr, vif->addr, ETH_ALEN); - if (iwl_set_mode(priv, vif->type) == -EAGAIN) - /* we are not ready, will run again when ready */ - set_bit(STATUS_MODE_PENDING, &priv->status); + err = iwl_set_mode(priv, vif); + if (err) + goto out_err; + goto out; + out_err: + priv->vif = NULL; + priv->iw_mode = NL80211_IFTYPE_STATION; out: mutex_unlock(&priv->mutex); @@ -2347,7 +2332,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, EXPORT_SYMBOL(iwl_mac_add_interface); void iwl_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) + struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index f493248d4727..bec00c790596 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -336,7 +336,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, u32 changes); int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); int iwl_commit_rxon(struct iwl_priv *priv); -int iwl_set_mode(struct iwl_priv *priv, int mode); int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void iwl_mac_remove_interface(struct ieee80211_hw *hw, @@ -617,7 +616,6 @@ void iwlcore_free_geos(struct iwl_priv *priv); #define STATUS_SCAN_HW 15 #define STATUS_POWER_PMI 16 #define STATUS_FW_ERROR 17 -#define STATUS_MODE_PENDING 18 static inline int iwl_is_ready(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 7bf44f146799..fc084dd2d14e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -560,8 +560,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, test_bit(STATUS_POWER_PMI, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", test_bit(STATUS_FW_ERROR, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_MODE_PENDING:\t %d\n", - test_bit(STATUS_MODE_PENDING, &priv->status)); return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index bdd5fc74bce4..2fd1b3d4949a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2537,9 +2537,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv) set_bit(STATUS_READY, &priv->status); wake_up_interruptible(&priv->wait_command_queue); - if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) - iwl_set_mode(priv, priv->iw_mode); - return; restart: -- cgit v1.2.3 From 60987206cba0dbb547bce2d23c3a3338c5aaf5ac Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Feb 2010 00:36:07 -0800 Subject: iwlagn: move sysfs flags and filter_flags files to debugfs These files are incompatible with some changes I'm making, and don't really belong into sysfs anyway as they can only be used for debugging. Since writing them will probably crash the firmware, keep only the reading part and move them into debugfs. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 83 ------------------------------ drivers/net/wireless/iwlwifi/iwl-debugfs.c | 29 +++++++++++ 2 files changed, 29 insertions(+), 83 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6c816d9b5240..bc84fd4a8d29 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3109,87 +3109,6 @@ static ssize_t store_tx_power(struct device *d, static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); -static ssize_t show_flags(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - - return sprintf(buf, "0x%04X\n", priv->active_rxon.flags); -} - -static ssize_t store_flags(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - unsigned long val; - u32 flags; - int ret = strict_strtoul(buf, 0, &val); - if (ret) - return ret; - flags = (u32)val; - - mutex_lock(&priv->mutex); - if (le32_to_cpu(priv->staging_rxon.flags) != flags) { - /* Cancel any currently running scans... */ - if (iwl_scan_cancel_timeout(priv, 100)) - IWL_WARN(priv, "Could not cancel scan.\n"); - else { - IWL_DEBUG_INFO(priv, "Commit rxon.flags = 0x%04X\n", flags); - priv->staging_rxon.flags = cpu_to_le32(flags); - iwlcore_commit_rxon(priv); - } - } - mutex_unlock(&priv->mutex); - - return count; -} - -static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags); - -static ssize_t show_filter_flags(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - - return sprintf(buf, "0x%04X\n", - le32_to_cpu(priv->active_rxon.filter_flags)); -} - -static ssize_t store_filter_flags(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - unsigned long val; - u32 filter_flags; - int ret = strict_strtoul(buf, 0, &val); - if (ret) - return ret; - filter_flags = (u32)val; - - mutex_lock(&priv->mutex); - if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) { - /* Cancel any currently running scans... */ - if (iwl_scan_cancel_timeout(priv, 100)) - IWL_WARN(priv, "Could not cancel scan.\n"); - else { - IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = " - "0x%04X\n", filter_flags); - priv->staging_rxon.filter_flags = - cpu_to_le32(filter_flags); - iwlcore_commit_rxon(priv); - } - } - mutex_unlock(&priv->mutex); - - return count; -} - -static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, - store_filter_flags); - - static ssize_t show_statistics(struct device *d, struct device_attribute *attr, char *buf) { @@ -3414,8 +3333,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv) } static struct attribute *iwl_sysfs_entries[] = { - &dev_attr_flags.attr, - &dev_attr_filter_flags.attr, &dev_attr_statistics.attr, &dev_attr_temperature.attr, &dev_attr_tx_power.attr, diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index fc084dd2d14e..50d0ee96629e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2093,6 +2093,31 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + int len = 0; + char buf[20]; + + len = sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.flags)); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + int len = 0; + char buf[20]; + + len = sprintf(buf, "0x%04X\n", + le32_to_cpu(priv->active_rxon.filter_flags)); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -2296,6 +2321,8 @@ DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); DEBUGFS_WRITE_FILE_OPS(internal_scan); DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); DEBUGFS_READ_WRITE_FILE_OPS(force_reset); +DEBUGFS_READ_FILE_OPS(rxon_flags); +DEBUGFS_READ_FILE_OPS(rxon_filter_flags); /* * Create the debugfs files and directories @@ -2358,6 +2385,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); } + DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); + DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal); DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, &priv->disable_chain_noise_cal); -- cgit v1.2.3 From 4967c31677cf3c6c49aadf205f1a31d15d7610da Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 18 Feb 2010 15:22:07 -0800 Subject: iwlwifi: remove un-necessary parameters small code cleanup to remove un-necessary parameters Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 50d0ee96629e..d9255b53be10 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -658,7 +658,6 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, int pos = 0, i; char buf[256]; const size_t bufsz = sizeof(buf); - ssize_t ret; for (i = 0; i < AC_NUM; i++) { pos += scnprintf(buf + pos, bufsz - pos, @@ -670,8 +669,7 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, priv->qos_data.def_qos_parm.ac[i].aifsn, priv->qos_data.def_qos_parm.ac[i].edca_txop); } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, @@ -681,7 +679,6 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, int pos = 0; char buf[256]; const size_t bufsz = sizeof(buf); - ssize_t ret; pos += scnprintf(buf + pos, bufsz - pos, "allow blinking: %s\n", @@ -695,8 +692,7 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, priv->last_blink_time); } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, @@ -709,7 +705,6 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, char buf[100]; int pos = 0; const size_t bufsz = sizeof(buf); - ssize_t ret; pos += scnprintf(buf + pos, bufsz - pos, "Thermal Throttling Mode: %s\n", @@ -729,8 +724,7 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, "HT mode: %d\n", restriction->is_ht); } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file, @@ -767,13 +761,11 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file, char buf[100]; int pos = 0; const size_t bufsz = sizeof(buf); - ssize_t ret; pos += scnprintf(buf + pos, bufsz - pos, "11n 40MHz Mode: %s\n", priv->disable_ht40 ? "Disabled" : "Enabled"); - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, @@ -2049,7 +2041,6 @@ static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, int pos = 0; char buf[128]; const size_t bufsz = sizeof(buf); - ssize_t ret; pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n", priv->event_log.ucode_trace ? "On" : "Off"); @@ -2060,8 +2051,7 @@ static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n", priv->event_log.wraps_more_count); - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, @@ -2147,13 +2137,11 @@ static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file, int pos = 0; char buf[12]; const size_t bufsz = sizeof(buf); - ssize_t ret; pos += scnprintf(buf + pos, bufsz - pos, "%d\n", priv->missed_beacon_threshold); - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, @@ -2211,13 +2199,11 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, int pos = 0; char buf[12]; const size_t bufsz = sizeof(buf); - ssize_t ret; pos += scnprintf(buf + pos, bufsz - pos, "%u\n", priv->cfg->plcp_delta_threshold); - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, -- cgit v1.2.3 From 72e15d71b02a21fd7b94ee1af4ba3a41f722b1f3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 19 Feb 2010 11:42:32 -0800 Subject: iwlwifi: change WEP key protection to use mutex For later station notification support we would like WEP key setting to be done synchronously always. Currently all places from which WEP key is set can sleep, but the usage of sta_lock prevents it to do so. Modify the locking to use priv->mutex instead and thus enable this call to sleep. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 18 +++++++++--------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index bc84fd4a8d29..d6e1a059b9b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2869,7 +2869,6 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, 100); - mutex_unlock(&priv->mutex); /* If we are getting WEP group key and we didn't receive any key mapping * so far, we are in legacy wep mode (group key only), otherwise we are @@ -2905,6 +2904,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ret = -EINVAL; } + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 90d2b6e0df76..bac8e7cc46ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1220,7 +1220,7 @@ struct iwl_priv { spinlock_t sta_lock; int num_stations; struct iwl_station_entry stations[IWL_STATION_COUNT]; - struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; + struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; /* protected by mutex */ u8 default_wep_key; u8 key_mapping_key; unsigned long ucode_key_table; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 4a6686fa6b36..b1aad306efa9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -549,9 +549,11 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) struct iwl_host_cmd cmd = { .id = REPLY_WEPKEY, .data = wep_cmd, - .flags = CMD_ASYNC, + .flags = CMD_SYNC, }; + might_sleep(); + memset(wep_cmd, 0, cmd_size + (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX)); @@ -587,9 +589,9 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf) { int ret; - unsigned long flags; - spin_lock_irqsave(&priv->sta_lock, flags); + WARN_ON(!mutex_is_locked(&priv->mutex)); + IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", keyconf->keyidx); @@ -601,13 +603,12 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); if (iwl_is_rfkill(priv)) { IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); - spin_unlock_irqrestore(&priv->sta_lock, flags); + /* but keys in device are clear anyway so return success */ return 0; } ret = iwl_send_static_wepkey_cmd(priv, 1); IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", keyconf->keyidx, ret); - spin_unlock_irqrestore(&priv->sta_lock, flags); return ret; } @@ -617,7 +618,8 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf) { int ret; - unsigned long flags; + + WARN_ON(!mutex_is_locked(&priv->mutex)); if (keyconf->keylen != WEP_KEY_LEN_128 && keyconf->keylen != WEP_KEY_LEN_64) { @@ -629,12 +631,11 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, keyconf->hw_key_idx = HW_KEY_DEFAULT; priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; - spin_lock_irqsave(&priv->sta_lock, flags); priv->default_wep_key++; if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table)) IWL_ERR(priv, "index %d already used in uCode key table.\n", - keyconf->keyidx); + keyconf->keyidx); priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, @@ -643,7 +644,6 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, ret = iwl_send_static_wepkey_cmd(priv, 0); IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n", keyconf->keylen, keyconf->keyidx, ret); - spin_unlock_irqrestore(&priv->sta_lock, flags); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 2fd1b3d4949a..dd33251d6918 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3344,7 +3344,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, 100); - mutex_unlock(&priv->mutex); switch (cmd) { case SET_KEY: @@ -3365,6 +3364,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ret = -EINVAL; } + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return ret; -- cgit v1.2.3 From f8e200de3af29c36ec93b72e3fc36350f8fbec84 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 19 Feb 2010 11:41:32 -0800 Subject: iwlwifi: remove needlessly exported symbols iwl_apm_stop_master and iwl_internal_short_hw_scan are only used within iwlcore and thus do not need to be exported. Reported-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - drivers/net/wireless/iwlwifi/iwl-scan.c | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index a962fb3cb35c..ec435e5491d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1356,7 +1356,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_irq_handle_error); -int iwl_apm_stop_master(struct iwl_priv *priv) +static int iwl_apm_stop_master(struct iwl_priv *priv) { int ret = 0; @@ -1372,7 +1372,6 @@ int iwl_apm_stop_master(struct iwl_priv *priv) return ret; } -EXPORT_SYMBOL(iwl_apm_stop_master); void iwl_apm_stop(struct iwl_priv *priv) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index bec00c790596..aced12f1611e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -675,7 +675,6 @@ extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv, void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_apm_stop(struct iwl_priv *priv); -int iwl_apm_stop_master(struct iwl_priv *priv); int iwl_apm_init(struct iwl_priv *priv); void iwl_setup_rxon_timing(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index dd9ff2ed645a..ccad04c0a767 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -580,7 +580,6 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv) out: return ret; } -EXPORT_SYMBOL(iwl_internal_short_hw_scan); #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) -- cgit v1.2.3 From 9856b7fa36a77d69e1413c63cb867514876796d2 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 23 Feb 2010 14:05:29 -0800 Subject: iwlwifi: remove duplicate function "internal_scan" debugfs function serves the same propose of mode "0" of "force_reset" debugfs function. Remove it to avoid duplicate. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index d9255b53be10..5f5820249a29 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2170,27 +2170,6 @@ static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, return count; } -static ssize_t iwl_dbgfs_internal_scan_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - char buf[8]; - int buf_size; - int scan; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%d", &scan) != 1) - return -EINVAL; - - iwl_internal_short_hw_scan(priv); - - return count; -} - static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -2304,7 +2283,6 @@ DEBUGFS_WRITE_FILE_OPS(csr); DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); DEBUGFS_READ_FILE_OPS(fh_reg); DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); -DEBUGFS_WRITE_FILE_OPS(internal_scan); DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); DEBUGFS_READ_WRITE_FILE_OPS(force_reset); DEBUGFS_READ_FILE_OPS(rxon_flags); @@ -2360,7 +2338,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); - DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { -- cgit v1.2.3 From 13115ba76b3200fca62d1bfd54f917f208e7d2e5 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 23 Feb 2010 14:36:13 -0800 Subject: iwlwifi: remove unnecessary parameter in scan function small change to remove unnecessary "ret" parameter since it not being used. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-scan.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index ccad04c0a767..1544d751a42e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -675,7 +675,6 @@ static void iwl_bg_request_scan(struct work_struct *data) }; struct iwl_scan_cmd *scan; struct ieee80211_conf *conf = NULL; - int ret = 0; u32 rate_flags = 0; u16 cmd_len; u16 rx_chain = 0; @@ -708,7 +707,6 @@ static void iwl_bg_request_scan(struct work_struct *data) if (test_bit(STATUS_SCAN_HW, &priv->status)) { IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. " "Ignoring second request.\n"); - ret = -EIO; goto done; } @@ -741,7 +739,8 @@ static void iwl_bg_request_scan(struct work_struct *data) priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE, GFP_KERNEL); if (!priv->scan) { - ret = -ENOMEM; + IWL_DEBUG_SCAN(priv, + "fail to allocate memory for scan\n"); goto done; } } @@ -908,8 +907,7 @@ static void iwl_bg_request_scan(struct work_struct *data) scan->len = cpu_to_le16(cmd.len); set_bit(STATUS_SCAN_HW, &priv->status); - ret = iwl_send_cmd_sync(priv, &cmd); - if (ret) + if (iwl_send_cmd_sync(priv, &cmd)) goto done; queue_delayed_work(priv->workqueue, &priv->scan_check, -- cgit v1.2.3 From 4f4d4088b05155d4904e29d5c00316395ce32f27 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 24 Feb 2010 08:28:30 -0800 Subject: iwlwifi: add internal short scan support for 3945 Add internal short scan support for 3945 NIC, This allows 3945 NIC to support radio reset request like the other series of NICs. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index dd33251d6918..252df12eeb38 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2799,7 +2799,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) .len = sizeof(struct iwl3945_scan_cmd), .flags = CMD_SIZE_HUGE, }; - int rc = 0; struct iwl3945_scan_cmd *scan; struct ieee80211_conf *conf = NULL; u8 n_probes = 0; @@ -2827,7 +2826,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) if (test_bit(STATUS_SCAN_HW, &priv->status)) { IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests " "Ignoring second request.\n"); - rc = -EIO; goto done; } @@ -2862,7 +2860,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE, GFP_KERNEL); if (!priv->scan) { - rc = -ENOMEM; + IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n"); goto done; } } @@ -2905,7 +2903,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan_suspend_time, interval); } - if (priv->scan_request->n_ssids) { + if (priv->is_internal_short_scan) { + IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); + } else if (priv->scan_request->n_ssids) { int i, p = 0; IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); for (i = 0; i < priv->scan_request->n_ssids; i++) { @@ -2952,13 +2952,20 @@ static void iwl3945_bg_request_scan(struct work_struct *data) goto done; } - scan->tx_cmd.len = cpu_to_le16( + if (!priv->is_internal_short_scan) { + scan->tx_cmd.len = cpu_to_le16( iwl_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, priv->scan_request->ie, priv->scan_request->ie_len, IWL_MAX_SCAN_SIZE - sizeof(*scan))); - + } else { + scan->tx_cmd.len = cpu_to_le16( + iwl_fill_probe_req(priv, + (struct ieee80211_mgmt *)scan->data, + NULL, 0, + IWL_MAX_SCAN_SIZE - sizeof(*scan))); + } /* select Rx antennas */ scan->flags |= iwl3945_get_antenna_flags(priv); @@ -2980,8 +2987,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan->len = cpu_to_le16(cmd.len); set_bit(STATUS_SCAN_HW, &priv->status); - rc = iwl_send_cmd_sync(priv, &cmd); - if (rc) + if (iwl_send_cmd_sync(priv, &cmd)) goto done; queue_delayed_work(priv->workqueue, &priv->scan_check, -- cgit v1.2.3 From edc1a3a090e83c48d4b33c23aa16c54b3b790ef5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 24 Feb 2010 01:57:19 -0800 Subject: iwlwifi: clean up queue/fifo handling 4965 hardware has 7 queues reserved and the remaining ones used for aggregation, 5000 and higher need to have 10 reserved. This is not very clear in the code right now, unfortunately. Introduce a new IWL_TX_FIFO_UNUSED constant and make the queue/FIFO mapping arrays able to hold that value, and change the setup code to reserve all queues in the arrays (the queue number is the index) and use the new unused constant to not map those queues to any FIFO. Additionally, clear up the AC/queue mapping code to be more understandable. The mapping is the identity mapping right now, but with the mapping function I think it's easier to understand what happens there. Finally, HCCA isn't implemented at all and I think newer microcode removed it, so let's remove all mention of it in the code, some comments remain for 4965. Signed-off-by: Johannes Berg Acked-by: Shanyu Zhao Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-4965.c | 20 +++--- drivers/net/wireless/iwlwifi/iwl-5000.c | 35 ++++++----- drivers/net/wireless/iwlwifi/iwl-dev.h | 12 ++-- drivers/net/wireless/iwlwifi/iwl-prph.h | 14 ++--- drivers/net/wireless/iwlwifi/iwl-tx.c | 105 ++++++++++++++++++++------------ 5 files changed, 109 insertions(+), 77 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 1bd2cd836026..644aacfbd7df 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -502,14 +502,14 @@ static void iwl4965_tx_queue_set_status(struct iwl_priv *priv, scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); } -static const u16 default_queue_to_tx_fifo[] = { - IWL_TX_FIFO_AC3, - IWL_TX_FIFO_AC2, - IWL_TX_FIFO_AC1, - IWL_TX_FIFO_AC0, +static const s8 default_queue_to_tx_fifo[] = { + IWL_TX_FIFO_VO, + IWL_TX_FIFO_VI, + IWL_TX_FIFO_BE, + IWL_TX_FIFO_BK, IWL49_CMD_FIFO_NUM, - IWL_TX_FIFO_HCCA_1, - IWL_TX_FIFO_HCCA_2 + IWL_TX_FIFO_UNUSED, + IWL_TX_FIFO_UNUSED, }; static int iwl4965_alive_notify(struct iwl_priv *priv) @@ -589,9 +589,15 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) /* reset to 0 to enable all the queue first */ priv->txq_ctx_active_msk = 0; /* Map each Tx/cmd queue to its corresponding fifo */ + BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7); for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { int ac = default_queue_to_tx_fifo[i]; + iwl_txq_ctx_activate(priv, i); + + if (ac == IWL_TX_FIFO_UNUSED) + continue; + iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0); } diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 4c0ef013acbf..37e1e77f513d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -64,14 +64,17 @@ #define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" #define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api) -static const u16 iwl5000_default_queue_to_tx_fifo[] = { - IWL_TX_FIFO_AC3, - IWL_TX_FIFO_AC2, - IWL_TX_FIFO_AC1, - IWL_TX_FIFO_AC0, +static const s8 iwl5000_default_queue_to_tx_fifo[] = { + IWL_TX_FIFO_VO, + IWL_TX_FIFO_VI, + IWL_TX_FIFO_BE, + IWL_TX_FIFO_BK, IWL50_CMD_FIFO_NUM, - IWL_TX_FIFO_HCCA_1, - IWL_TX_FIFO_HCCA_2 + IWL_TX_FIFO_UNUSED, + IWL_TX_FIFO_UNUSED, + IWL_TX_FIFO_UNUSED, + IWL_TX_FIFO_UNUSED, + IWL_TX_FIFO_UNUSED, }; /* NIC configuration for 5000 series */ @@ -657,25 +660,21 @@ int iwl5000_alive_notify(struct iwl_priv *priv) /* reset to 0 to enable all the queue first */ priv->txq_ctx_active_msk = 0; /* map qos queues to fifos one-to-one */ + BUILD_BUG_ON(ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo) != 10); + for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) { int ac = iwl5000_default_queue_to_tx_fifo[i]; + iwl_txq_ctx_activate(priv, i); + + if (ac == IWL_TX_FIFO_UNUSED) + continue; + iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0); } - /* - * TODO - need to initialize these queues and map them to FIFOs - * in the loop above, not only mark them as active. We do this - * because we want the first aggregation queue to be queue #10, - * but do not use 8 or 9 otherwise yet. - */ - iwl_txq_ctx_activate(priv, 7); - iwl_txq_ctx_activate(priv, 8); - iwl_txq_ctx_activate(priv, 9); - spin_unlock_irqrestore(&priv->lock, flags); - iwl_send_wimax_coex(priv); iwl5000_set_Xtal_calib(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index bac8e7cc46ce..2e4d47c7139b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -304,13 +304,11 @@ struct iwl_channel_info { struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; }; -#define IWL_TX_FIFO_AC0 0 -#define IWL_TX_FIFO_AC1 1 -#define IWL_TX_FIFO_AC2 2 -#define IWL_TX_FIFO_AC3 3 -#define IWL_TX_FIFO_HCCA_1 5 -#define IWL_TX_FIFO_HCCA_2 6 -#define IWL_TX_FIFO_NONE 7 +#define IWL_TX_FIFO_BK 0 +#define IWL_TX_FIFO_BE 1 +#define IWL_TX_FIFO_VI 2 +#define IWL_TX_FIFO_VO 3 +#define IWL_TX_FIFO_UNUSED -1 /* Minimum number of queues. MAX_NUM is defined in hw specific files. * Set the minimum to accommodate the 4 standard TX queues, 1 command diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index d2d2a9174900..5944de7a98a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -254,7 +254,7 @@ * device. A queue maps to only one (selectable by driver) Tx DMA channel, * but one DMA channel may take input from several queues. * - * Tx DMA channels have dedicated purposes. For 4965, they are used as follows + * Tx DMA FIFOs have dedicated purposes. For 4965, they are used as follows * (cf. default_queue_to_tx_fifo in iwl-4965.c): * * 0 -- EDCA BK (background) frames, lowest priority @@ -262,20 +262,20 @@ * 2 -- EDCA VI (video) frames, higher priority * 3 -- EDCA VO (voice) and management frames, highest priority * 4 -- Commands (e.g. RXON, etc.) - * 5 -- HCCA short frames - * 6 -- HCCA long frames + * 5 -- unused (HCCA) + * 6 -- unused (HCCA) * 7 -- not used by driver (device-internal only) * - * For 5000 series and up, they are used slightly differently + * For 5000 series and up, they are used differently * (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c): * * 0 -- EDCA BK (background) frames, lowest priority * 1 -- EDCA BE (best effort) frames, normal priority * 2 -- EDCA VI (video) frames, higher priority * 3 -- EDCA VO (voice) and management frames, highest priority - * 4 -- (TBD) - * 5 -- HCCA short frames - * 6 -- HCCA long frames + * 4 -- unused + * 5 -- unused + * 6 -- unused * 7 -- Commands * * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6. diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 08b33fcc0792..045e4a67344b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -37,26 +37,63 @@ #include "iwl-io.h" #include "iwl-helpers.h" -static const u16 default_tid_to_tx_fifo[] = { - IWL_TX_FIFO_AC1, - IWL_TX_FIFO_AC0, - IWL_TX_FIFO_AC0, - IWL_TX_FIFO_AC1, - IWL_TX_FIFO_AC2, - IWL_TX_FIFO_AC2, - IWL_TX_FIFO_AC3, - IWL_TX_FIFO_AC3, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_AC3 +/* + * mac80211 queues, ACs, hardware queues, FIFOs. + * + * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues + * + * Mac80211 uses the following numbers, which we get as from it + * by way of skb_get_queue_mapping(skb): + * + * VO 0 + * VI 1 + * BE 2 + * BK 3 + * + * + * Regular (not A-MPDU) frames are put into hardware queues corresponding + * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their + * own queue per aggregation session (RA/TID combination), such queues are + * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In + * order to map frames to the right queue, we also need an AC->hw queue + * mapping. This is implemented here. + * + * Due to the way hw queues are set up (by the hw specific modules like + * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity + * mapping. + */ + +static const u8 tid_to_ac[] = { + /* this matches the mac80211 numbers */ + 2, 3, 3, 2, 1, 1, 0, 0 +}; + +static const u8 ac_to_fifo[] = { + IWL_TX_FIFO_VO, + IWL_TX_FIFO_VI, + IWL_TX_FIFO_BE, + IWL_TX_FIFO_BK, }; +static inline int get_fifo_from_ac(u8 ac) +{ + return ac_to_fifo[ac]; +} + +static inline int get_queue_from_ac(u16 ac) +{ + return ac; +} + +static inline int get_fifo_from_tid(u16 tid) +{ + if (likely(tid < ARRAY_SIZE(tid_to_ac))) + return get_fifo_from_ac(tid_to_ac[tid]); + + /* no support for TIDs 8-15 yet */ + return -EINVAL; +} + static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, struct iwl_dma_ptr *ptr, size_t size) { @@ -591,13 +628,12 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, tx_cmd->next_frame_len = 0; } -#define RTS_HCCA_RETRY_LIMIT 3 #define RTS_DFAULT_RETRY_LIMIT 60 static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, struct iwl_tx_cmd *tx_cmd, struct ieee80211_tx_info *info, - __le16 fc, int is_hcca) + __le16 fc) { u32 rate_flags; int rate_idx; @@ -613,8 +649,7 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, tx_cmd->data_retry_limit = data_retry_limit; /* Set retry limit on RTS packets */ - rts_retry_limit = (is_hcca) ? RTS_HCCA_RETRY_LIMIT : - RTS_DFAULT_RETRY_LIMIT; + rts_retry_limit = RTS_DFAULT_RETRY_LIMIT; if (data_retry_limit < rts_retry_limit) rts_retry_limit = data_retry_limit; tx_cmd->rts_retry_limit = rts_retry_limit; @@ -794,7 +829,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); } - txq_id = skb_get_queue_mapping(skb); + txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); if (ieee80211_is_data_qos(fc)) { qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; @@ -859,8 +894,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id); iwl_dbg_log_tx_data_frame(priv, len, hdr); - /* set is_hcca to 0; it probably will never be implemented */ - iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, 0); + iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc); iwl_update_stats(priv, true, fc, len); /* @@ -1260,7 +1294,7 @@ EXPORT_SYMBOL(iwl_tx_cmd_complete); * Find first available (lowest unused) Tx Queue, mark it "active". * Called only when finding queue for aggregation. * Should never return anything < 7, because they should already - * be in use as EDCA AC (0-3), Command (4), HCCA (5, 6). + * be in use as EDCA AC (0-3), Command (4), reserved (5, 6) */ static int iwl_txq_ctx_activate_free(struct iwl_priv *priv) { @@ -1281,10 +1315,9 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) unsigned long flags; struct iwl_tid_data *tid_data; - if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) - tx_fifo = default_tid_to_tx_fifo[tid]; - else - return -EINVAL; + tx_fifo = get_fifo_from_tid(tid); + if (unlikely(tx_fifo < 0)) + return tx_fifo; IWL_WARN(priv, "%s on ra = %pM tid = %d\n", __func__, ra, tid); @@ -1345,13 +1378,9 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) return -EINVAL; } - if (unlikely(tid >= MAX_TID_COUNT)) - return -EINVAL; - - if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) - tx_fifo_id = default_tid_to_tx_fifo[tid]; - else - return -EINVAL; + tx_fifo_id = get_fifo_from_tid(tid); + if (unlikely(tx_fifo_id < 0)) + return tx_fifo_id; sta_id = iwl_find_station(priv, ra); @@ -1419,7 +1448,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) if ((txq_id == tid_data->agg.txq_id) && (q->read_ptr == q->write_ptr)) { u16 ssn = SEQ_TO_SN(tid_data->seq_number); - int tx_fifo = default_tid_to_tx_fifo[tid]; + int tx_fifo = get_fifo_from_tid(tid); IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, tx_fifo); -- cgit v1.2.3 From 75a9a92625a7d7401d04209f4226061cd2674b59 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 26 Feb 2010 15:17:01 -0800 Subject: iwl3945: check ucode load error code Check successful completion of BSM loading. Give a chance to load BSM again. If BSM loading is unsuccessful we should exit and not initilize NIC. Before this checking even if the BSM loading failed driver tries to initilize the NIC which should not be the case. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 252df12eeb38..2579bbcaab36 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2697,7 +2697,7 @@ static int __iwl3945_up(struct iwl_priv *priv) /* load bootstrap state machine, * load bootstrap program into processor's memory, * prepare to load the "initialize" uCode */ - priv->cfg->ops->lib->load_ucode(priv); + rc = priv->cfg->ops->lib->load_ucode(priv); if (rc) { IWL_ERR(priv, -- cgit v1.2.3 From 7d49c6111c27f0e68b0310aeececf7ded53f7f94 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 25 Feb 2010 14:15:25 +0800 Subject: iwmc3200wifi: refuse to associate on unallowed channels We need to make sure we don't associate with APs on unallowed channels (according to regulatory setting). This could happen when the channel is not specified (auto-select) within the connection request. In this case we get the AP's channel until the firmware indicates the association succeeded later. We need to verify the associated channel. If the channel is disabled by regulatory, we have to disassociate with the AP. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/commands.c | 12 +++++++++--- drivers/net/wireless/iwmc3200wifi/commands.h | 1 + drivers/net/wireless/iwmc3200wifi/rx.c | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 1e41ad0fcad5..9ef4fd045041 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -781,10 +781,9 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm) return 0; } -int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) +int __iwm_invalidate_mlme_profile(struct iwm_priv *iwm) { struct iwm_umac_invalidate_profile invalid; - int ret; invalid.hdr.oid = UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE; invalid.hdr.buf_size = @@ -793,7 +792,14 @@ int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) invalid.reason = WLAN_REASON_UNSPECIFIED; - ret = iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1); + return iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1); +} + +int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) +{ + int ret; + + ret = __iwm_invalidate_mlme_profile(iwm); if (ret) return ret; diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h index 3dfd9f0e9003..7e16bcf59978 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.h +++ b/drivers/net/wireless/iwmc3200wifi/commands.h @@ -488,6 +488,7 @@ int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key, void *payload, u16 payload_size); int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags); int iwm_send_mlme_profile(struct iwm_priv *iwm); +int __iwm_invalidate_mlme_profile(struct iwm_priv *iwm); int iwm_invalidate_mlme_profile(struct iwm_priv *iwm); int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id); int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx); diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index ad8f7eabb5aa..36b1580329cc 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -518,6 +518,8 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size, struct iwm_wifi_cmd *cmd) { + struct wiphy *wiphy = iwm_to_wiphy(iwm); + struct ieee80211_channel *chan; struct iwm_umac_notif_assoc_complete *complete = (struct iwm_umac_notif_assoc_complete *)buf; @@ -526,6 +528,18 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, switch (le32_to_cpu(complete->status)) { case UMAC_ASSOC_COMPLETE_SUCCESS: + chan = ieee80211_get_channel(wiphy, + ieee80211_channel_to_frequency(complete->channel)); + if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) { + /* Associated to a unallowed channel, disassociate. */ + __iwm_invalidate_mlme_profile(iwm); + IWM_WARN(iwm, "Couldn't associate with %pM due to " + "channel %d is disabled. Check your local " + "regulatory setting.\n", + complete->bssid, complete->channel); + goto failure; + } + set_bit(IWM_STATUS_ASSOCIATED, &iwm->status); memcpy(iwm->bssid, complete->bssid, ETH_ALEN); iwm->channel = complete->channel; @@ -562,6 +576,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, GFP_KERNEL); break; case UMAC_ASSOC_COMPLETE_FAILURE: + failure: clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); memset(iwm->bssid, 0, ETH_ALEN); iwm->channel = 0; -- cgit v1.2.3 From 04d1c22761f33ac8f345665e7ef809c875142425 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 25 Feb 2010 14:15:26 +0800 Subject: iwmc3200wifi: remove "_safe" for some list_for_each_entry usage Use list_for_each_entry instead of list_for_each_entry_safe in places iteration against list entry removal is not required. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 4 ++-- drivers/net/wireless/iwmc3200wifi/debugfs.c | 9 +++++---- drivers/net/wireless/iwmc3200wifi/hal.c | 12 ++++++------ drivers/net/wireless/iwmc3200wifi/main.c | 4 ++-- drivers/net/wireless/iwmc3200wifi/rx.c | 15 ++++++--------- 5 files changed, 21 insertions(+), 23 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 7c4f44a9c3e6..6778e5838fe6 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -263,7 +263,7 @@ static int iwm_cfg80211_get_station(struct wiphy *wiphy, int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) { struct wiphy *wiphy = iwm_to_wiphy(iwm); - struct iwm_bss_info *bss, *next; + struct iwm_bss_info *bss; struct iwm_umac_notif_bss_info *umac_bss; struct ieee80211_mgmt *mgmt; struct ieee80211_channel *channel; @@ -271,7 +271,7 @@ int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) s32 signal; int freq; - list_for_each_entry_safe(bss, next, &iwm->bss_list, node) { + list_for_each_entry(bss, &iwm->bss_list, node) { umac_bss = bss->bss; mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf); diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c index be992ca41cf1..6ac5c8dbe051 100644 --- a/drivers/net/wireless/iwmc3200wifi/debugfs.c +++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c @@ -265,7 +265,7 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, size_t count, loff_t *ppos) { struct iwm_priv *iwm = filp->private_data; - struct iwm_rx_ticket_node *ticket, *next; + struct iwm_rx_ticket_node *ticket; char *buf; int buf_len = 4096, i; size_t len = 0; @@ -280,7 +280,7 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, if (!buf) return -ENOMEM; - list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) { + list_for_each_entry(ticket, &iwm->rx_tickets, node) { len += snprintf(buf + len, buf_len - len, "Ticket #%d\n", ticket->ticket->id); len += snprintf(buf + len, buf_len - len, "\taction: 0x%x\n", @@ -290,12 +290,13 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, } for (i = 0; i < IWM_RX_ID_HASH; i++) { - struct iwm_rx_packet *packet, *nxt; + struct iwm_rx_packet *packet; struct list_head *pkt_list = &iwm->rx_packets[i]; + if (!list_empty(pkt_list)) { len += snprintf(buf + len, buf_len - len, "Packet hash #%d\n", i); - list_for_each_entry_safe(packet, nxt, pkt_list, node) { + list_for_each_entry(packet, pkt_list, node) { len += snprintf(buf + len, buf_len - len, "\tPacket id: %d\n", packet->id); diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c index d13c8853ee82..96caab4bbe58 100644 --- a/drivers/net/wireless/iwmc3200wifi/hal.c +++ b/drivers/net/wireless/iwmc3200wifi/hal.c @@ -206,9 +206,9 @@ void iwm_cmd_flush(struct iwm_priv *iwm) struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num) { - struct iwm_wifi_cmd *cmd, *next; + struct iwm_wifi_cmd *cmd; - list_for_each_entry_safe(cmd, next, &iwm->wifi_pending_cmd, pending) + list_for_each_entry(cmd, &iwm->wifi_pending_cmd, pending) if (cmd->seq_num == seq_num) { list_del(&cmd->pending); return cmd; @@ -217,12 +217,12 @@ struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num) return NULL; } -struct iwm_nonwifi_cmd * -iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm, u8 seq_num, u8 cmd_opcode) +struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm, + u8 seq_num, u8 cmd_opcode) { - struct iwm_nonwifi_cmd *cmd, *next; + struct iwm_nonwifi_cmd *cmd; - list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending) + list_for_each_entry(cmd, &iwm->nonwifi_pending_cmd, pending) if ((cmd->seq_num == seq_num) && (cmd->udma_cmd.opcode == cmd_opcode) && (cmd->resp_received)) { diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 7f34d6dd3c41..90519600a947 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -423,9 +423,9 @@ int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd, static struct iwm_notif *iwm_notif_find(struct iwm_priv *iwm, u32 cmd, u8 source) { - struct iwm_notif *notif, *next; + struct iwm_notif *notif; - list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) { + list_for_each_entry(notif, &iwm->pending_notif, pending) { if ((notif->cmd_id == cmd) && (notif->src == source)) { list_del(¬if->pending); return notif; diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 36b1580329cc..cbaf8ae3aa37 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -342,12 +342,9 @@ static void iwm_rx_ticket_node_free(struct iwm_rx_ticket_node *ticket_node) static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id) { u8 id_hash = IWM_RX_ID_GET_HASH(id); - struct list_head *packet_list; - struct iwm_rx_packet *packet, *next; - - packet_list = &iwm->rx_packets[id_hash]; + struct iwm_rx_packet *packet; - list_for_each_entry_safe(packet, next, packet_list, node) + list_for_each_entry(packet, &iwm->rx_packets[id_hash], node) if (packet->id == id) return packet; @@ -771,7 +768,7 @@ static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf, (struct iwm_umac_notif_bss_info *)buf; struct ieee80211_channel *channel; struct ieee80211_supported_band *band; - struct iwm_bss_info *bss, *next; + struct iwm_bss_info *bss; s32 signal; int freq; u16 frame_len = le16_to_cpu(umac_bss->frame_len); @@ -790,7 +787,7 @@ static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf, IWM_DBG_MLME(iwm, DBG, "\tRSSI: %d\n", umac_bss->rssi); IWM_DBG_MLME(iwm, DBG, "\tFrame Length: %d\n", frame_len); - list_for_each_entry_safe(bss, next, &iwm->bss_list, node) + list_for_each_entry(bss, &iwm->bss_list, node) if (bss->bss->table_idx == umac_bss->table_idx) break; @@ -1331,7 +1328,7 @@ static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf, { u8 seq_num; struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf; - struct iwm_nonwifi_cmd *cmd, *next; + struct iwm_nonwifi_cmd *cmd; seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM); @@ -1343,7 +1340,7 @@ static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf, * That means we only support synchronised non wifi command response * schemes. */ - list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending) + list_for_each_entry(cmd, &iwm->nonwifi_pending_cmd, pending) if (cmd->seq_num == seq_num) { cmd->resp_received = 1; cmd->buf.len = buf_size; -- cgit v1.2.3 From 34dd5feb8b8b15654714731e1dbb34a6d37fb34e Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 25 Feb 2010 14:15:27 +0800 Subject: iwmc3200wifi: add ftrace event tracing support Add event tracer for iwmc3200wifi driver. When enabled, all the commands and responses between the driver and firmware (also including Tx/Rx frames) will be recorded in the ftrace ring buffer. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/Kconfig | 9 +- drivers/net/wireless/iwmc3200wifi/Makefile | 3 + drivers/net/wireless/iwmc3200wifi/hal.c | 3 + drivers/net/wireless/iwmc3200wifi/hal.h | 3 +- drivers/net/wireless/iwmc3200wifi/iwm.h | 1 + drivers/net/wireless/iwmc3200wifi/rx.c | 15 +- drivers/net/wireless/iwmc3200wifi/trace.c | 3 + drivers/net/wireless/iwmc3200wifi/trace.h | 283 +++++++++++++++++++++++++++++ drivers/net/wireless/iwmc3200wifi/tx.c | 1 + 9 files changed, 314 insertions(+), 7 deletions(-) create mode 100644 drivers/net/wireless/iwmc3200wifi/trace.c create mode 100644 drivers/net/wireless/iwmc3200wifi/trace.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig index b9d34a766964..03f998d098c5 100644 --- a/drivers/net/wireless/iwmc3200wifi/Kconfig +++ b/drivers/net/wireless/iwmc3200wifi/Kconfig @@ -17,7 +17,7 @@ config IWM config IWM_DEBUG bool "Enable full debugging output in iwmc3200wifi" depends on IWM && DEBUG_FS - ---help--- + help This option will enable debug tracing and setting for iwm You can set the debug level and module through debugfs. By @@ -30,3 +30,10 @@ config IWM_DEBUG Or, if you want the full debug, for all modules: echo 0xff > /sys/kernel/debug/iwm/phyN/debug/level echo 0xff > /sys/kernel/debug/iwm/phyN/debug/modules + +config IWM_TRACING + bool "Enable event tracing for iwmc3200wifi" + depends on IWM && EVENT_TRACING + help + Say Y here to trace all the commands and responses between + the driver and firmware (including TX/RX frames) with ftrace. diff --git a/drivers/net/wireless/iwmc3200wifi/Makefile b/drivers/net/wireless/iwmc3200wifi/Makefile index d34291b652d3..aeed5cd80819 100644 --- a/drivers/net/wireless/iwmc3200wifi/Makefile +++ b/drivers/net/wireless/iwmc3200wifi/Makefile @@ -3,3 +3,6 @@ iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o iwmc3200wifi-objs += commands.o cfg80211.o eeprom.o iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o +iwmc3200wifi-$(CONFIG_IWM_TRACING) += trace.o + +CFLAGS_trace.o := -I$(src) diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c index 96caab4bbe58..373b5b5001d2 100644 --- a/drivers/net/wireless/iwmc3200wifi/hal.c +++ b/drivers/net/wireless/iwmc3200wifi/hal.c @@ -104,6 +104,7 @@ #include "hal.h" #include "umac.h" #include "debug.h" +#include "trace.h" static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm, struct iwm_nonwifi_cmd *cmd, @@ -276,6 +277,7 @@ static int iwm_send_udma_nonwifi_cmd(struct iwm_priv *iwm, udma_cmd->handle_by_hw, cmd->seq_num, udma_cmd->addr, udma_cmd->op1_sz, udma_cmd->op2); + trace_iwm_tx_nonwifi_cmd(iwm, udma_hdr); return iwm_bus_send_chunk(iwm, buf->start, buf->len); } @@ -362,6 +364,7 @@ static int iwm_send_udma_wifi_cmd(struct iwm_priv *iwm, return ret; } + trace_iwm_tx_wifi_cmd(iwm, umac_hdr); return iwm_bus_send_chunk(iwm, buf->start, buf->len); } diff --git a/drivers/net/wireless/iwmc3200wifi/hal.h b/drivers/net/wireless/iwmc3200wifi/hal.h index 0adfdc85765d..e7bc41670b25 100644 --- a/drivers/net/wireless/iwmc3200wifi/hal.h +++ b/drivers/net/wireless/iwmc3200wifi/hal.h @@ -75,7 +75,8 @@ do { \ /* UDMA IN OP CODE -- cmd bits [3:0] */ -#define UDMA_IN_OPCODE_MASK 0xF +#define UDMA_HDI_IN_NW_CMD_OPCODE_POS 0 +#define UDMA_HDI_IN_NW_CMD_OPCODE_SEED 0xF #define UDMA_IN_OPCODE_GENERAL_RESP 0x0 #define UDMA_IN_OPCODE_READ_RESP 0x1 diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 79ffa3b98d73..9ad5b3c22eb2 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -48,6 +48,7 @@ #include "umac.h" #include "lmac.h" #include "eeprom.h" +#include "trace.h" #define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation" #define IWM_AUTHOR "" diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index cbaf8ae3aa37..38d950b0f24b 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -1235,18 +1235,24 @@ static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf, u8 source, cmd_id; u16 seq_num; u32 count; - u8 resp; wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; cmd_id = wifi_hdr->sw_hdr.cmd.cmd; - source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); if (source >= IWM_SRC_NUM) { IWM_CRIT(iwm, "invalid source %d\n", source); return -EINVAL; } - count = (GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT)); + if (cmd_id == REPLY_RX_MPDU_CMD) + trace_iwm_rx_packet(iwm, buf, buf_size); + else if ((cmd_id == UMAC_NOTIFY_OPCODE_RX_TICKET) && + (source == UMAC_HDI_IN_SOURCE_FW)) + trace_iwm_rx_ticket(iwm, buf, buf_size); + else + trace_iwm_rx_wifi_cmd(iwm, wifi_hdr); + + count = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT); count += sizeof(struct iwm_umac_wifi_in_hdr) - sizeof(struct iwm_dev_cmd_hdr); if (count > buf_size) { @@ -1254,8 +1260,6 @@ static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf, return -EINVAL; } - resp = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_STATUS); - seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num); IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n", @@ -1330,6 +1334,7 @@ static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf, struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf; struct iwm_nonwifi_cmd *cmd; + trace_iwm_rx_nonwifi_cmd(iwm, buf, buf_size); seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM); /* diff --git a/drivers/net/wireless/iwmc3200wifi/trace.c b/drivers/net/wireless/iwmc3200wifi/trace.c new file mode 100644 index 000000000000..904d36f22311 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/trace.c @@ -0,0 +1,3 @@ +#include "iwm.h" +#define CREATE_TRACE_POINTS +#include "trace.h" diff --git a/drivers/net/wireless/iwmc3200wifi/trace.h b/drivers/net/wireless/iwmc3200wifi/trace.h new file mode 100644 index 000000000000..320e54fbb38c --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/trace.h @@ -0,0 +1,283 @@ +#if !defined(__IWM_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ) +#define __IWM_TRACE_H__ + +#include + +#if !defined(CONFIG_IWM_TRACING) +#undef TRACE_EVENT +#define TRACE_EVENT(name, proto, ...) \ +static inline void trace_ ## name(proto) {} +#endif + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM iwm + +#define IWM_ENTRY __array(char, ndev_name, 16) +#define IWM_ASSIGN strlcpy(__entry->ndev_name, iwm_to_ndev(iwm)->name, 16) +#define IWM_PR_FMT "%s" +#define IWM_PR_ARG __entry->ndev_name + +TRACE_EVENT(iwm_tx_nonwifi_cmd, + TP_PROTO(struct iwm_priv *iwm, struct iwm_udma_out_nonwifi_hdr *hdr), + + TP_ARGS(iwm, hdr), + + TP_STRUCT__entry( + IWM_ENTRY + __field(u8, opcode) + __field(u8, resp) + __field(u8, eot) + __field(u8, hw) + __field(u16, seq) + __field(u32, addr) + __field(u32, op1) + __field(u32, op2) + ), + + TP_fast_assign( + IWM_ASSIGN; + __entry->opcode = GET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE); + __entry->resp = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_RESP); + __entry->eot = GET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT); + __entry->hw = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW); + __entry->seq = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM); + __entry->addr = le32_to_cpu(hdr->addr); + __entry->op1 = le32_to_cpu(hdr->op1_sz); + __entry->op2 = le32_to_cpu(hdr->op2); + ), + + TP_printk( + IWM_PR_FMT " Tx TARGET CMD: opcode 0x%x, resp %d, eot %d, " + "hw %d, seq 0x%x, addr 0x%x, op1 0x%x, op2 0x%x", + IWM_PR_ARG, __entry->opcode, __entry->resp, __entry->eot, + __entry->hw, __entry->seq, __entry->addr, __entry->op1, + __entry->op2 + ) +); + +TRACE_EVENT(iwm_tx_wifi_cmd, + TP_PROTO(struct iwm_priv *iwm, struct iwm_umac_wifi_out_hdr *hdr), + + TP_ARGS(iwm, hdr), + + TP_STRUCT__entry( + IWM_ENTRY + __field(u8, opcode) + __field(u8, lmac) + __field(u8, resp) + __field(u8, eot) + __field(u8, ra_tid) + __field(u8, credit_group) + __field(u8, color) + __field(u16, seq) + ), + + TP_fast_assign( + IWM_ASSIGN; + __entry->opcode = hdr->sw_hdr.cmd.cmd; + __entry->lmac = 0; + __entry->seq = hdr->sw_hdr.cmd.seq_num; + __entry->resp = GET_VAL8(hdr->sw_hdr.cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ); + __entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR); + __entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT); + __entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID); + __entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP); + if (__entry->opcode == UMAC_CMD_OPCODE_WIFI_PASS_THROUGH || + __entry->opcode == UMAC_CMD_OPCODE_WIFI_IF_WRAPPER) { + __entry->lmac = 1; + __entry->opcode = ((struct iwm_lmac_hdr *)(hdr + 1))->id; + } + ), + + TP_printk( + IWM_PR_FMT " Tx %cMAC CMD: opcode 0x%x, resp %d, eot %d, " + "seq 0x%x, sta_color 0x%x, ra_tid 0x%x, credit_group 0x%x", + IWM_PR_ARG, __entry->lmac ? 'L' : 'U', __entry->opcode, + __entry->resp, __entry->eot, __entry->seq, __entry->color, + __entry->ra_tid, __entry->credit_group + ) +); + +TRACE_EVENT(iwm_tx_packets, + TP_PROTO(struct iwm_priv *iwm, u8 *buf, int len), + + TP_ARGS(iwm, buf, len), + + TP_STRUCT__entry( + IWM_ENTRY + __field(u8, eot) + __field(u8, ra_tid) + __field(u8, credit_group) + __field(u8, color) + __field(u16, seq) + __field(u8, npkt) + __field(u32, bytes) + ), + + TP_fast_assign( + struct iwm_umac_wifi_out_hdr *hdr = + (struct iwm_umac_wifi_out_hdr *)buf; + + IWM_ASSIGN; + __entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT); + __entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID); + __entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP); + __entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR); + __entry->seq = hdr->sw_hdr.cmd.seq_num; + __entry->npkt = 1; + __entry->bytes = len; + + if (!__entry->eot) { + int count; + u8 *ptr = buf; + + __entry->npkt = 0; + while (ptr < buf + len) { + count = GET_VAL32(hdr->sw_hdr.meta_data, + UMAC_FW_CMD_BYTE_COUNT); + ptr += ALIGN(sizeof(*hdr) + count, 16); + hdr = (struct iwm_umac_wifi_out_hdr *)ptr; + __entry->npkt++; + } + } + ), + + TP_printk( + IWM_PR_FMT " Tx %spacket: eot %d, seq 0x%x, sta_color 0x%x, " + "ra_tid 0x%x, credit_group 0x%x, embeded_packets %d, %d bytes", + IWM_PR_ARG, !__entry->eot ? "concatenated " : "", + __entry->eot, __entry->seq, __entry->color, __entry->ra_tid, + __entry->credit_group, __entry->npkt, __entry->bytes + ) +); + +TRACE_EVENT(iwm_rx_nonwifi_cmd, + TP_PROTO(struct iwm_priv *iwm, void *buf, int len), + + TP_ARGS(iwm, buf, len), + + TP_STRUCT__entry( + IWM_ENTRY + __field(u8, opcode) + __field(u16, seq) + __field(u32, len) + ), + + TP_fast_assign( + struct iwm_udma_in_hdr *hdr = buf; + + IWM_ASSIGN; + __entry->opcode = GET_VAL32(hdr->cmd, UDMA_HDI_IN_NW_CMD_OPCODE); + __entry->seq = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM); + __entry->len = len; + ), + + TP_printk( + IWM_PR_FMT " Rx TARGET RESP: opcode 0x%x, seq 0x%x, len 0x%x", + IWM_PR_ARG, __entry->opcode, __entry->seq, __entry->len + ) +); + +TRACE_EVENT(iwm_rx_wifi_cmd, + TP_PROTO(struct iwm_priv *iwm, struct iwm_umac_wifi_in_hdr *hdr), + + TP_ARGS(iwm, hdr), + + TP_STRUCT__entry( + IWM_ENTRY + __field(u8, cmd) + __field(u8, source) + __field(u16, seq) + __field(u32, count) + ), + + TP_fast_assign( + IWM_ASSIGN; + __entry->cmd = hdr->sw_hdr.cmd.cmd; + __entry->source = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); + __entry->count = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT); + __entry->seq = le16_to_cpu(hdr->sw_hdr.cmd.seq_num); + ), + + TP_printk( + IWM_PR_FMT " Rx %s RESP: cmd 0x%x, seq 0x%x, count 0x%x", + IWM_PR_ARG, __entry->source == UMAC_HDI_IN_SOURCE_FHRX ? "LMAC" : + __entry->source == UMAC_HDI_IN_SOURCE_FW ? "UMAC" : "UDMA", + __entry->cmd, __entry->seq, __entry->count + ) +); + +#define iwm_ticket_action_symbol \ + { IWM_RX_TICKET_DROP, "DROP" }, \ + { IWM_RX_TICKET_RELEASE, "RELEASE" }, \ + { IWM_RX_TICKET_SNIFFER, "SNIFFER" }, \ + { IWM_RX_TICKET_ENQUEUE, "ENQUEUE" } + +TRACE_EVENT(iwm_rx_ticket, + TP_PROTO(struct iwm_priv *iwm, void *buf, int len), + + TP_ARGS(iwm, buf, len), + + TP_STRUCT__entry( + IWM_ENTRY + __field(u8, action) + __field(u8, reason) + __field(u16, id) + __field(u16, flags) + ), + + TP_fast_assign( + struct iwm_rx_ticket *ticket = + ((struct iwm_umac_notif_rx_ticket *)buf)->tickets; + + IWM_ASSIGN; + __entry->id = le16_to_cpu(ticket->id); + __entry->action = le16_to_cpu(ticket->action); + __entry->flags = le16_to_cpu(ticket->flags); + __entry->reason = (__entry->flags & IWM_RX_TICKET_DROP_REASON_MSK) >> IWM_RX_TICKET_DROP_REASON_POS; + ), + + TP_printk( + IWM_PR_FMT " Rx ticket: id 0x%x, action %s, %s 0x%x%s", + IWM_PR_ARG, __entry->id, + __print_symbolic(__entry->action, iwm_ticket_action_symbol), + __entry->reason ? "reason" : "flags", + __entry->reason ? __entry->reason : __entry->flags, + __entry->flags & IWM_RX_TICKET_AMSDU_MSK ? ", AMSDU frame" : "" + ) +); + +TRACE_EVENT(iwm_rx_packet, + TP_PROTO(struct iwm_priv *iwm, void *buf, int len), + + TP_ARGS(iwm, buf, len), + + TP_STRUCT__entry( + IWM_ENTRY + __field(u8, source) + __field(u16, id) + __field(u32, len) + ), + + TP_fast_assign( + struct iwm_umac_wifi_in_hdr *hdr = buf; + + IWM_ASSIGN; + __entry->source = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); + __entry->id = le16_to_cpu(hdr->sw_hdr.cmd.seq_num); + __entry->len = len - sizeof(*hdr); + ), + + TP_printk( + IWM_PR_FMT " Rx %s packet: id 0x%x, %d bytes", + IWM_PR_ARG, __entry->source == UMAC_HDI_IN_SOURCE_FHRX ? + "LMAC" : "UMAC", __entry->id, __entry->len + ) +); +#endif + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace +#include diff --git a/drivers/net/wireless/iwmc3200wifi/tx.c b/drivers/net/wireless/iwmc3200wifi/tx.c index 55905f02309c..406615c2c580 100644 --- a/drivers/net/wireless/iwmc3200wifi/tx.c +++ b/drivers/net/wireless/iwmc3200wifi/tx.c @@ -346,6 +346,7 @@ static int iwm_tx_send_concat_packets(struct iwm_priv *iwm, /* mark EOP for the last packet */ iwm_udma_wifi_hdr_set_eop(iwm, txq->concat_ptr, 1); + trace_iwm_tx_packets(iwm, txq->concat_buf, txq->concat_count); ret = iwm_bus_send_chunk(iwm, txq->concat_buf, txq->concat_count); txq->concat_count = 0; -- cgit v1.2.3 From c03c6aefdc2c1f5785a5b0d1a3f7e48eeaae3505 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 25 Feb 2010 14:15:28 +0800 Subject: iwmc3200wifi: protect rx_tickets and rx_packets[] lists Protect rx_tickets and rx_packets[] lists with spinlocks to fix the race condition for concurrent list operations. In iwmc3200wifi both sdio_isr_worker and rx_worker workqueues can access the rx ticket and packets lists at the same time under high rx load. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/debugfs.c | 4 ++++ drivers/net/wireless/iwmc3200wifi/iwm.h | 2 ++ drivers/net/wireless/iwmc3200wifi/main.c | 5 ++++- drivers/net/wireless/iwmc3200wifi/rx.c | 24 ++++++++++++++++++++---- 4 files changed, 30 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c index 6ac5c8dbe051..48930c1a0f76 100644 --- a/drivers/net/wireless/iwmc3200wifi/debugfs.c +++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c @@ -280,6 +280,7 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, if (!buf) return -ENOMEM; + spin_lock(&iwm->ticket_lock); list_for_each_entry(ticket, &iwm->rx_tickets, node) { len += snprintf(buf + len, buf_len - len, "Ticket #%d\n", ticket->ticket->id); @@ -288,6 +289,7 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, len += snprintf(buf + len, buf_len - len, "\tflags: 0x%x\n", ticket->ticket->flags); } + spin_unlock(&iwm->ticket_lock); for (i = 0; i < IWM_RX_ID_HASH; i++) { struct iwm_rx_packet *packet; @@ -296,6 +298,7 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, if (!list_empty(pkt_list)) { len += snprintf(buf + len, buf_len - len, "Packet hash #%d\n", i); + spin_lock(&iwm->packet_lock[i]); list_for_each_entry(packet, pkt_list, node) { len += snprintf(buf + len, buf_len - len, "\tPacket id: %d\n", @@ -304,6 +307,7 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, "\tPacket length: %lu\n", packet->pkt_size); } + spin_unlock(&iwm->packet_lock[i]); } } diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 9ad5b3c22eb2..13266c3842f8 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -269,7 +269,9 @@ struct iwm_priv { struct sk_buff_head rx_list; struct list_head rx_tickets; + spinlock_t ticket_lock; struct list_head rx_packets[IWM_RX_ID_HASH]; + spinlock_t packet_lock[IWM_RX_ID_HASH]; struct workqueue_struct *rx_wq; struct work_struct rx_worker; diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 90519600a947..3a3510a6223a 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -276,8 +276,11 @@ int iwm_priv_init(struct iwm_priv *iwm) skb_queue_head_init(&iwm->rx_list); INIT_LIST_HEAD(&iwm->rx_tickets); - for (i = 0; i < IWM_RX_ID_HASH; i++) + spin_lock_init(&iwm->ticket_lock); + for (i = 0; i < IWM_RX_ID_HASH; i++) { INIT_LIST_HEAD(&iwm->rx_packets[i]); + spin_lock_init(&iwm->packet_lock[i]); + } INIT_WORK(&iwm->rx_worker, iwm_rx_worker); diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 38d950b0f24b..c8a31be16885 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -344,10 +344,15 @@ static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id) u8 id_hash = IWM_RX_ID_GET_HASH(id); struct iwm_rx_packet *packet; + spin_lock(&iwm->packet_lock[id_hash]); list_for_each_entry(packet, &iwm->rx_packets[id_hash], node) - if (packet->id == id) + if (packet->id == id) { + list_del(&packet->node); + spin_unlock(&iwm->packet_lock[id_hash]); return packet; + } + spin_unlock(&iwm->packet_lock[id_hash]); return NULL; } @@ -385,18 +390,22 @@ void iwm_rx_free(struct iwm_priv *iwm) struct iwm_rx_packet *packet, *np; int i; + spin_lock(&iwm->ticket_lock); list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) { list_del(&ticket->node); iwm_rx_ticket_node_free(ticket); } + spin_unlock(&iwm->ticket_lock); for (i = 0; i < IWM_RX_ID_HASH; i++) { + spin_lock(&iwm->packet_lock[i]); list_for_each_entry_safe(packet, np, &iwm->rx_packets[i], node) { list_del(&packet->node); kfree_skb(packet->skb); kfree(packet); } + spin_unlock(&iwm->packet_lock[i]); } } @@ -424,7 +433,9 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf, ticket->action == IWM_RX_TICKET_RELEASE ? "RELEASE" : "DROP", ticket->id); + spin_lock(&iwm->ticket_lock); list_add_tail(&ticket_node->node, &iwm->rx_tickets); + spin_unlock(&iwm->ticket_lock); /* * We received an Rx ticket, most likely there's @@ -457,6 +468,7 @@ static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf, struct iwm_rx_packet *packet; u16 id, buf_offset; u32 packet_size; + u8 id_hash; IWM_DBG_RX(iwm, DBG, "\n"); @@ -474,7 +486,10 @@ static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf, if (IS_ERR(packet)) return PTR_ERR(packet); - list_add_tail(&packet->node, &iwm->rx_packets[IWM_RX_ID_GET_HASH(id)]); + id_hash = IWM_RX_ID_GET_HASH(id); + spin_lock(&iwm->packet_lock[id_hash]); + list_add_tail(&packet->node, &iwm->rx_packets[id_hash]); + spin_unlock(&iwm->packet_lock[id_hash]); /* We might (unlikely) have received the packet _after_ the ticket */ queue_work(iwm->rx_wq, &iwm->rx_worker); @@ -1664,6 +1679,7 @@ void iwm_rx_worker(struct work_struct *work) * We stop whenever a ticket is missing its packet, as we're * supposed to send the packets in order. */ + spin_lock(&iwm->ticket_lock); list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) { struct iwm_rx_packet *packet = iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id)); @@ -1672,12 +1688,12 @@ void iwm_rx_worker(struct work_struct *work) IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d " "to be handled first\n", le16_to_cpu(ticket->ticket->id)); - return; + break; } list_del(&ticket->node); - list_del(&packet->node); iwm_rx_process_packet(iwm, packet, ticket); } + spin_unlock(&iwm->ticket_lock); } -- cgit v1.2.3 From 880f8bdd396ef0548d5967db55e45ce2135fbb2b Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 25 Feb 2010 14:15:29 +0800 Subject: iwmc3200wifi: increase concatenated buffer Increase concatenated buffer from 8K to 32K to get better performance. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/hal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwmc3200wifi/hal.h b/drivers/net/wireless/iwmc3200wifi/hal.h index e7bc41670b25..c20936d9b6b7 100644 --- a/drivers/net/wireless/iwmc3200wifi/hal.h +++ b/drivers/net/wireless/iwmc3200wifi/hal.h @@ -131,7 +131,7 @@ do { \ #define IWM_MAX_WIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \ IWM_MAX_WIFI_HEADERS_SIZE) -#define IWM_HAL_CONCATENATE_BUF_SIZE 8192 +#define IWM_HAL_CONCATENATE_BUF_SIZE (32 * 1024) struct iwm_wifi_cmd_buff { u16 len; -- cgit v1.2.3 From d281fd461dcb9b3d0dc46180bf6e90da3913079d Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 25 Feb 2010 14:15:30 +0800 Subject: iwmc3200wifi: mark some pmksa functions static This fixes the sparse warnings. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 6778e5838fe6..fc239a32cb6b 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -725,23 +725,26 @@ static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy, CFG_POWER_INDEX, iwm->conf.power_index); } -int iwm_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, - struct cfg80211_pmksa *pmksa) +static int iwm_cfg80211_set_pmksa(struct wiphy *wiphy, + struct net_device *netdev, + struct cfg80211_pmksa *pmksa) { struct iwm_priv *iwm = wiphy_to_iwm(wiphy); return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD); } -int iwm_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, - struct cfg80211_pmksa *pmksa) +static int iwm_cfg80211_del_pmksa(struct wiphy *wiphy, + struct net_device *netdev, + struct cfg80211_pmksa *pmksa) { struct iwm_priv *iwm = wiphy_to_iwm(wiphy); return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL); } -int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) +static int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy, + struct net_device *netdev) { struct iwm_priv *iwm = wiphy_to_iwm(wiphy); struct cfg80211_pmksa pmksa; -- cgit v1.2.3 From 1da3f88222579135569ad52d1c82a7393cf87178 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 25 Feb 2010 14:15:31 +0800 Subject: iwmc3200wifi: typo fix and code cleanup Fix wrong IWM_RX_TICKET_DROP_REASON_MSK macro define, typo and other small cleanups. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/commands.c | 2 +- drivers/net/wireless/iwmc3200wifi/rx.c | 7 +++---- drivers/net/wireless/iwmc3200wifi/tx.c | 7 +++---- drivers/net/wireless/iwmc3200wifi/umac.h | 2 +- 4 files changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 9ef4fd045041..b5cbd2bfd52a 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -506,7 +506,7 @@ static int iwm_target_read(struct iwm_priv *iwm, __le32 address, return ret; } - /* When succeding, the send_target routine returns the seq number */ + /* When succeeding, the send_target routine returns the seq number */ seq_num = ret; ret = wait_event_interruptible_timeout(iwm->nonwifi_queue, diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index c8a31be16885..5090a8a61887 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -869,16 +869,15 @@ static int iwm_mlme_remove_bss(struct iwm_priv *iwm, u8 *buf, int i; for (i = 0; i < le32_to_cpu(bss_rm->count); i++) { - table_idx = (le16_to_cpu(bss_rm->entries[i]) - & IWM_BSS_REMOVE_INDEX_MSK); + table_idx = le16_to_cpu(bss_rm->entries[i]) & + IWM_BSS_REMOVE_INDEX_MSK; list_for_each_entry_safe(bss, next, &iwm->bss_list, node) if (bss->bss->table_idx == cpu_to_le16(table_idx)) { struct ieee80211_mgmt *mgmt; mgmt = (struct ieee80211_mgmt *) (bss->bss->frame_buf); - IWM_DBG_MLME(iwm, ERR, - "BSS removed: %pM\n", + IWM_DBG_MLME(iwm, ERR, "BSS removed: %pM\n", mgmt->bssid); list_del(&bss->node); kfree(bss->bss); diff --git a/drivers/net/wireless/iwmc3200wifi/tx.c b/drivers/net/wireless/iwmc3200wifi/tx.c index 406615c2c580..a20b936ae21f 100644 --- a/drivers/net/wireless/iwmc3200wifi/tx.c +++ b/drivers/net/wireless/iwmc3200wifi/tx.c @@ -451,7 +451,6 @@ void iwm_tx_worker(struct work_struct *work) int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct iwm_priv *iwm = ndev_to_iwm(netdev); - struct net_device *ndev = iwm_to_ndev(iwm); struct wireless_dev *wdev = iwm_to_wdev(iwm); struct iwm_tx_info *tx_info; struct iwm_tx_queue *txq; @@ -518,12 +517,12 @@ int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev) queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker); - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += skb->len; + netdev->stats.tx_packets++; + netdev->stats.tx_bytes += skb->len; return NETDEV_TX_OK; drop: - ndev->stats.tx_dropped++; + netdev->stats.tx_dropped++; dev_kfree_skb_any(skb); return NETDEV_TX_OK; } diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h index 7f54a145ca65..0cbba3ecc813 100644 --- a/drivers/net/wireless/iwmc3200wifi/umac.h +++ b/drivers/net/wireless/iwmc3200wifi/umac.h @@ -362,7 +362,7 @@ struct iwm_udma_out_wifi_hdr { #define IWM_RX_TICKET_SPECIAL_SNAP_MSK 0x4 #define IWM_RX_TICKET_AMSDU_MSK 0x8 #define IWM_RX_TICKET_DROP_REASON_POS 4 -#define IWM_RX_TICKET_DROP_REASON_MSK (0x1F << RX_TICKET_FLAGS_DROP_REASON_POS) +#define IWM_RX_TICKET_DROP_REASON_MSK (0x1F << IWM_RX_TICKET_DROP_REASON_POS) #define IWM_RX_DROP_NO_DROP 0x0 #define IWM_RX_DROP_BAD_CRC 0x1 -- cgit v1.2.3 From 8127fbdc417b5916b82e91400a4be1d9555feee7 Mon Sep 17 00:00:00 2001 From: Benoit Papillault Date: Sat, 27 Feb 2010 23:05:26 +0100 Subject: ath5k: Fix TX/RX padding for all frames Currently, the padding position is based on ieee80211_get_hdrlen_from_skb(). This is not correct since the HW does padding on RX (and expect the same padding to be present on TX) at the following position : - management : 24 + 6 if 4-addr format - control : 24 + 6 if 4-addr format - data : 24 + 6 if 4-addr format + 2 if QoS - invalid : 24 + 6 if 4-addr format whereas ieee80211_get_hdrlen_from_skb() is : - management : 24 - control : 16 except for ACK/CTS where it is 10 - data : 24 + 6 if 4-addr format + 2 if QoS + 2 if QoS & order - invalid : 24 So, correct frames are not affected : management frames do not use 4-addr format, control frames have no body and invalid frames are ... not valid by definition. However, in order to use monitor interface for debugging purpose, one must be able to send/receive any frames, be it correct or not. Such frames are affected by incorrect padding. Moreover, since padding is added on TX, we need to remove it before calling ieee80211_tx_status. This affect TX packets received by monitor interfaces. It has been tested between an ath5k based card (AR5212) and an ar9170usb based card (netgear WNDA3100) using a frame generator and a monitor interface for each card. v2: Added ath5k_add_padding / ath5k_remove_padding Signed-off-by: Benoit Papillault Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 9 +-- drivers/net/wireless/ath/ath5k/base.c | 105 +++++++++++++++++++++++++-------- drivers/net/wireless/ath/ath5k/desc.c | 10 ++-- 3 files changed, 88 insertions(+), 36 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 4de7fe03b9fc..22f9f59397c1 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1141,9 +1141,9 @@ struct ath5k_hw { int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc, u32 size, unsigned int flags); int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, - unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, + unsigned int, unsigned int, int, enum ath5k_pkt_type, unsigned int, unsigned int, unsigned int, unsigned int, - unsigned int, unsigned int, unsigned int); + unsigned int, unsigned int, unsigned int, unsigned int); int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); @@ -1342,9 +1342,4 @@ static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) return retval; } -static inline int ath5k_pad_size(int hdrlen) -{ - return (hdrlen < 24) ? 0 : hdrlen & 3; -} - #endif diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index c889d4992a67..7c08434ebd1a 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -307,7 +307,7 @@ static int ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf); static int ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, - struct ath5k_txq *txq); + struct ath5k_txq *txq, int padsize); static inline void ath5k_txbuf_free(struct ath5k_softc *sc, struct ath5k_buf *bf) { @@ -1271,7 +1271,7 @@ static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb) static int ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, - struct ath5k_txq *txq) + struct ath5k_txq *txq, int padsize) { struct ath5k_hw *ah = sc->ah; struct ath5k_desc *ds = bf->desc; @@ -1323,7 +1323,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, sc->vif, pktlen, info)); } ret = ah->ah_setup_tx_desc(ah, ds, pktlen, - ieee80211_get_hdrlen_from_skb(skb), + ieee80211_get_hdrlen_from_skb(skb), padsize, get_hw_packet_type(skb), (sc->power_level * 2), hw_rate, @@ -1805,6 +1805,67 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, } } +/* + * Compute padding position. skb must contains an IEEE 802.11 frame + */ +static int ath5k_common_padpos(struct sk_buff *skb) +{ + struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; + __le16 frame_control = hdr->frame_control; + int padpos = 24; + + if (ieee80211_has_a4(frame_control)) { + padpos += ETH_ALEN; + } + if (ieee80211_is_data_qos(frame_control)) { + padpos += IEEE80211_QOS_CTL_LEN; + } + + return padpos; +} + +/* + * This function expects a 802.11 frame and returns the number of + * bytes added, or -1 if we don't have enought header room. + */ + +static int ath5k_add_padding(struct sk_buff *skb) +{ + int padpos = ath5k_common_padpos(skb); + int padsize = padpos & 3; + + if (padsize && skb->len>padpos) { + + if (skb_headroom(skb) < padsize) + return -1; + + skb_push(skb, padsize); + memmove(skb->data, skb->data+padsize, padpos); + return padsize; + } + + return 0; +} + +/* + * This function expects a 802.11 frame and returns the number of + * bytes removed + */ + +static int ath5k_remove_padding(struct sk_buff *skb) +{ + int padpos = ath5k_common_padpos(skb); + int padsize = padpos & 3; + + if (padsize && skb->len>=padpos+padsize) { + memmove(skb->data + padsize, skb->data, padpos); + skb_pull(skb, padsize); + return padsize; + } + + return 0; +} + static void ath5k_tasklet_rx(unsigned long data) { @@ -1818,8 +1879,6 @@ ath5k_tasklet_rx(unsigned long data) struct ath5k_buf *bf; struct ath5k_desc *ds; int ret; - int hdrlen; - int padsize; int rx_flag; spin_lock(&sc->rxbuflock); @@ -1904,12 +1963,8 @@ accept: * bytes and we can optimize this a bit. In addition, we must * not try to remove padding from short control frames that do * not have payload. */ - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - padsize = ath5k_pad_size(hdrlen); - if (padsize) { - memmove(skb->data + padsize, skb->data, hdrlen); - skb_pull(skb, padsize); - } + ath5k_remove_padding(skb); + rxs = IEEE80211_SKB_RXCB(skb); /* @@ -2029,6 +2084,12 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) info->status.ack_signal = ts.ts_rssi; } + /* + * Remove MAC header padding before giving the frame + * back to mac80211. + */ + ath5k_remove_padding(skb); + ieee80211_tx_status(sc->hw, skb); spin_lock(&sc->txbuflock); @@ -2072,6 +2133,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) int ret = 0; u8 antenna; u32 flags; + const int padsize = 0; bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); @@ -2119,7 +2181,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) * from tx power (value is in dB units already) */ ds->ds_data = bf->skbaddr; ret = ah->ah_setup_tx_desc(ah, ds, skb->len, - ieee80211_get_hdrlen_from_skb(skb), + ieee80211_get_hdrlen_from_skb(skb), padsize, AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), ieee80211_get_tx_rate(sc->hw, info)->hw_value, 1, AR5K_TXKEYIX_INVALID, @@ -2679,7 +2741,6 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath5k_softc *sc = hw->priv; struct ath5k_buf *bf; unsigned long flags; - int hdrlen; int padsize; ath5k_debug_dump_skb(sc, skb, "TX ", 1); @@ -2691,17 +2752,11 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, * the hardware expects the header padded to 4 byte boundaries * if this is not the case we add the padding after the header */ - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - padsize = ath5k_pad_size(hdrlen); - if (padsize) { - - if (skb_headroom(skb) < padsize) { - ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough" - " headroom to pad %d\n", hdrlen, padsize); - goto drop_packet; - } - skb_push(skb, padsize); - memmove(skb->data, skb->data+padsize, hdrlen); + padsize = ath5k_add_padding(skb); + if (padsize < 0) { + ATH5K_ERR(sc, "tx hdrlen not %%4: not enough" + " headroom to pad"); + goto drop_packet; } spin_lock_irqsave(&sc->txbuflock, flags); @@ -2720,7 +2775,7 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, bf->skb = skb; - if (ath5k_txbuf_setup(sc, bf, txq)) { + if (ath5k_txbuf_setup(sc, bf, txq, padsize)) { bf->skb = NULL; spin_lock_irqsave(&sc->txbuflock, flags); list_add_tail(&bf->list, &sc->txbuf); diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index dc30a2b70a6b..d26126bfacdd 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -35,7 +35,8 @@ */ static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, - unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type, + unsigned int pkt_len, unsigned int hdr_len, int padsize, + enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, unsigned int key_index, unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate, unsigned int rtscts_duration) @@ -71,7 +72,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, /* Verify and set frame length */ /* remove padding we might have added before */ - frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN; + frame_len = pkt_len - padsize + FCS_LEN; if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) return -EINVAL; @@ -100,7 +101,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); } - /*Diferences between 5210-5211*/ + /*Differences between 5210-5211*/ if (ah->ah_version == AR5K_AR5210) { switch (type) { case AR5K_PKT_TYPE_BEACON: @@ -165,6 +166,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, */ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len, + int padsize, enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, unsigned int key_index, unsigned int antenna_mode, unsigned int flags, @@ -206,7 +208,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, /* Verify and set frame length */ /* remove padding we might have added before */ - frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN; + frame_len = pkt_len - padsize + FCS_LEN; if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) return -EINVAL; -- cgit v1.2.3 From 80f8c5b434f94926c6489d7350d58aecb53ab70f Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Thu, 4 Mar 2010 18:27:02 +0200 Subject: rndis_wlan: copy only useful data from rndis_command respond rndis_query_oid() uses full output buffer size to copy response buffer from rndis_command()/device. This doesn't cause problems as response buffer is sized based on output buffer but does copy extra unset bytes. So change rndis_query_oid() so that only meaningful bytes are being copied. Also in case of malfunctioning device/cable/etc returned data offset from device might be wrong so bound check memory access correctly, so add checks for this. v2: fixed to use new netdev_dbg/warn/etc instead of old devdbg/warn/etc Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 9f6d6bf06b8e..a4f70de99cdd 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -704,6 +704,7 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) struct rndis_query_c *get_c; } u; int ret, buflen; + int resplen, respoffs, copylen; buflen = *len + sizeof(*u.get); if (buflen < CONTROL_BUFFER_SIZE) @@ -733,11 +734,34 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) le32_to_cpu(u.get_c->status)); if (ret == 0) { - memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len); + resplen = le32_to_cpu(u.get_c->len); + respoffs = le32_to_cpu(u.get_c->offset) + 8; - ret = le32_to_cpu(u.get_c->len); - if (ret > *len) - *len = ret; + if (respoffs > buflen) { + /* Device returned data offset outside buffer, error. */ + netdev_dbg(dev->net, "%s(%s): received invalid " + "data offset: %d > %d\n", __func__, + oid_to_string(oid), respoffs, buflen); + + ret = -EINVAL; + goto exit_unlock; + } + + if ((resplen + respoffs) > buflen) { + /* Device would have returned more data if buffer would + * have been big enough. Copy just the bits that we got. + */ + copylen = buflen - respoffs; + } else { + copylen = resplen; + } + + if (copylen > *len) + copylen = *len; + + memcpy(data, u.buf + respoffs, copylen); + + *len = resplen; ret = rndis_error_status(u.get_c->status); if (ret < 0) @@ -746,6 +770,7 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) le32_to_cpu(u.get_c->status), ret); } +exit_unlock: mutex_unlock(&priv->command_lock); if (u.buf != priv->command_buffer) -- cgit v1.2.3 From ea29d65ea4e7585a5ac94f7ec0069d384315bd77 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Thu, 4 Mar 2010 18:27:12 +0200 Subject: rndis_wlan: remove unused variables from priv structure Some variables were left unused after cfg80211 conversion. Remove those and related deadcode. Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index a4f70de99cdd..15bae0a68054 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -476,13 +476,7 @@ struct rndis_wlan_private { /* encryption stuff */ int encr_tx_key_index; struct rndis_wlan_encr_key encr_keys[4]; - enum nl80211_auth_type wpa_auth_type; int wpa_version; - int wpa_keymgmt; - int wpa_ie_len; - u8 *wpa_ie; - int wpa_cipher_pair; - int wpa_cipher_group; u8 command_buffer[COMMAND_BUFFER_SIZE]; }; @@ -1116,8 +1110,6 @@ static int set_auth_mode(struct usbnet *usbdev, u32 wpa_version, } priv->wpa_version = wpa_version; - priv->wpa_auth_type = auth_type; - priv->wpa_keymgmt = keymgmt; return 0; } @@ -1142,7 +1134,6 @@ static int set_priv_filter(struct usbnet *usbdev) static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise) { - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); __le32 tmp; int encr_mode, ret; @@ -1171,8 +1162,6 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise) return ret; } - priv->wpa_cipher_pair = pairwise; - priv->wpa_cipher_group = groupwise; return 0; } @@ -2871,9 +2860,6 @@ static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf) flush_workqueue(priv->workqueue); destroy_workqueue(priv->workqueue); - if (priv && priv->wpa_ie_len) - kfree(priv->wpa_ie); - rndis_unbind(usbdev, intf); wiphy_unregister(priv->wdev.wiphy); -- cgit v1.2.3 From 0308383f9591c991b3eb865c4f5ea2a87242afac Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Thu, 4 Mar 2010 18:27:24 +0200 Subject: rndis_wlan: get max_num_pmkids from device Extend rndis_wlan_get_caps() to get 802.11 capabilities and maximum supported number of PMKIDs by device. v2: fixed to use new netdev_dbg/warn/etc instead of old devdbg/warn/etc Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 15bae0a68054..3433461995a7 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -117,6 +117,7 @@ MODULE_PARM_DESC(workaround_interval, #define OID_802_11_ADD_KEY cpu_to_le32(0x0d01011d) #define OID_802_11_REMOVE_KEY cpu_to_le32(0x0d01011e) #define OID_802_11_ASSOCIATION_INFORMATION cpu_to_le32(0x0d01011f) +#define OID_802_11_CAPABILITY cpu_to_le32(0x0d010122) #define OID_802_11_PMKID cpu_to_le32(0x0d010123) #define OID_802_11_NETWORK_TYPES_SUPPORTED cpu_to_le32(0x0d010203) #define OID_802_11_NETWORK_TYPE_IN_USE cpu_to_le32(0x0d010204) @@ -358,6 +359,19 @@ struct ndis_80211_assoc_info { __le32 offset_resp_ies; } __attribute__((packed)); +struct ndis_80211_auth_encr_pair { + __le32 auth_mode; + __le32 encr_mode; +} __attribute__((packed)); + +struct ndis_80211_capability { + __le32 length; + __le32 version; + __le32 num_pmkids; + __le32 num_auth_encr_pair; + struct ndis_80211_auth_encr_pair auth_encr_pair[0]; +} __attribute__((packed)); + /* * private data */ @@ -2520,12 +2534,14 @@ static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen) } } -static int rndis_wlan_get_caps(struct usbnet *usbdev) +static int rndis_wlan_get_caps(struct usbnet *usbdev, struct wiphy *wiphy) { struct { __le32 num_items; __le32 items[8]; } networks_supported; + struct ndis_80211_capability *caps; + u8 caps_buf[sizeof(*caps) + sizeof(caps->auth_encr_pair) * 16]; int len, retval, i, n; struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); @@ -2553,6 +2569,21 @@ static int rndis_wlan_get_caps(struct usbnet *usbdev) } } + /* get device 802.11 capabilities, number of PMKIDs */ + caps = (struct ndis_80211_capability *)caps_buf; + len = sizeof(caps_buf); + retval = rndis_query_oid(usbdev, OID_802_11_CAPABILITY, caps, &len); + if (retval >= 0) { + netdev_dbg(usbdev->net, "OID_802_11_CAPABILITY -> len %d, " + "ver %d, pmkids %d, auth-encr-pairs %d\n", + le32_to_cpu(caps->length), + le32_to_cpu(caps->version), + le32_to_cpu(caps->num_pmkids), + le32_to_cpu(caps->num_auth_encr_pair)); + wiphy->max_num_pmkids = le32_to_cpu(caps->num_pmkids); + } else + wiphy->max_num_pmkids = 0; + return retval; } @@ -2800,7 +2831,7 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf) wiphy->max_scan_ssids = 1; /* TODO: fill-out band/encr information based on priv->caps */ - rndis_wlan_get_caps(usbdev); + rndis_wlan_get_caps(usbdev, wiphy); memcpy(priv->channels, rndis_channels, sizeof(rndis_channels)); memcpy(priv->rates, rndis_rates, sizeof(rndis_rates)); -- cgit v1.2.3 From 5a7d05830de1ecfdaf0a9fb43e4aa08abbdbfe9f Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Thu, 4 Mar 2010 18:27:36 +0200 Subject: rndis_wlan: Implement cfg80211 PMKSA API Add support for cfg80211 set_pmksa/del_pmksa/flush_pmksa. Updating PMKID entry list is done on driver side since NDIS API requires full list update. v2: - fixed to use new netdev_dbg/warn/etc instead of old devdbg/warn/etc - fixed false padding from struct ndis_80211_bssid_info Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 282 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 3433461995a7..267afd714c74 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -372,6 +372,17 @@ struct ndis_80211_capability { struct ndis_80211_auth_encr_pair auth_encr_pair[0]; } __attribute__((packed)); +struct ndis_80211_bssid_info { + u8 bssid[6]; + u8 pmkid[16]; +}; + +struct ndis_80211_pmkid { + __le32 length; + __le32 bssid_info_count; + struct ndis_80211_bssid_info bssid_info[0]; +}; + /* * private data */ @@ -542,6 +553,14 @@ static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *mac, struct station_info *sinfo); +static int rndis_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa); + +static int rndis_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa); + +static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev); + static struct cfg80211_ops rndis_config_ops = { .change_virtual_intf = rndis_change_virtual_intf, .scan = rndis_scan, @@ -558,6 +577,9 @@ static struct cfg80211_ops rndis_config_ops = { .set_default_key = rndis_set_default_key, .get_station = rndis_get_station, .dump_station = rndis_dump_station, + .set_pmksa = rndis_set_pmksa, + .del_pmksa = rndis_del_pmksa, + .flush_pmksa = rndis_flush_pmksa, }; static void *rndis_wiphy_privid = &rndis_wiphy_privid; @@ -1580,6 +1602,194 @@ static void set_multicast_list(struct usbnet *usbdev) le32_to_cpu(filter), ret); } +#ifdef DEBUG +static void debug_print_pmkids(struct usbnet *usbdev, + struct ndis_80211_pmkid *pmkids, + const char *func_str) +{ + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); + int i, len, count, max_pmkids, entry_len; + + max_pmkids = priv->wdev.wiphy->max_num_pmkids; + len = le32_to_cpu(pmkids->length); + count = le32_to_cpu(pmkids->bssid_info_count); + + entry_len = (count > 0) ? (len - sizeof(*pmkids)) / count : -1; + + netdev_dbg(usbdev->net, "%s(): %d PMKIDs (data len: %d, entry len: " + "%d)\n", func_str, count, len, entry_len); + + if (count > max_pmkids) + count = max_pmkids; + + for (i = 0; i < count; i++) { + u32 *tmp = (u32 *)pmkids->bssid_info[i].pmkid; + + netdev_dbg(usbdev->net, "%s(): bssid: %pM, " + "pmkid: %08X:%08X:%08X:%08X\n", + func_str, pmkids->bssid_info[i].bssid, + cpu_to_be32(tmp[0]), cpu_to_be32(tmp[1]), + cpu_to_be32(tmp[2]), cpu_to_be32(tmp[3])); + } +} +#else +static void debug_print_pmkids(struct usbnet *usbdev, + struct ndis_80211_pmkid *pmkids, + const char *func_str) +{ + return; +} +#endif + +static struct ndis_80211_pmkid *get_device_pmkids(struct usbnet *usbdev) +{ + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); + struct ndis_80211_pmkid *pmkids; + int len, ret, max_pmkids; + + max_pmkids = priv->wdev.wiphy->max_num_pmkids; + len = sizeof(*pmkids) + max_pmkids * sizeof(pmkids->bssid_info[0]); + + pmkids = kzalloc(len, GFP_KERNEL); + if (!pmkids) + return ERR_PTR(-ENOMEM); + + pmkids->length = cpu_to_le32(len); + pmkids->bssid_info_count = cpu_to_le32(max_pmkids); + + ret = rndis_query_oid(usbdev, OID_802_11_PMKID, pmkids, &len); + if (ret < 0) { + netdev_dbg(usbdev->net, "%s(): OID_802_11_PMKID(%d, %d)" + " -> %d\n", __func__, len, max_pmkids, ret); + + kfree(pmkids); + return ERR_PTR(ret); + } + + if (le32_to_cpu(pmkids->bssid_info_count) > max_pmkids) + pmkids->bssid_info_count = cpu_to_le32(max_pmkids); + + debug_print_pmkids(usbdev, pmkids, __func__); + + return pmkids; +} + +static int set_device_pmkids(struct usbnet *usbdev, + struct ndis_80211_pmkid *pmkids) +{ + int ret, len, num_pmkids; + + num_pmkids = le32_to_cpu(pmkids->bssid_info_count); + len = sizeof(*pmkids) + num_pmkids * sizeof(pmkids->bssid_info[0]); + pmkids->length = cpu_to_le32(len); + + debug_print_pmkids(usbdev, pmkids, __func__); + + ret = rndis_set_oid(usbdev, OID_802_11_PMKID, pmkids, + le32_to_cpu(pmkids->length)); + if (ret < 0) { + netdev_dbg(usbdev->net, "%s(): OID_802_11_PMKID(%d, %d) -> %d" + "\n", __func__, len, num_pmkids, ret); + } + + kfree(pmkids); + return ret; +} + +static struct ndis_80211_pmkid *remove_pmkid(struct usbnet *usbdev, + struct ndis_80211_pmkid *pmkids, + struct cfg80211_pmksa *pmksa, + int max_pmkids) +{ + int i, len, count, newlen, err; + + len = le32_to_cpu(pmkids->length); + count = le32_to_cpu(pmkids->bssid_info_count); + + if (count > max_pmkids) + count = max_pmkids; + + for (i = 0; i < count; i++) + if (!compare_ether_addr(pmkids->bssid_info[i].bssid, + pmksa->bssid)) + break; + + /* pmkid not found */ + if (i == count) { + netdev_dbg(usbdev->net, "%s(): bssid not found (%pM)\n", + __func__, pmksa->bssid); + err = -ENOENT; + goto error; + } + + for (; i + 1 < count; i++) + pmkids->bssid_info[i] = pmkids->bssid_info[i + 1]; + + count--; + newlen = sizeof(*pmkids) + count * sizeof(pmkids->bssid_info[0]); + + pmkids->length = cpu_to_le32(newlen); + pmkids->bssid_info_count = cpu_to_le32(count); + + return pmkids; +error: + kfree(pmkids); + return ERR_PTR(err); +} + +static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev, + struct ndis_80211_pmkid *pmkids, + struct cfg80211_pmksa *pmksa, + int max_pmkids) +{ + int i, err, len, count, newlen; + + len = le32_to_cpu(pmkids->length); + count = le32_to_cpu(pmkids->bssid_info_count); + + if (count > max_pmkids) + count = max_pmkids; + + /* update with new pmkid */ + for (i = 0; i < count; i++) { + if (compare_ether_addr(pmkids->bssid_info[i].bssid, + pmksa->bssid)) + continue; + + memcpy(pmkids->bssid_info[i].pmkid, pmksa->pmkid, + WLAN_PMKID_LEN); + + return pmkids; + } + + /* out of space, return error */ + if (i == max_pmkids) { + netdev_dbg(usbdev->net, "%s(): out of space\n", __func__); + err = -ENOSPC; + goto error; + } + + /* add new pmkid */ + newlen = sizeof(*pmkids) + (count + 1) * sizeof(pmkids->bssid_info[0]); + + pmkids = krealloc(pmkids, newlen, GFP_KERNEL); + if (!pmkids) { + err = -ENOMEM; + goto error; + } + + pmkids->length = cpu_to_le32(newlen); + pmkids->bssid_info_count = cpu_to_le32(count + 1); + + memcpy(pmkids->bssid_info[count].bssid, pmksa->bssid, ETH_ALEN); + memcpy(pmkids->bssid_info[count].pmkid, pmksa->pmkid, WLAN_PMKID_LEN); + + return pmkids; +error: + kfree(pmkids); + return ERR_PTR(err); +} + /* * cfg80211 ops */ @@ -2190,6 +2400,78 @@ static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev, return 0; } +static int rndis_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + struct rndis_wlan_private *priv = wiphy_priv(wiphy); + struct usbnet *usbdev = priv->usbdev; + struct ndis_80211_pmkid *pmkids; + u32 *tmp = (u32 *)pmksa->pmkid; + + netdev_dbg(usbdev->net, "%s(%pM, %08X:%08X:%08X:%08X)\n", __func__, + pmksa->bssid, + cpu_to_be32(tmp[0]), cpu_to_be32(tmp[1]), + cpu_to_be32(tmp[2]), cpu_to_be32(tmp[3])); + + pmkids = get_device_pmkids(usbdev); + if (IS_ERR(pmkids)) { + /* couldn't read PMKID cache from device */ + return PTR_ERR(pmkids); + } + + pmkids = update_pmkid(usbdev, pmkids, pmksa, wiphy->max_num_pmkids); + if (IS_ERR(pmkids)) { + /* not found, list full, etc */ + return PTR_ERR(pmkids); + } + + return set_device_pmkids(usbdev, pmkids); +} + +static int rndis_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + struct rndis_wlan_private *priv = wiphy_priv(wiphy); + struct usbnet *usbdev = priv->usbdev; + struct ndis_80211_pmkid *pmkids; + u32 *tmp = (u32 *)pmksa->pmkid; + + netdev_dbg(usbdev->net, "%s(%pM, %08X:%08X:%08X:%08X)\n", __func__, + pmksa->bssid, + cpu_to_be32(tmp[0]), cpu_to_be32(tmp[1]), + cpu_to_be32(tmp[2]), cpu_to_be32(tmp[3])); + + pmkids = get_device_pmkids(usbdev); + if (IS_ERR(pmkids)) { + /* Couldn't read PMKID cache from device */ + return PTR_ERR(pmkids); + } + + pmkids = remove_pmkid(usbdev, pmkids, pmksa, wiphy->max_num_pmkids); + if (IS_ERR(pmkids)) { + /* not found, etc */ + return PTR_ERR(pmkids); + } + + return set_device_pmkids(usbdev, pmkids); +} + +static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) +{ + struct rndis_wlan_private *priv = wiphy_priv(wiphy); + struct usbnet *usbdev = priv->usbdev; + struct ndis_80211_pmkid pmkid; + + netdev_dbg(usbdev->net, "%s()\n", __func__); + + memset(&pmkid, 0, sizeof(pmkid)); + + pmkid.length = cpu_to_le32(sizeof(pmkid)); + pmkid.bssid_info_count = cpu_to_le32(0); + + return rndis_set_oid(usbdev, OID_802_11_PMKID, &pmkid, sizeof(pmkid)); +} + /* * workers, indication handlers, device poller */ -- cgit v1.2.3 From 604eeadd1880bddfb155369491cc13fb8d3f9df6 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Tue, 9 Mar 2010 16:55:17 +0900 Subject: ath5k: add antenna statistics and debugfs file for antenna settings keep statistics about which antenna was used for TX and RX. this is used only for debugging right now, but might have other applications later. add a new file 'antenna' in debugfs (/sys/kernel/debug/ath5k/phy0/antenna) to show antenna use statistics and antenna diversity related register values. it can also be used to set the antenna mode until we have proper support for that in iw: - echo diversity > antenna: use default antenna mode (RX and TX diversity) - echo fixed-a > antenna: use fixed antenna A for RX and TX - echo fixed-b > antenna: use fixed antenna B for RX and TX - echo clear > antenna: reset antenna statistics Signed-off-by: Bruno Randolf Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 11 ++++ drivers/net/wireless/ath/ath5k/base.h | 8 +++ drivers/net/wireless/ath/ath5k/debug.c | 106 +++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath5k/debug.h | 1 + 4 files changed, 126 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 7c08434ebd1a..e7a989c707ac 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1997,6 +1997,12 @@ accept: rxs->signal = rxs->noise + rs.rs_rssi; rxs->antenna = rs.rs_antenna; + + if (rs.rs_antenna > 0 && rs.rs_antenna < 5) + sc->stats.antenna_rx[rs.rs_antenna]++; + else + sc->stats.antenna_rx[0]++; /* invalid */ + rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); @@ -2090,6 +2096,11 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) */ ath5k_remove_padding(skb); + if (ts.ts_antenna > 0 && ts.ts_antenna < 5) + sc->stats.antenna_tx[ts.ts_antenna]++; + else + sc->stats.antenna_tx[0]++; /* invalid */ + ieee80211_tx_status(sc->hw, skb); spin_lock(&sc->txbuflock); diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 7e1a88a5abdb..ca525842d827 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -105,6 +105,12 @@ struct ath5k_rfkill { struct tasklet_struct toggleq; }; +/* statistics (only used for debugging now) */ +struct ath5k_statistics { + unsigned int antenna_rx[5]; /* frames count per antenna RX */ + unsigned int antenna_tx[5]; /* frames count per antenna TX */ +}; + #if CHAN_DEBUG #define ATH_CHAN_MAX (26+26+26+200+200) #else @@ -191,6 +197,8 @@ struct ath5k_softc { int power_level; /* Requested tx power in dbm */ bool assoc; /* associate state */ bool enable_beacon; /* true if beacons are on */ + + struct ath5k_statistics stats; }; #define ath5k_hw_hasbssidmask(_ah) \ diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 747508c15d34..236f20f9cd40 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -364,6 +364,107 @@ static const struct file_operations fops_debug = { }; +/* debugfs: antenna */ + +static ssize_t read_file_antenna(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + char buf[700]; + unsigned int len = 0; + unsigned int i; + unsigned int v; + + len += snprintf(buf+len, sizeof(buf)-len, "antenna mode\t%d\n", + sc->ah->ah_ant_mode); + len += snprintf(buf+len, sizeof(buf)-len, "default antenna\t%d\n", + sc->ah->ah_def_ant); + len += snprintf(buf+len, sizeof(buf)-len, "tx antenna\t%d\n", + sc->ah->ah_tx_ant); + + len += snprintf(buf+len, sizeof(buf)-len, "\nANTENNA\t\tRX\tTX\n"); + for (i = 1; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) { + len += snprintf(buf+len, sizeof(buf)-len, + "[antenna %d]\t%d\t%d\n", + i, sc->stats.antenna_rx[i], sc->stats.antenna_tx[i]); + } + len += snprintf(buf+len, sizeof(buf)-len, "[invalid]\t%d\t%d\n", + sc->stats.antenna_rx[0], sc->stats.antenna_tx[0]); + + v = ath5k_hw_reg_read(sc->ah, AR5K_DEFAULT_ANTENNA); + len += snprintf(buf+len, sizeof(buf)-len, + "\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v); + + v = ath5k_hw_reg_read(sc->ah, AR5K_STA_ID1); + len += snprintf(buf+len, sizeof(buf)-len, + "AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n", + (v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0); + len += snprintf(buf+len, sizeof(buf)-len, + "AR5K_STA_ID1_DESC_ANTENNA\t%d\n", + (v & AR5K_STA_ID1_DESC_ANTENNA) != 0); + len += snprintf(buf+len, sizeof(buf)-len, + "AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n", + (v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0); + len += snprintf(buf+len, sizeof(buf)-len, + "AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n", + (v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0); + + v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_AGCCTL); + len += snprintf(buf+len, sizeof(buf)-len, + "\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n", + (v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0); + + v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_RESTART); + len += snprintf(buf+len, sizeof(buf)-len, + "AR5K_PHY_RESTART_DIV_GC\t\t%x\n", + (v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S); + + v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_FAST_ANT_DIV); + len += snprintf(buf+len, sizeof(buf)-len, + "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n", + (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_antenna(struct file *file, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + unsigned int i; + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; + + if (strncmp(buf, "diversity", 9) == 0) { + ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT); + printk(KERN_INFO "ath5k debug: enable diversity\n"); + } else if (strncmp(buf, "fixed-a", 7) == 0) { + ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A); + printk(KERN_INFO "ath5k debugfs: fixed antenna A\n"); + } else if (strncmp(buf, "fixed-b", 7) == 0) { + ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B); + printk(KERN_INFO "ath5k debug: fixed antenna B\n"); + } else if (strncmp(buf, "clear", 5) == 0) { + for (i = 0; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) { + sc->stats.antenna_rx[i] = 0; + sc->stats.antenna_tx[i] = 0; + } + printk(KERN_INFO "ath5k debug: cleared antenna stats\n"); + } + return count; +} + +static const struct file_operations fops_antenna = { + .read = read_file_antenna, + .write = write_file_antenna, + .open = ath5k_debugfs_open, + .owner = THIS_MODULE, +}; + + /* init */ void @@ -393,6 +494,10 @@ ath5k_debug_init_device(struct ath5k_softc *sc) sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, sc->debug.debugfs_phydir, sc, &fops_reset); + + sc->debug.debugfs_antenna = debugfs_create_file("antenna", + S_IWUSR | S_IRUSR, + sc->debug.debugfs_phydir, sc, &fops_antenna); } void @@ -408,6 +513,7 @@ ath5k_debug_finish_device(struct ath5k_softc *sc) debugfs_remove(sc->debug.debugfs_registers); debugfs_remove(sc->debug.debugfs_beacon); debugfs_remove(sc->debug.debugfs_reset); + debugfs_remove(sc->debug.debugfs_antenna); debugfs_remove(sc->debug.debugfs_phydir); } diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index 66f69f04e55e..018612711045 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h @@ -74,6 +74,7 @@ struct ath5k_dbg_info { struct dentry *debugfs_registers; struct dentry *debugfs_beacon; struct dentry *debugfs_reset; + struct dentry *debugfs_antenna; }; /** -- cgit v1.2.3 From caec9112d6cb07cb5b82a967a448c3b15b257654 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Tue, 9 Mar 2010 16:55:28 +0900 Subject: ath5k: preserve antenna settings save antenna settings and preserve across resets. Signed-off-by: Bruno Randolf Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/attach.c | 1 + drivers/net/wireless/ath/ath5k/base.c | 2 +- drivers/net/wireless/ath/ath5k/phy.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 42284445b75e..c8bb102a4db4 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -123,6 +123,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ah->ah_cw_min = AR5K_TUNE_CWMIN; ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; ah->ah_software_retry = false; + ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; /* * Find the mac version diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index e7a989c707ac..fdf3190e4611 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2971,7 +2971,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) * then we must allow the user to set how many tx antennas we * have available */ - ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); + ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); unlock: mutex_unlock(&sc->lock); diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 10ad877c2cdf..5aee85f27c0e 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1929,6 +1929,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) ah->ah_tx_ant = tx_ant; ah->ah_ant_mode = ant_mode; + ah->ah_def_ant = def_ant; sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0; sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0; -- cgit v1.2.3 From ccfe5552aeb18c87a4d0ecb8cb7512280435bfdd Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Tue, 9 Mar 2010 16:55:38 +0900 Subject: ath5k: remove double opmode definition opmode (operating mode) was defined in struct ath5k_hw and struct ath5k_softc. remove it from ath5k_hw and use only from ath5k_softc (sc->opmode). (btw: what's the meaning of opmode when we have multiple interfaces?) Signed-off-by: Bruno Randolf Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 3 +-- drivers/net/wireless/ath/ath5k/attach.c | 3 +-- drivers/net/wireless/ath/ath5k/base.c | 7 ++++--- drivers/net/wireless/ath/ath5k/pcu.c | 14 +++++++------- drivers/net/wireless/ath/ath5k/reset.c | 9 ++------- 5 files changed, 15 insertions(+), 21 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 22f9f59397c1..e5ace22b951e 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1036,7 +1036,6 @@ struct ath5k_hw { enum ath5k_int ah_imr; - enum nl80211_iftype ah_op_mode; struct ieee80211_channel *ah_current_channel; bool ah_turbo; bool ah_calibration; @@ -1200,7 +1199,7 @@ void ath5k_eeprom_detach(struct ath5k_hw *ah); int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); /* Protocol Control Unit Functions */ -int ath5k_hw_set_opmode(struct ath5k_hw *ah); +extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); /* BSSID Functions */ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index c8bb102a4db4..66758cb66d50 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -113,7 +113,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc) /* * HW information */ - ah->ah_op_mode = NL80211_IFTYPE_STATION; ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; ah->ah_turbo = false; ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; @@ -328,7 +327,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); ath5k_hw_set_associd(ah); - ath5k_hw_set_opmode(ah); + ath5k_hw_set_opmode(ah, sc->opmode); ath5k_hw_rfgain_opt_init(ah); diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index fdf3190e4611..79922cfd96b8 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1137,8 +1137,6 @@ ath5k_mode_setup(struct ath5k_softc *sc) struct ath5k_hw *ah = sc->ah; u32 rfilt; - ah->ah_op_mode = sc->opmode; - /* configure rx filter */ rfilt = sc->filter_flags; ath5k_hw_set_rx_filter(ah, rfilt); @@ -1147,8 +1145,9 @@ ath5k_mode_setup(struct ath5k_softc *sc) ath5k_hw_set_bssid_mask(ah, sc->bssidmask); /* configure operational mode */ - ath5k_hw_set_opmode(ah); + ath5k_hw_set_opmode(ah, sc->opmode); + ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d\n", sc->opmode); ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); } @@ -2901,6 +2900,8 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, goto end; } + ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", sc->opmode); + ath5k_hw_set_lladdr(sc->ah, vif->addr); ath5k_mode_setup(sc); diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index be69ebb2744e..c813046b3540 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -39,16 +39,16 @@ * ath5k_hw_set_opmode - Set PCU operating mode * * @ah: The &struct ath5k_hw + * @op_mode: &enum nl80211_iftype operating mode * * Initialize PCU for the various operating modes (AP/STA etc) - * - * NOTE: ah->ah_op_mode must be set before calling this. */ -int ath5k_hw_set_opmode(struct ath5k_hw *ah) +int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) { struct ath_common *common = ath5k_hw_common(ah); u32 pcu_reg, beacon_reg, low_id, high_id; + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); /* Preserve rest settings */ pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; @@ -61,7 +61,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) ATH5K_TRACE(ah->ah_sc); - switch (ah->ah_op_mode) { + switch (op_mode) { case NL80211_IFTYPE_ADHOC: pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; beacon_reg |= AR5K_BCR_ADHOC; @@ -644,7 +644,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) /* * Set the additional timers by mode */ - switch (ah->ah_op_mode) { + switch (ah->ah_sc->opmode) { case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_STATION: /* In STA mode timer1 is used as next wakeup @@ -681,8 +681,8 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) * Set the beacon register and enable all timers. */ /* When in AP or Mesh Point mode zero timer0 to start TSF */ - if (ah->ah_op_mode == NL80211_IFTYPE_AP || - ah->ah_op_mode == NL80211_IFTYPE_MESH_POINT) + if (ah->ah_sc->opmode == NL80211_IFTYPE_AP || + ah->ah_sc->opmode == NL80211_IFTYPE_MESH_POINT) ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 8bd62c130b26..4120068792ec 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -1033,11 +1033,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, if (ret) return ret; - /* - * Initialize operating mode - */ - ah->ah_op_mode = op_mode; - /* PHY access enable */ if (ah->ah_mac_srev >= AR5K_SREV_AR5211) ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); @@ -1208,7 +1203,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ath5k_hw_set_associd(ah); /* Set PCU config */ - ath5k_hw_set_opmode(ah); + ath5k_hw_set_opmode(ah, op_mode); /* Clear any pending interrupts * PISR/SISR Not available on 5210 */ @@ -1394,7 +1389,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, * external 32KHz crystal when sleeping if one * exists */ if (ah->ah_version == AR5K_AR5212 && - ah->ah_op_mode != NL80211_IFTYPE_AP) + op_mode != NL80211_IFTYPE_AP) ath5k_hw_set_sleep_clock(ah, true); /* -- cgit v1.2.3 From ff5d96ce622271df430c715ebe3e0b7400059dc1 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Tue, 9 Mar 2010 16:55:44 +0900 Subject: ath5k: remove ah_magic it's never used. probably a leftover from the old OpenHAL days... Signed-off-by: Bruno Randolf Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 1 - drivers/net/wireless/ath/ath5k/desc.c | 6 ------ drivers/net/wireless/ath/ath5k/eeprom.h | 3 --- 3 files changed, 10 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index e5ace22b951e..2c3b4a65752c 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1028,7 +1028,6 @@ struct ath5k_nfcal_hist /* TODO: Clean up and merge with ath5k_softc */ struct ath5k_hw { - u32 ah_magic; struct ath_common common; struct ath5k_softc *ah_sc; diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index d26126bfacdd..aebb31f2834b 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -670,12 +670,6 @@ int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) ah->ah_version != AR5K_AR5212) return -ENOTSUPP; - /* XXX: What is this magic value and where is it used ? */ - if (ah->ah_version == AR5K_AR5212) - ah->ah_magic = AR5K_EEPROM_MAGIC_5212; - else if (ah->ah_version == AR5K_AR5211) - ah->ah_magic = AR5K_EEPROM_MAGIC_5211; - if (ah->ah_version == AR5K_AR5212) { ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 473a483bb9c3..1a65683e8c16 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -24,9 +24,6 @@ * SERDES infos are present */ #define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */ #define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */ -#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */ -#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */ -#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ #define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */ -- cgit v1.2.3 From a71bcebcb776e84dd765d2c7da51ed45a714e3ea Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Tue, 9 Mar 2010 16:55:49 +0900 Subject: ath5k: remove ah_mac_revision it's not used, and we have ah_mac_srev. Signed-off-by: Bruno Randolf Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 1 - drivers/net/wireless/ath/ath5k/attach.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 2c3b4a65752c..1c2a8e87d767 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1047,7 +1047,6 @@ struct ath5k_hw { u32 ah_phy; u32 ah_mac_srev; u16 ah_mac_version; - u16 ah_mac_revision; u16 ah_phy_revision; u16 ah_radio_5ghz_revision; u16 ah_radio_2ghz_revision; diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 66758cb66d50..dd4099a2ff15 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -148,7 +148,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc) /* Get MAC, PHY and RADIO revisions */ ah->ah_mac_srev = srev; ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); - ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV); ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & 0xffffffff; ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, -- cgit v1.2.3 From 919154540aa26e8c333c420b5b930e94ef7a6839 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Tue, 9 Mar 2010 16:55:55 +0900 Subject: ath5k: remove ah_gpio_npins it's never used and we have a newer implementation in gpio.c. Signed-off-by: Bruno Randolf Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 2 -- drivers/net/wireless/ath/ath5k/caps.c | 3 --- 2 files changed, 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 1c2a8e87d767..5898e2e50a70 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1068,8 +1068,6 @@ struct ath5k_hw { u8 ah_def_ant; bool ah_software_retry; - int ah_gpio_npins; - struct ath5k_capabilities ah_capabilities; struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index 367a6c7d3cc7..e618e71b1ce6 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c @@ -102,9 +102,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) } } - /* GPIO */ - ah->ah_gpio_npins = AR5K_NUM_GPIO; - /* Set number of supported TX queues */ if (ah->ah_version == AR5K_AR5210) ah->ah_capabilities.cap_queues.q_tx_num = -- cgit v1.2.3 From 7644395f8df9aa5b42af268a485b83e44bba2784 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Tue, 9 Mar 2010 16:56:00 +0900 Subject: ath5k: add debugfs file frameerrors add a debugfs file to see different RX and TX errors as reported in our status descriptors. this can help to diagnose driver problems. statistics can be cleared by writing 'clear' into the frameerrors file. example: # cat /sys/kernel/debug/ath5k/phy0/frameerrors RX --------------------- CRC 27 (11%) PHY 3 (1%) FIFO 0 (0%) decrypt 0 (0%) MIC 0 (0%) process 0 (0%) jumbo 0 (0%) [RX all 245] TX --------------------- retry 2 (9%) FIFO 0 (0%) filter 0 (0%) [TX all 21] Signed-off-by: Bruno Randolf Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 23 ++++++- drivers/net/wireless/ath/ath5k/base.h | 12 ++++ drivers/net/wireless/ath/ath5k/debug.c | 106 +++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath5k/debug.h | 1 + 4 files changed, 140 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 79922cfd96b8..b142a78ed1e5 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1902,18 +1902,28 @@ ath5k_tasklet_rx(unsigned long data) break; else if (unlikely(ret)) { ATH5K_ERR(sc, "error in processing rx descriptor\n"); + sc->stats.rxerr_proc++; spin_unlock(&sc->rxbuflock); return; } + sc->stats.rx_all_count++; + if (unlikely(rs.rs_more)) { ATH5K_WARN(sc, "unsupported jumbo\n"); + sc->stats.rxerr_jumbo++; goto next; } if (unlikely(rs.rs_status)) { - if (rs.rs_status & AR5K_RXERR_PHY) + if (rs.rs_status & AR5K_RXERR_CRC) + sc->stats.rxerr_crc++; + if (rs.rs_status & AR5K_RXERR_FIFO) + sc->stats.rxerr_fifo++; + if (rs.rs_status & AR5K_RXERR_PHY) { + sc->stats.rxerr_phy++; goto next; + } if (rs.rs_status & AR5K_RXERR_DECRYPT) { /* * Decrypt error. If the error occurred @@ -1925,12 +1935,14 @@ ath5k_tasklet_rx(unsigned long data) * * XXX do key cache faulting */ + sc->stats.rxerr_decrypt++; if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && !(rs.rs_status & AR5K_RXERR_CRC)) goto accept; } if (rs.rs_status & AR5K_RXERR_MIC) { rx_flag |= RX_FLAG_MMIC_ERROR; + sc->stats.rxerr_mic++; goto accept; } @@ -2056,6 +2068,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) break; } + sc->stats.tx_all_count++; skb = bf->skb; info = IEEE80211_SKB_CB(skb); bf->skb = NULL; @@ -2082,8 +2095,14 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) if (unlikely(ts.ts_status)) { sc->ll_stats.dot11ACKFailureCount++; - if (ts.ts_status & AR5K_TXERR_FILT) + if (ts.ts_status & AR5K_TXERR_FILT) { info->flags |= IEEE80211_TX_STAT_TX_FILTERED; + sc->stats.txerr_filt++; + } + if (ts.ts_status & AR5K_TXERR_XRETRY) + sc->stats.txerr_retry++; + if (ts.ts_status & AR5K_TXERR_FIFO) + sc->stats.txerr_fifo++; } else { info->flags |= IEEE80211_TX_STAT_ACK; info->status.ack_signal = ts.ts_rssi; diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index ca525842d827..33f1d8b87ee1 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -109,6 +109,18 @@ struct ath5k_rfkill { struct ath5k_statistics { unsigned int antenna_rx[5]; /* frames count per antenna RX */ unsigned int antenna_tx[5]; /* frames count per antenna TX */ + unsigned int rx_all_count; /* all RX frames, including errors */ + unsigned int tx_all_count; /* all TX frames, including errors */ + unsigned int rxerr_crc; + unsigned int rxerr_phy; + unsigned int rxerr_fifo; + unsigned int rxerr_decrypt; + unsigned int rxerr_mic; + unsigned int rxerr_proc; + unsigned int rxerr_jumbo; + unsigned int txerr_retry; + unsigned int txerr_fifo; + unsigned int txerr_filt; }; #if CHAN_DEBUG diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 236f20f9cd40..bccd4a78027e 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -465,6 +465,106 @@ static const struct file_operations fops_antenna = { }; +/* debugfs: frameerrors */ + +static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + struct ath5k_statistics *st = &sc->stats; + char buf[700]; + unsigned int len = 0; + + len += snprintf(buf+len, sizeof(buf)-len, + "RX\n---------------------\n"); + len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%d\t(%d%%)\n", + st->rxerr_crc, + st->rx_all_count > 0 ? + st->rxerr_crc*100/st->rx_all_count : 0); + len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%d\t(%d%%)\n", + st->rxerr_phy, + st->rx_all_count > 0 ? + st->rxerr_phy*100/st->rx_all_count : 0); + len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", + st->rxerr_fifo, + st->rx_all_count > 0 ? + st->rxerr_fifo*100/st->rx_all_count : 0); + len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%d\t(%d%%)\n", + st->rxerr_decrypt, + st->rx_all_count > 0 ? + st->rxerr_decrypt*100/st->rx_all_count : 0); + len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%d\t(%d%%)\n", + st->rxerr_mic, + st->rx_all_count > 0 ? + st->rxerr_mic*100/st->rx_all_count : 0); + len += snprintf(buf+len, sizeof(buf)-len, "process\t%d\t(%d%%)\n", + st->rxerr_proc, + st->rx_all_count > 0 ? + st->rxerr_proc*100/st->rx_all_count : 0); + len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%d\t(%d%%)\n", + st->rxerr_jumbo, + st->rx_all_count > 0 ? + st->rxerr_jumbo*100/st->rx_all_count : 0); + len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n", + st->rx_all_count); + + len += snprintf(buf+len, sizeof(buf)-len, + "\nTX\n---------------------\n"); + len += snprintf(buf+len, sizeof(buf)-len, "retry\t%d\t(%d%%)\n", + st->txerr_retry, + st->tx_all_count > 0 ? + st->txerr_retry*100/st->tx_all_count : 0); + len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", + st->txerr_fifo, + st->tx_all_count > 0 ? + st->txerr_fifo*100/st->tx_all_count : 0); + len += snprintf(buf+len, sizeof(buf)-len, "filter\t%d\t(%d%%)\n", + st->txerr_filt, + st->tx_all_count > 0 ? + st->txerr_filt*100/st->tx_all_count : 0); + len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n", + st->tx_all_count); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_frameerrors(struct file *file, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + struct ath5k_statistics *st = &sc->stats; + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; + + if (strncmp(buf, "clear", 5) == 0) { + st->rxerr_crc = 0; + st->rxerr_phy = 0; + st->rxerr_fifo = 0; + st->rxerr_decrypt = 0; + st->rxerr_mic = 0; + st->rxerr_proc = 0; + st->rxerr_jumbo = 0; + st->rx_all_count = 0; + st->txerr_retry = 0; + st->txerr_fifo = 0; + st->txerr_filt = 0; + st->tx_all_count = 0; + printk(KERN_INFO "ath5k debug: cleared frameerrors stats\n"); + } + return count; +} + +static const struct file_operations fops_frameerrors = { + .read = read_file_frameerrors, + .write = write_file_frameerrors, + .open = ath5k_debugfs_open, + .owner = THIS_MODULE, +}; + + /* init */ void @@ -498,6 +598,11 @@ ath5k_debug_init_device(struct ath5k_softc *sc) sc->debug.debugfs_antenna = debugfs_create_file("antenna", S_IWUSR | S_IRUSR, sc->debug.debugfs_phydir, sc, &fops_antenna); + + sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors", + S_IWUSR | S_IRUSR, + sc->debug.debugfs_phydir, sc, + &fops_frameerrors); } void @@ -514,6 +619,7 @@ ath5k_debug_finish_device(struct ath5k_softc *sc) debugfs_remove(sc->debug.debugfs_beacon); debugfs_remove(sc->debug.debugfs_reset); debugfs_remove(sc->debug.debugfs_antenna); + debugfs_remove(sc->debug.debugfs_frameerrors); debugfs_remove(sc->debug.debugfs_phydir); } diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index 018612711045..da24ff52e274 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h @@ -75,6 +75,7 @@ struct ath5k_dbg_info { struct dentry *debugfs_beacon; struct dentry *debugfs_reset; struct dentry *debugfs_antenna; + struct dentry *debugfs_frameerrors; }; /** -- cgit v1.2.3 From 49a85d211a63ad1d565842ebc535c5168d85d86a Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Tue, 9 Mar 2010 16:56:15 +0900 Subject: ath5k: IQ calibration for AR5211 is slightly different according to the HAL sources the calculation of the Q value is slightly different for AR5211 chips. i couldn't test this since IQ calibration never finishes on older parts. this is a different problem... Signed-off-by: Bruno Randolf Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/phy.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 5aee85f27c0e..20d562b07c95 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1391,7 +1391,11 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, } i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; - q_coffd = q_pwr >> 7; + + if (ah->ah_version == AR5K_AR5211) + q_coffd = q_pwr >> 6; + else + q_coffd = q_pwr >> 7; /* No correction */ if (i_coffd == 0 || q_coffd == 0) @@ -1405,7 +1409,10 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, if (i_coff < -32) i_coff = -32; - q_coff = (((s32)i_pwr / q_coffd) - 128); + if (ah->ah_version == AR5K_AR5211) + q_coff = (i_pwr / q_coffd) - 64; + else + q_coff = (i_pwr / q_coffd) - 128; /* Boundary check */ if (q_coff > 15) -- cgit v1.2.3 From 687c8ff12df6b469c662a6cc288ea35989ee0704 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Tue, 9 Mar 2010 16:56:21 +0900 Subject: ath5k: Minor EEPROM documentation updates Here are some minor updates for EEPROM, mostly documentation and some small fixes which have no effect at the moment. - fixed_bias is not available for B mode. - AR5K_EEPROM_[RT]X_CHAIN_DIS is 3 bit. this is MIMO and will not be used in ath5k, but just to be correct. - AR5K_EEPROM_JAP_MID_EN added, and shift of following flags adapted. - added some documentation for EEPROM values and some comments. Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/eeprom.c | 4 +- drivers/net/wireless/ath/ath5k/eeprom.h | 85 +++++++++++++++++++++++++-------- drivers/net/wireless/ath/ath5k/reg.h | 2 +- 3 files changed, 68 insertions(+), 23 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 6a3f4da7fb48..86654b9e1092 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -329,7 +329,8 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, ee->ee_x_gain[mode] = (val >> 1) & 0xf; ee->ee_xpd[mode] = val & 0x1; - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 && + mode != AR5K_EEPROM_MODE_11B) ee->ee_fixed_bias[mode] = (val >> 13) & 0x1; if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) { @@ -339,6 +340,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, if (mode == AR5K_EEPROM_MODE_11A) ee->ee_xr_power[mode] = val & 0x3f; else { + /* b_DB_11[bg] and b_OB_11[bg] */ ee->ee_ob[mode][0] = val & 0x7; ee->ee_db[mode][0] = (val >> 3) & 0x7; } diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 1a65683e8c16..c4a6d5f26af4 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -75,9 +75,9 @@ #define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1) #define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1) #define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) -#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */ -#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */ -#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) +#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz */ +#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for < 2W power consumption */ +#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) /* Device type (1 Cardbus, 2 PCI, 3 MiniPCI, 4 AP) */ #define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ #define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */ @@ -98,7 +98,7 @@ #define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5) #define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) -#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) +#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) /* has 32KHz crystal for sleep mode */ #define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1) #define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6) @@ -111,26 +111,27 @@ #define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8) #define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff) -#define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3) -#define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3) +#define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3) /* modes supported by radio 0 (bit 1: G, bit 2: A) */ +#define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3) /* modes supported by radio 1 (bit 1: G, bit 2: A) */ #define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9) -#define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1) -#define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1) -#define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1) -#define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1) -#define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf) -#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) -#define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf) +#define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1) /* disable compression */ +#define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1) /* disable AES */ +#define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1) /* disable fast frames */ +#define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1) /* disable bursting */ +#define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf) /* max number of QCUs. defaults to 10 */ +#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) /* enable heayy clipping */ +#define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf) /* key cache size. defaults to 128 */ #define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10) -#define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x8) -#define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x8) -#define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1) -#define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1) -#define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1) -#define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 9) & 0x1) -#define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 10) & 0x1) +#define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x7) /* MIMO chains disabled for TX bitmask */ +#define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x7) /* MIMO chains disabled for RX bitmask */ +#define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1) /* 5.47-5.7GHz supported */ +#define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1) /* Japan UNII1 band (5.15-5.25GHz) on even channels (5180, 5200, 5220, 5240) supported */ +#define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1) /* Japan UNII2 band (5.25-5.35GHz) supported */ +#define AR5K_EEPROM_JAP_MID_EN (((_v) >> 9) & 0x1) /* Japan band from 5.47-5.7GHz supported */ +#define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 10) & 0x1) /* Japan UNII2 band (5.15-5.25GHz) on odd channels (5170, 5190, 5210, 5230) supported */ +#define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 11) & 0x1) /* Japan A mode enabled (using even channels) */ /* calibration settings */ #define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4) @@ -386,7 +387,49 @@ struct ath5k_edge_power { bool flag; }; -/* EEPROM calibration data */ +/** + * struct ath5k_eeprom_info - EEPROM calibration data + * + * @ee_regdomain: ath/regd.c takes care of COUNTRY_ERD and WORLDWIDE_ROAMING + * flags + * @ee_ant_gain: Antenna gain in 0.5dB steps signed [5211 only?] + * @ee_cck_ofdm_gain_delta: difference in gainF to output the same power for + * OFDM and CCK packets + * @ee_cck_ofdm_power_delta: power difference between OFDM (6Mbps) and CCK + * (11Mbps) rate in G mode. 0.1dB steps + * @ee_scaled_cck_delta: for Japan Channel 14: 0.1dB resolution + * + * @ee_i_cal: Initial I coefficient to correct I/Q mismatch in the receive path + * @ee_q_cal: Initial Q coefficient to correct I/Q mismatch in the receive path + * @ee_fixed_bias: use ee_ob and ee_db settings or use automatic control + * @ee_switch_settling: RX/TX Switch settling time + * @ee_atn_tx_rx: Difference in attenuation between TX and RX in 1dB steps + * @ee_ant_control: Antenna Control Settings + * @ee_ob: Bias current for Output stage of PA + * B/G mode: Index [0] is used for AR2112/5112, otherwise [1] + * A mode: [0] 5.15-5.25 [1] 5.25-5.50 [2] 5.50-5.70 [3] 5.70-5.85 GHz + * @ee_db: Bias current for Output stage of PA. see @ee_ob + * @ee_tx_end2xlna_enable: Time difference from when BB finishes sending a frame + * to when the external LNA is activated + * @ee_tx_end2xpa_disable: Time difference from when BB finishes sending a frame + * to when the external PA switch is deactivated + * @ee_tx_frm2xpa_enable: Time difference from when MAC sends frame to when + * external PA switch is activated + * @ee_thr_62: Clear Channel Assessment (CCA) sensitivity + * (IEEE802.11a section 17.3.10.5 ) + * @ee_xlna_gain: Total gain of the LNA (information only) + * @ee_xpd: Use external (1) or internal power detector + * @ee_x_gain: Gain for external power detector output (differences in EEMAP + * versions!) + * @ee_i_gain: Initial gain value after reset + * @ee_margin_tx_rx: Margin in dB when final attenuation stage should be used + * + * @ee_false_detect: Backoff in Sensitivity (dB) on channels with spur signals + * @ee_noise_floor_thr: Noise floor threshold in 1dB steps + * @ee_adc_desired_size: Desired amplitude for ADC, used by AGC; in 0.5 dB steps + * @ee_pga_desired_size: Desired output of PGA (for BB gain) in 0.5 dB steps + * @ee_pd_gain_overlap: PD ADC curves need to overlap in 0.5dB steps (ee_map>=2) + */ struct ath5k_eeprom_info { /* Header information */ diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 4cb9c5df9f46..f325e664065a 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -1974,7 +1974,7 @@ #define AR5K_PHY_SETTLING 0x9844 /* Register Address */ #define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */ #define AR5K_PHY_SETTLING_AGC_S 0 -#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */ +#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settling time */ #define AR5K_PHY_SETTLING_SWITCH_S 7 /* -- cgit v1.2.3 From 7c3c76a82f3a6d52bbeabf48dd32109cc951a7cf Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Wed, 10 Mar 2010 13:22:31 +0200 Subject: wl1271: Changed wl1271_sdio to be selectable only on ARM As wl1271_sdio implementation depends on ARM GPIO impelementation it is not directly usable on other architectures at the moment. Added ARM dependency to kernel configuration option. Reported-by: Stephen Rothwell Signed-off-by: Teemu Paasikivi Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 2f6733526f7f..337fc7bec5a5 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig @@ -53,7 +53,7 @@ config WL1271 unsure. config WL1271_SPI - tristate "TI wl1251 SPI support" + tristate "TI wl1271 SPI support" depends on WL1271 && SPI_MASTER ---help--- This module adds support for the SPI interface of adapters using @@ -65,7 +65,7 @@ config WL1271_SPI config WL1271_SDIO tristate "TI wl1271 SDIO support" - depends on WL1271 && MMC + depends on WL1271 && MMC && ARM ---help--- This module adds support for the SDIO interface of adapters using TI wl1271 chipset. Select this if your platform is using -- cgit v1.2.3 From d969847c2202f82b3f6755d16909925e64e354e5 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 1 Mar 2010 13:32:11 +0100 Subject: ath9k: fix rate control tx status handling for A-MPDU Currently the rate control tx status update gets called for every subframe of an A-MPDU, and ath9k marks the frame with the relevant status update with an internal flag. This not suitable for rate control algorithms using the standard mac80211 rate control API, so fix this by using IEEE80211_TX_STAT_AMPDU for marking the correct frames that should be processed. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 8 ++++++-- drivers/net/wireless/ath/ath9k/rc.h | 1 - drivers/net/wireless/ath/ath9k/xmit.c | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 0e79e58cf4c9..3c4b5d2d9e16 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1226,8 +1226,12 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, long_retry = rate->count - 1; } - if (!priv_sta || !ieee80211_is_data(fc) || - !(tx_info->pad[0] & ATH_TX_INFO_UPDATE_RC)) + if (!priv_sta || !ieee80211_is_data(fc)) + return; + + /* This packet was aggregated but doesn't carry status info */ + if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && + !(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) return; if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 4f6d6fd442f4..f4818e4fa4b0 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -172,7 +172,6 @@ struct ath_rate_priv { #define ATH_TX_INFO_FRAME_TYPE_INTERNAL (1 << 0) #define ATH_TX_INFO_FRAME_TYPE_PAUSE (1 << 1) -#define ATH_TX_INFO_UPDATE_RC (1 << 2) #define ATH_TX_INFO_XRETRY (1 << 3) #define ATH_TX_INFO_UNDERRUN (1 << 4) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index b2c8207f7bc1..8359362fc51c 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1947,10 +1947,10 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, tx_rateindex = ds->ds_txstat.ts_rateindex; WARN_ON(tx_rateindex >= hw->max_rates); - if (update_rc) - tx_info->pad[0] |= ATH_TX_INFO_UPDATE_RC; if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; + if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) + tx_info->flags |= IEEE80211_TX_STAT_AMPDU; if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { -- cgit v1.2.3 From e9f08381cb117d66ad14474228ce02a27d6f62ae Mon Sep 17 00:00:00 2001 From: Andrew Blaich Date: Mon, 1 Mar 2010 10:30:40 -0500 Subject: ath5k: fixing retries in ath5k_hw_setup_4word_tx_desc The rate control algorithm, default is Minstrel for ath5k, determines the number of retries to use for each rate. However, there exists in ath5k_hw_setup_4word_tx_desc (which is called for AR5212 like devices) a set number of retries defined by AR5K_TUNE_HWTXTRIES. The set number of tries is added to the tx_tries0 variable setup by the rate control algorithm. This changes the number of retries the rate control algorithm considers necessary. By removing the AR5K_TUNE_HWTXTRIES from the retry calculation the rate control algorithm is given control over the number of retries. Signed-off-by: Andrew Blaich Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 1 - drivers/net/wireless/ath/ath5k/desc.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 5898e2e50a70..365eccd777a3 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -202,7 +202,6 @@ #define AR5K_TUNE_MAX_TXPOWER 63 #define AR5K_TUNE_DEFAULT_TXPOWER 25 #define AR5K_TUNE_TPC_TXPOWER false -#define AR5K_TUNE_HWTXTRIES 4 #define AR5K_INIT_CARR_SENSE_EN 1 diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index aebb31f2834b..9d920fb14d5d 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -231,7 +231,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); tx_ctl->tx_control_1 |= AR5K_REG_SM(type, AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); - tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES, + tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; -- cgit v1.2.3 From 3bc819e8d4dd385e481137b2dbe3b7d23314319e Mon Sep 17 00:00:00 2001 From: matthieu castet Date: Sun, 28 Feb 2010 15:31:21 +0100 Subject: airo : fix printing status info For some status, reason is encoded in the low byte, but airo_print_status forgot tp mask low byte in status parsing. This make it only work when reason is 0. Signed-off-by: Matthieu CASTET Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index dc5018a6d9ed..2859a355ef99 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -3193,19 +3193,26 @@ static void airo_print_status(const char *devname, u16 status) { u8 reason = status & 0xFF; - switch (status) { + switch (status & 0xFF00) { case STAT_NOBEACON: - airo_print_dbg(devname, "link lost (missed beacons)"); - break; - case STAT_MAXRETRIES: - case STAT_MAXARL: - airo_print_dbg(devname, "link lost (max retries)"); - break; - case STAT_FORCELOSS: - airo_print_dbg(devname, "link lost (local choice)"); - break; - case STAT_TSFSYNC: - airo_print_dbg(devname, "link lost (TSF sync lost)"); + switch (status) { + case STAT_NOBEACON: + airo_print_dbg(devname, "link lost (missed beacons)"); + break; + case STAT_MAXRETRIES: + case STAT_MAXARL: + airo_print_dbg(devname, "link lost (max retries)"); + break; + case STAT_FORCELOSS: + airo_print_dbg(devname, "link lost (local choice)"); + break; + case STAT_TSFSYNC: + airo_print_dbg(devname, "link lost (TSF sync lost)"); + break; + default: + airo_print_dbg(devname, "unknow status %x\n", status); + break; + } break; case STAT_DEAUTH: airo_print_dbg(devname, "deauthenticated (reason: %d)", reason); @@ -3221,7 +3228,11 @@ static void airo_print_status(const char *devname, u16 status) airo_print_dbg(devname, "authentication failed (reason: %d)", reason); break; + case STAT_ASSOC: + case STAT_REASSOC: + break; default: + airo_print_dbg(devname, "unknow status %x\n", status); break; } } -- cgit v1.2.3 From f3a981ffddcc9671505b85ead976630878116434 Mon Sep 17 00:00:00 2001 From: matthieu castet Date: Sun, 28 Feb 2010 15:42:54 +0100 Subject: airo : Print of firmware version For the firmware version 5.30.17 the log file shows: Firmware version 5.30.11 The variable softSubVer is binary. Signed-off-by: Matthieu CASTET Signed-off-by: Jose Alonso Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 2859a355ef99..a441aad922c2 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -2876,7 +2876,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, ai->wep_capable = (cap_rid.softCap & cpu_to_le16(0x02)) ? 1 : 0; ai->max_wep_idx = (cap_rid.softCap & cpu_to_le16(0x80)) ? 3 : 0; - airo_print_info(dev->name, "Firmware version %x.%x.%02x", + airo_print_info(dev->name, "Firmware version %x.%x.%02d", ((le16_to_cpu(cap_rid.softVer) >> 8) & 0xF), (le16_to_cpu(cap_rid.softVer) & 0xFF), le16_to_cpu(cap_rid.softSubVer)); -- cgit v1.2.3 From 6fe10e760bcde8c29b84ad16f54015af5ef59ff5 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 10 Mar 2010 11:08:48 -0500 Subject: ath5k: remove some dead functions "ath5k: remove stale function declarations, make some functions static" commented-out some unused functions. This removes them. Signed-off-by: John W. Linville Acked-by: Bob Copeland --- drivers/net/wireless/ath/ath5k/pcu.c | 82 ------------------------------------ drivers/net/wireless/ath/ath5k/phy.c | 12 ------ drivers/net/wireless/ath/ath5k/qcu.c | 19 --------- 3 files changed, 113 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index c813046b3540..9247123c9b6d 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -178,21 +178,6 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) * ACK/CTS Timeouts * \******************/ -#if 0 -/** - * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec - * - * @ah: The &struct ath5k_hw - */ -unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - - return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, - AR5K_TIME_OUT), AR5K_TIME_OUT_ACK)); -} -#endif - /** * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU * @@ -212,20 +197,6 @@ static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) return 0; } -#if 0 -/** - * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec - * - * @ah: The &struct ath5k_hw - */ -unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, - AR5K_TIME_OUT), AR5K_TIME_OUT_CTS)); -} -#endif - /** * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU * @@ -455,44 +426,6 @@ void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); } -#if 0 -/* - * Set multicast filter by index - */ -int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index) -{ - - ATH5K_TRACE(ah->ah_sc); - if (index >= 64) - return -EINVAL; - else if (index >= 32) - AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1, - (1 << (index - 32))); - else - AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); - - return 0; -} - -/* - * Clear Multicast filter by index - */ -int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index) -{ - - ATH5K_TRACE(ah->ah_sc); - if (index >= 64) - return -EINVAL; - else if (index >= 32) - AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1, - (1 << (index - 32))); - else - AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); - - return 0; -} -#endif - /** * ath5k_hw_get_rx_filter - Get current rx filter * @@ -964,21 +897,6 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) return 0; } -#if 0 -/* - * Check if a table entry is valid - */ -int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry) -{ - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); - - /* Check the validation flag at the end of the entry */ - return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) & - AR5K_KEYTABLE_VALID; -} -#endif - static int ath5k_keycache_type(const struct ieee80211_key_conf *key) { diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 20d562b07c95..e291bfbd6e68 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1781,18 +1781,6 @@ ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); } -#if 0 -unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - - if (ah->ah_version != AR5K_AR5210) - return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA) & 0x7; - - return false; /*XXX: What do we return for 5210 ?*/ -} -#endif - /* * Enable/disable fast rx antenna diversity */ diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index d9cab7c3cff7..f5831da33f7b 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -516,25 +516,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) return 0; } -#if 0 -/* - * Get slot time from DCU - */ -unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) -{ - unsigned int slot_time_clock; - - ATH5K_TRACE(ah->ah_sc); - - if (ah->ah_version == AR5K_AR5210) - slot_time_clock = ath5k_hw_reg_read(ah, AR5K_SLOT_TIME); - else - slot_time_clock = ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT); - - return ath5k_hw_clocktoh(ah, slot_time_clock & 0xffff); -} -#endif - /* * Set slot time on DCU */ -- cgit v1.2.3 From a93b7aec657e3bd01ef043dff46d3c27dba26bb3 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 10 Mar 2010 11:08:49 -0500 Subject: ath5k: remove dead source in ath5k_combine_linear_pcdac_curves This code was commented-out when it was added about a year ago and remains unchanged -- seems as if we don't need it... Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/phy.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index e291bfbd6e68..384347b0c9f0 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -2435,19 +2435,6 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min, pcdac_tmp = pcdac_high_pwr; edge_flag = 0x40; -#if 0 - /* If both min and max power limits are in lower - * power curve's range, only use the low power curve. - * TODO: min/max levels are related to target - * power values requested from driver/user - * XXX: Is this really needed ? */ - if (min_pwr < table_max[1] && - max_pwr < table_max[1]) { - edge_flag = 0; - pcdac_tmp = pcdac_low_pwr; - max_pwr_idx = (table_max[1] - table_min[1])/2; - } -#endif } else { pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */ pcdac_high_pwr = ah->ah_txpower.tmpL[0]; -- cgit v1.2.3 From 200763bb7503102aa364658e2b32cb2463a08d91 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 10 Mar 2010 11:08:50 -0500 Subject: ath5k: remove unused beacon timer code Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 28 ----- drivers/net/wireless/ath/ath5k/pcu.c | 197 --------------------------------- 2 files changed, 225 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 365eccd777a3..1d7491c85460 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -613,28 +613,6 @@ struct ath5k_rx_status { #define AR5K_BEACON_ENA 0x00800000 /*enable beacon xmit*/ #define AR5K_BEACON_RESET_TSF 0x01000000 /*force a TSF reset*/ -#if 0 -/** - * struct ath5k_beacon_state - Per-station beacon timer state. - * @bs_interval: in TU's, can also include the above flags - * @bs_cfp_max_duration: if non-zero hw is setup to coexist with a - * Point Coordination Function capable AP - */ -struct ath5k_beacon_state { - u32 bs_next_beacon; - u32 bs_next_dtim; - u32 bs_interval; - u8 bs_dtim_period; - u8 bs_cfp_period; - u16 bs_cfp_max_duration; - u16 bs_cfp_du_remain; - u16 bs_tim_offset; - u16 bs_sleep_duration; - u16 bs_bmiss_threshold; - u32 bs_cfp_next; -}; -#endif - /* * TSF to TU conversion: @@ -1212,12 +1190,6 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); void ath5k_hw_reset_tsf(struct ath5k_hw *ah); void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); -#if 0 -int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, - const struct ath5k_beacon_state *state); -void ath5k_hw_reset_beacon(struct ath5k_hw *ah); -int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr); -#endif /* ACK bit rate */ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); /* Clock rate related functions */ diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 9247123c9b6d..1b9fcb842167 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -648,203 +648,6 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) } -#if 0 -/* - * Set beacon timers - */ -int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, - const struct ath5k_beacon_state *state) -{ - u32 cfp_period, next_cfp, dtim, interval, next_beacon; - - /* - * TODO: should be changed through *state - * review struct ath5k_beacon_state struct - * - * XXX: These are used for cfp period bellow, are they - * ok ? Is it O.K. for tsf here to be 0 or should we use - * get_tsf ? - */ - u32 dtim_count = 0; /* XXX */ - u32 cfp_count = 0; /* XXX */ - u32 tsf = 0; /* XXX */ - - ATH5K_TRACE(ah->ah_sc); - /* Return on an invalid beacon state */ - if (state->bs_interval < 1) - return -EINVAL; - - interval = state->bs_interval; - dtim = state->bs_dtim_period; - - /* - * PCF support? - */ - if (state->bs_cfp_period > 0) { - /* - * Enable PCF mode and set the CFP - * (Contention Free Period) and timer registers - */ - cfp_period = state->bs_cfp_period * state->bs_dtim_period * - state->bs_interval; - next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) * - state->bs_interval; - - AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, - AR5K_STA_ID1_DEFAULT_ANTENNA | - AR5K_STA_ID1_PCF); - ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD); - ath5k_hw_reg_write(ah, state->bs_cfp_max_duration, - AR5K_CFP_DUR); - ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period : - next_cfp)) << 3, AR5K_TIMER2); - } else { - /* Disable PCF mode */ - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, - AR5K_STA_ID1_DEFAULT_ANTENNA | - AR5K_STA_ID1_PCF); - } - - /* - * Enable the beacon timer register - */ - ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0); - - /* - * Start the beacon timers - */ - ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) & - ~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) | - AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0, - AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval, - AR5K_BEACON_PERIOD), AR5K_BEACON); - - /* - * Write new beacon miss threshold, if it appears to be valid - * XXX: Figure out right values for min <= bs_bmiss_threshold <= max - * and return if its not in range. We can test this by reading value and - * setting value to a largest value and seeing which values register. - */ - - AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS, - state->bs_bmiss_threshold); - - /* - * Set sleep control register - * XXX: Didn't find this in 5210 code but since this register - * exists also in ar5k's 5210 headers i leave it as common code. - */ - AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR, - (state->bs_sleep_duration - 3) << 3); - - /* - * Set enhanced sleep registers on 5212 - */ - if (ah->ah_version == AR5K_AR5212) { - if (state->bs_sleep_duration > state->bs_interval && - roundup(state->bs_sleep_duration, interval) == - state->bs_sleep_duration) - interval = state->bs_sleep_duration; - - if (state->bs_sleep_duration > dtim && (dtim == 0 || - roundup(state->bs_sleep_duration, dtim) == - state->bs_sleep_duration)) - dtim = state->bs_sleep_duration; - - if (interval > dtim) - return -EINVAL; - - next_beacon = interval == dtim ? state->bs_next_dtim : - state->bs_next_beacon; - - ath5k_hw_reg_write(ah, - AR5K_REG_SM((state->bs_next_dtim - 3) << 3, - AR5K_SLEEP0_NEXT_DTIM) | - AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) | - AR5K_SLEEP0_ENH_SLEEP_EN | - AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0); - - ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3, - AR5K_SLEEP1_NEXT_TIM) | - AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1); - - ath5k_hw_reg_write(ah, - AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) | - AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2); - } - - return 0; -} - -/* - * Reset beacon timers - */ -void ath5k_hw_reset_beacon(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - /* - * Disable beacon timer - */ - ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); - - /* - * Disable some beacon register values - */ - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, - AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF); - ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON); -} - -/* - * Wait for beacon queue to finish - */ -int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) -{ - unsigned int i; - int ret; - - ATH5K_TRACE(ah->ah_sc); - - /* 5210 doesn't have QCU*/ - if (ah->ah_version == AR5K_AR5210) { - /* - * Wait for beaconn queue to finish by checking - * Control Register and Beacon Status Register. - */ - for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) { - if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F) - || - !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F)) - break; - udelay(10); - } - - /* Timeout... */ - if (i <= 0) { - /* - * Re-schedule the beacon queue - */ - ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1); - ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, - AR5K_BCR); - - return -EIO; - } - ret = 0; - } else { - /*5211/5212*/ - ret = ath5k_hw_register_timeout(ah, - AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON), - AR5K_QCU_STS_FRMPENDCNT, 0, false); - - if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON)) - return -EIO; - } - - return ret; -} -#endif - /*********************\ * Key table functions * -- cgit v1.2.3 From 819cf15e7cde0a1b0fa4f831478f792434f55679 Mon Sep 17 00:00:00 2001 From: Stewart Malik Date: Thu, 11 Mar 2010 20:28:29 +1030 Subject: DRIVER: Libertas: Fixed coding style in rx.c Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/rx.c | 50 +++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 2daf8ffdb7e1..7a867e31ca5a 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -38,10 +38,10 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, struct sk_buff *skb); /** - * @brief This function computes the avgSNR . + * @brief This function computes the avgSNR . * - * @param priv A pointer to struct lbs_private structure - * @return avgSNR + * @param priv A pointer to struct lbs_private structure + * @return avgSNR */ static u8 lbs_getavgsnr(struct lbs_private *priv) { @@ -56,10 +56,10 @@ static u8 lbs_getavgsnr(struct lbs_private *priv) } /** - * @brief This function computes the AvgNF + * @brief This function computes the AvgNF * - * @param priv A pointer to struct lbs_private structure - * @return AvgNF + * @param priv A pointer to struct lbs_private structure + * @return AvgNF */ static u8 lbs_getavgnf(struct lbs_private *priv) { @@ -74,11 +74,11 @@ static u8 lbs_getavgnf(struct lbs_private *priv) } /** - * @brief This function save the raw SNR/NF to our internel buffer + * @brief This function save the raw SNR/NF to our internel buffer * - * @param priv A pointer to struct lbs_private structure - * @param prxpd A pointer to rxpd structure of received packet - * @return n/a + * @param priv A pointer to struct lbs_private structure + * @param prxpd A pointer to rxpd structure of received packet + * @return n/a */ static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd) { @@ -93,11 +93,11 @@ static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd) } /** - * @brief This function computes the RSSI in received packet. + * @brief This function computes the RSSI in received packet. * - * @param priv A pointer to struct lbs_private structure - * @param prxpd A pointer to rxpd structure of received packet - * @return n/a + * @param priv A pointer to struct lbs_private structure + * @param prxpd A pointer to rxpd structure of received packet + * @return n/a */ static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd) { @@ -134,9 +134,9 @@ static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd) * @brief This function processes received packet and forwards it * to kernel/upper layer * - * @param priv A pointer to struct lbs_private - * @param skb A pointer to skb which includes the received packet - * @return 0 or -1 + * @param priv A pointer to struct lbs_private + * @param skb A pointer to skb which includes the received packet + * @return 0 or -1 */ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) { @@ -196,7 +196,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) * before the snap_type. */ p_ethhdr = (struct ethhdr *) - ((u8 *) & p_rx_pkt->eth803_hdr + ((u8 *) &p_rx_pkt->eth803_hdr + sizeof(p_rx_pkt->eth803_hdr) + sizeof(p_rx_pkt->rfc1042_hdr) - sizeof(p_rx_pkt->eth803_hdr.dest_addr) - sizeof(p_rx_pkt->eth803_hdr.src_addr) @@ -213,7 +213,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) hdrchop = (u8 *)p_ethhdr - (u8 *)p_rx_pd; } else { lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP", - (u8 *) & p_rx_pkt->rfc1042_hdr, + (u8 *) &p_rx_pkt->rfc1042_hdr, sizeof(p_rx_pkt->rfc1042_hdr)); /* Chop off the rxpd */ @@ -254,8 +254,8 @@ EXPORT_SYMBOL_GPL(lbs_process_rxed_packet); * @brief This function converts Tx/Rx rates from the Marvell WLAN format * (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s) * - * @param rate Input rate - * @return Output Rate (0 if invalid) + * @param rate Input rate + * @return Output Rate (0 if invalid) */ static u8 convert_mv_rate_to_radiotap(u8 rate) { @@ -294,9 +294,9 @@ static u8 convert_mv_rate_to_radiotap(u8 rate) * @brief This function processes a received 802.11 packet and forwards it * to kernel/upper layer * - * @param priv A pointer to struct lbs_private - * @param skb A pointer to skb which includes the received packet - * @return 0 or -1 + * @param priv A pointer to struct lbs_private + * @param skb A pointer to skb which includes the received packet + * @return 0 or -1 */ static int process_rxed_802_11_packet(struct lbs_private *priv, struct sk_buff *skb) @@ -313,7 +313,7 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, p_rx_pkt = (struct rx80211packethdr *) skb->data; prxpd = &p_rx_pkt->rx_pd; - // lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100)); + /* lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100)); */ if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) { lbs_deb_rx("rx err: frame received with bad length\n"); -- cgit v1.2.3 From 3c9cb9c38a1368b1e3f187f23c1a56883ec656c2 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Fri, 12 Mar 2010 12:28:41 +0200 Subject: wl1251: make local symbols static Make local functions and data static, also constify some structures. While at it, clean up unneeded includes. Signed-off-by: Grazvydas Ignotas Cc: Bob Copeland Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_sdio.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c index 9423f22bdced..cfca232dc8cb 100644 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c @@ -20,20 +20,11 @@ * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com) */ #include -#include #include -#include #include #include -#include #include "wl1251.h" -#include "wl12xx_80211.h" -#include "wl1251_reg.h" -#include "wl1251_ps.h" -#include "wl1251_io.h" -#include "wl1251_tx.h" -#include "wl1251_debugfs.h" #ifndef SDIO_VENDOR_ID_TI #define SDIO_VENDOR_ID_TI 0x104c @@ -65,7 +56,8 @@ static const struct sdio_device_id wl1251_devices[] = { MODULE_DEVICE_TABLE(sdio, wl1251_devices); -void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len) +static void wl1251_sdio_read(struct wl1251 *wl, int addr, + void *buf, size_t len) { int ret; struct sdio_func *func = wl_to_func(wl); @@ -77,7 +69,8 @@ void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len) sdio_release_host(func); } -void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len) +static void wl1251_sdio_write(struct wl1251 *wl, int addr, + void *buf, size_t len) { int ret; struct sdio_func *func = wl_to_func(wl); @@ -89,7 +82,7 @@ void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len) sdio_release_host(func); } -void wl1251_sdio_reset(struct wl1251 *wl) +static void wl1251_sdio_reset(struct wl1251 *wl) { } @@ -111,11 +104,11 @@ static void wl1251_sdio_disable_irq(struct wl1251 *wl) sdio_release_host(func); } -void wl1251_sdio_set_power(bool enable) +static void wl1251_sdio_set_power(bool enable) { } -struct wl1251_if_operations wl1251_sdio_ops = { +static const struct wl1251_if_operations wl1251_sdio_ops = { .read = wl1251_sdio_read, .write = wl1251_sdio_write, .reset = wl1251_sdio_reset, @@ -123,7 +116,8 @@ struct wl1251_if_operations wl1251_sdio_ops = { .disable_irq = wl1251_sdio_disable_irq, }; -int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) +static int wl1251_sdio_probe(struct sdio_func *func, + const struct sdio_device_id *id) { int ret; struct wl1251 *wl; -- cgit v1.2.3 From 3f9e750d130b4a4d9f8226642b46ed17d8357f40 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Thu, 11 Mar 2010 17:44:57 +0200 Subject: wl1251: fix ELP_CTRL register accesses when using SDIO For some unknown reason ELP_CTRL can't be accesed using sdio_memcpy_* functions (any attemts to do so result in timeouts): wl1251: ERROR sdio write failed (-110) wl1251: ERROR sdio read failed (-110) wl1251: WARNING WLAN not ready To fix this, add special IO functions for ELP_CTRL access that are using sdio_readb/sdio_writeb. Similar handling is done in TI reference driver from Android code drop. Signed-off-by: Grazvydas Ignotas Cc: Bob Copeland Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251.h | 2 ++ drivers/net/wireless/wl12xx/wl1251_io.h | 20 ++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1251_main.c | 4 ++-- drivers/net/wireless/wl12xx/wl1251_ps.c | 8 ++++---- drivers/net/wireless/wl12xx/wl1251_sdio.c | 28 ++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index 37c61c19cae5..4f5f02a26e62 100644 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ b/drivers/net/wireless/wl12xx/wl1251.h @@ -256,6 +256,8 @@ struct wl1251_debugfs { struct wl1251_if_operations { void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len); void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len); + void (*read_elp)(struct wl1251 *wl, int addr, u32 *val); + void (*write_elp)(struct wl1251 *wl, int addr, u32 val); void (*reset)(struct wl1251 *wl); void (*enable_irq)(struct wl1251 *wl); void (*disable_irq)(struct wl1251 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl12xx/wl1251_io.h index b89d2ac62efb..c545e9d5f512 100644 --- a/drivers/net/wireless/wl12xx/wl1251_io.h +++ b/drivers/net/wireless/wl12xx/wl1251_io.h @@ -48,6 +48,26 @@ static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val) wl->if_ops->write(wl, addr, &val, sizeof(u32)); } +static inline u32 wl1251_read_elp(struct wl1251 *wl, int addr) +{ + u32 response; + + if (wl->if_ops->read_elp) + wl->if_ops->read_elp(wl, addr, &response); + else + wl->if_ops->read(wl, addr, &response, sizeof(u32)); + + return response; +} + +static inline void wl1251_write_elp(struct wl1251 *wl, int addr, u32 val) +{ + if (wl->if_ops->write_elp) + wl->if_ops->write_elp(wl, addr, val); + else + wl->if_ops->write(wl, addr, &val, sizeof(u32)); +} + /* Memory target IO, address is translated to partition 0 */ void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len); void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len); diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 24ae6a360ac8..0155653b7105 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -146,8 +146,8 @@ static void wl1251_fw_wakeup(struct wl1251 *wl) u32 elp_reg; elp_reg = ELPCTRL_WAKE_UP; - wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); - elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); + wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); + elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); if (!(elp_reg & ELPCTRL_WLAN_READY)) wl1251_warning("WLAN not ready"); diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c index 851dfb65e474..b55cb2bd459a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c +++ b/drivers/net/wireless/wl12xx/wl1251_ps.c @@ -45,7 +45,7 @@ void wl1251_elp_work(struct work_struct *work) goto out; wl1251_debug(DEBUG_PSM, "chip to elp"); - wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); + wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); wl->elp = true; out: @@ -79,9 +79,9 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) start = jiffies; timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); - wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); + wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); - elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); + elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); /* * FIXME: we should wait for irq from chip but, as a temporary @@ -93,7 +93,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) return -ETIMEDOUT; } msleep(1); - elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); + elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); } wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c index cfca232dc8cb..2051ef06e9ec 100644 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c @@ -82,6 +82,32 @@ static void wl1251_sdio_write(struct wl1251 *wl, int addr, sdio_release_host(func); } +static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val) +{ + int ret = 0; + struct sdio_func *func = wl_to_func(wl); + + sdio_claim_host(func); + *val = sdio_readb(func, addr, &ret); + sdio_release_host(func); + + if (ret) + wl1251_error("sdio_readb failed (%d)", ret); +} + +static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val) +{ + int ret = 0; + struct sdio_func *func = wl_to_func(wl); + + sdio_claim_host(func); + sdio_writeb(func, val, addr, &ret); + sdio_release_host(func); + + if (ret) + wl1251_error("sdio_writeb failed (%d)", ret); +} + static void wl1251_sdio_reset(struct wl1251 *wl) { } @@ -111,6 +137,8 @@ static void wl1251_sdio_set_power(bool enable) static const struct wl1251_if_operations wl1251_sdio_ops = { .read = wl1251_sdio_read, .write = wl1251_sdio_write, + .write_elp = wl1251_sdio_write_elp, + .read_elp = wl1251_sdio_read_elp, .reset = wl1251_sdio_reset, .enable_irq = wl1251_sdio_enable_irq, .disable_irq = wl1251_sdio_disable_irq, -- cgit v1.2.3 From 1e3f7ac81ef81f25d8d8d902b73d884f97e6aa21 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Thu, 11 Mar 2010 17:45:07 +0200 Subject: wl1251: reduce eeprom read wait time 4sec wait is way too pessimistic, TI driver uses 40ms here, and testing shows that is ebough, so let's also use that. While at it, add useful sounding comment from the TI driver. Signed-off-by: Grazvydas Ignotas Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_boot.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 28a808674080..acb334184d70 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c @@ -496,7 +496,8 @@ int wl1251_boot(struct wl1251 *wl) /* 2. start processing NVS file */ if (wl->use_eeprom) { wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR); - msleep(4000); + /* Wait for EEPROM NVS burst read to complete */ + msleep(40); wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM); } else { ret = wl1251_boot_upload_nvs(wl); -- cgit v1.2.3 From 484b4dd582867c6cfec3a1feb128d60af21c4978 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Thu, 11 Mar 2010 23:13:28 -0500 Subject: orinoco: disable support for prism chipset by default The hostap driver provides better support for Prism chipset. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/Kconfig | 13 ++++- drivers/net/wireless/orinoco/hw.c | 7 +++ drivers/net/wireless/orinoco/orinoco_cs.c | 79 ++++++++++++++++--------------- 3 files changed, 60 insertions(+), 39 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/orinoco/Kconfig b/drivers/net/wireless/orinoco/Kconfig index e2a2c18920aa..6116b546861d 100644 --- a/drivers/net/wireless/orinoco/Kconfig +++ b/drivers/net/wireless/orinoco/Kconfig @@ -27,6 +27,17 @@ config HERMES configure your card and that /etc/pcmcia/wireless.opts works : +config HERMES_PRISM + bool "Support Prism 2/2.5 chipset" + depends on HERMES + ---help--- + + Say Y to enable support for Prism 2 and 2.5 chipsets. These + chipsets are better handled by the hostap driver. This driver + would not support WPA or firmware download for Prism chipset. + + If you are not sure, say N. + config HERMES_CACHE_FW_ON_INIT bool "Cache Hermes firmware on driver initialisation" depends on HERMES @@ -86,7 +97,7 @@ config NORTEL_HERMES config PCI_HERMES tristate "Prism 2.5 PCI 802.11b adaptor support" - depends on PCI && HERMES + depends on PCI && HERMES && HERMES_PRISM help Enable support for PCI and mini-PCI 802.11b wireless NICs based on the Prism 2.5 chipset. These are true PCI cards, not the 802.11b diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index e6369242e49c..883b8f868626 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c @@ -262,6 +262,13 @@ int determine_fw_capabilities(struct orinoco_private *priv, if (fw_name) dev_info(dev, "Firmware determined as %s\n", fw_name); +#ifndef CONFIG_HERMES_PRISM + if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL) { + dev_err(dev, "Support for Prism chipset is not enabled\n"); + return -ENODEV; + } +#endif + return 0; } diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index 1d4ada188eda..fdc961379170 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -374,87 +374,90 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION "Pavel Roskin , et al)"; static struct pcmcia_device_id orinoco_cs_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */ - PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */ - PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */ PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */ - PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */ - PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */ PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */ PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */ PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */ - PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */ - PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */ PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */ PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */ PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0003), /* ARtem Onair Comcard 11 */ PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */ - PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */ - PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */ - PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */ - PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */ PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */ PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */ PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x3021), /* SpeedStream Wireless Adapter */ PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */ + PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), + PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f), + PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), + PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), + PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169), + PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb), + PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), + PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916), + PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3), + PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c), + PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077), + PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92), + PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a), + PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410), + PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3), + PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a), + PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767), + PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed), + PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), + PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26), + PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b), + PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e), +#ifdef CONFIG_HERMES_PRISM + /* Only entries that certainly identify Prism chipset */ + PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */ + PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */ + PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */ + PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */ + PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */ + PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */ + PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */ + PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */ + PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */ + PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */ + PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */ PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */ PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */ PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */ PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */ PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */ PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */ - PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9), - PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), + PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5), PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2), - PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f), - PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), - PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), - PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169), - PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb), - PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3), PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), - PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), + PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3), PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b), PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae), + PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146), PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac), PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab), - PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916), - PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146), - PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3), - PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c), - PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), - PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077), + PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9), PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77), PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf), - PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92), PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395), - PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a), - PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410), - PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3), PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01), - PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a), - PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1), PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1), - PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767), + PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1), PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6), - PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed), PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264), PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178), - PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), - PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26), - PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b), PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757), PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a), - PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e), PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092), PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2), PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b), PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39), +#endif PCMCIA_DEVICE_NULL, }; MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids); -- cgit v1.2.3 From 27ae60f8f7aac221b428422eecafddaa7aff9549 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Fri, 12 Mar 2010 00:01:22 -0500 Subject: ipw2x00: replace "ieee80211" with "libipw" where appropriate "ieee80211" was the old name of the common library for ipw2100 and ipw2200. It was renamed to "libipw", but some occurrences of the old name remained. Rename alloc_ieee80211() to alloc_libipw() and free_ieee80211() to free_libipw(). Adjust comments and label names. Change prefixes in diagnostic messages. Keep /proc/net/ieee80211 under the original name to avoid breaking user interface. Move the affected EXPORT_SYMBOL macros to their proper places. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2100.c | 10 +++++----- drivers/net/wireless/ipw2x00/ipw2200.c | 18 +++++++++--------- drivers/net/wireless/ipw2x00/libipw.h | 14 +++++++------- drivers/net/wireless/ipw2x00/libipw_module.c | 13 ++++++------- 4 files changed, 27 insertions(+), 28 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 9b72c45a7748..fe63bf21c67e 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -6102,7 +6102,7 @@ static const struct net_device_ops ipw2100_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -/* Look into using netdev destructor to shutdown ieee80211? */ +/* Look into using netdev destructor to shutdown libipw? */ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, void __iomem * base_addr, @@ -6112,7 +6112,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, struct ipw2100_priv *priv; struct net_device *dev; - dev = alloc_ieee80211(sizeof(struct ipw2100_priv), 0); + dev = alloc_libipw(sizeof(struct ipw2100_priv), 0); if (!dev) return NULL; priv = libipw_priv(dev); @@ -6425,7 +6425,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, sysfs_remove_group(&pci_dev->dev.kobj, &ipw2100_attribute_group); - free_ieee80211(dev, 0); + free_libipw(dev, 0); pci_set_drvdata(pci_dev, NULL); } @@ -6483,10 +6483,10 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev) if (dev->base_addr) iounmap((void __iomem *)dev->base_addr); - /* wiphy_unregister needs to be here, before free_ieee80211 */ + /* wiphy_unregister needs to be here, before free_libipw */ wiphy_unregister(priv->ieee->wdev.wiphy); kfree(priv->ieee->bg_band.channels); - free_ieee80211(dev, 0); + free_libipw(dev, 0); } pci_release_regions(pci_dev); diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 63c2a7ade5fb..d6edc2440128 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -11651,7 +11651,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv) if (priv->prom_net_dev) return -EPERM; - priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv), 1); + priv->prom_net_dev = alloc_libipw(sizeof(struct ipw_prom_priv), 1); if (priv->prom_net_dev == NULL) return -ENOMEM; @@ -11670,7 +11670,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv) rc = register_netdev(priv->prom_net_dev); if (rc) { - free_ieee80211(priv->prom_net_dev, 1); + free_libipw(priv->prom_net_dev, 1); priv->prom_net_dev = NULL; return rc; } @@ -11684,7 +11684,7 @@ static void ipw_prom_free(struct ipw_priv *priv) return; unregister_netdev(priv->prom_net_dev); - free_ieee80211(priv->prom_net_dev, 1); + free_libipw(priv->prom_net_dev, 1); priv->prom_net_dev = NULL; } @@ -11712,7 +11712,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, struct ipw_priv *priv; int i; - net_dev = alloc_ieee80211(sizeof(struct ipw_priv), 0); + net_dev = alloc_libipw(sizeof(struct ipw_priv), 0); if (net_dev == NULL) { err = -ENOMEM; goto out; @@ -11732,7 +11732,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, mutex_init(&priv->mutex); if (pci_enable_device(pdev)) { err = -ENODEV; - goto out_free_ieee80211; + goto out_free_libipw; } pci_set_master(pdev); @@ -11859,8 +11859,8 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, out_pci_disable_device: pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); - out_free_ieee80211: - free_ieee80211(priv->net_dev, 0); + out_free_libipw: + free_libipw(priv->net_dev, 0); out: return err; } @@ -11927,11 +11927,11 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); - /* wiphy_unregister needs to be here, before free_ieee80211 */ + /* wiphy_unregister needs to be here, before free_libipw */ wiphy_unregister(priv->ieee->wdev.wiphy); kfree(priv->ieee->a_band.channels); kfree(priv->ieee->bg_band.channels); - free_ieee80211(priv->net_dev, 0); + free_libipw(priv->net_dev, 0); free_firmware(); } diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h index bf45391172f3..9ac136b98bb3 100644 --- a/drivers/net/wireless/ipw2x00/libipw.h +++ b/drivers/net/wireless/ipw2x00/libipw.h @@ -64,7 +64,7 @@ extern u32 libipw_debug_level; #define LIBIPW_DEBUG(level, fmt, args...) \ do { if (libipw_debug_level & (level)) \ - printk(KERN_DEBUG "ieee80211: %c %s " fmt, \ + printk(KERN_DEBUG "libipw: %c %s " fmt, \ in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) static inline bool libipw_ratelimit_debug(u32 level) { @@ -116,8 +116,8 @@ static inline bool libipw_ratelimit_debug(u32 level) #define LIBIPW_DL_RX (1<<9) #define LIBIPW_DL_QOS (1<<31) -#define LIBIPW_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a) -#define LIBIPW_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a) +#define LIBIPW_ERROR(f, a...) printk(KERN_ERR "libipw: " f, ## a) +#define LIBIPW_WARNING(f, a...) printk(KERN_WARNING "libipw: " f, ## a) #define LIBIPW_DEBUG_INFO(f, a...) LIBIPW_DEBUG(LIBIPW_DL_INFO, f, ## a) #define LIBIPW_DEBUG_WX(f, a...) LIBIPW_DEBUG(LIBIPW_DL_WX, f, ## a) @@ -905,7 +905,7 @@ struct libipw_device { struct libipw_reassoc_request * req); /* This must be the last item so that it points to the data - * allocated beyond this structure by alloc_ieee80211 */ + * allocated beyond this structure by alloc_libipw */ u8 priv[0]; }; @@ -1017,9 +1017,9 @@ static inline int libipw_is_cck_rate(u8 rate) return 0; } -/* ieee80211.c */ -extern void free_ieee80211(struct net_device *dev, int monitor); -extern struct net_device *alloc_ieee80211(int sizeof_priv, int monitor); +/* libipw.c */ +extern void free_libipw(struct net_device *dev, int monitor); +extern struct net_device *alloc_libipw(int sizeof_priv, int monitor); extern int libipw_change_mtu(struct net_device *dev, int new_mtu); extern void libipw_networks_age(struct libipw_device *ieee, diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index 1ae0b2b02c38..5b8841159b7c 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c @@ -53,7 +53,7 @@ #include "libipw.h" #define DRV_DESCRIPTION "802.11 data/management/control stack" -#define DRV_NAME "ieee80211" +#define DRV_NAME "libipw" #define DRV_VERSION LIBIPW_VERSION #define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation " @@ -143,7 +143,7 @@ int libipw_change_mtu(struct net_device *dev, int new_mtu) } EXPORT_SYMBOL(libipw_change_mtu); -struct net_device *alloc_ieee80211(int sizeof_priv, int monitor) +struct net_device *alloc_libipw(int sizeof_priv, int monitor) { struct libipw_device *ieee; struct net_device *dev; @@ -225,8 +225,9 @@ failed_free_netdev: failed: return NULL; } +EXPORT_SYMBOL(alloc_libipw); -void free_ieee80211(struct net_device *dev, int monitor) +void free_libipw(struct net_device *dev, int monitor) { struct libipw_device *ieee = netdev_priv(dev); @@ -240,6 +241,7 @@ void free_ieee80211(struct net_device *dev, int monitor) free_netdev(dev); } +EXPORT_SYMBOL(free_libipw); #ifdef CONFIG_LIBIPW_DEBUG @@ -294,7 +296,7 @@ static int __init libipw_init(void) struct proc_dir_entry *e; libipw_debug_level = debug; - libipw_proc = proc_mkdir(DRV_NAME, init_net.proc_net); + libipw_proc = proc_mkdir("ieee80211", init_net.proc_net); if (libipw_proc == NULL) { LIBIPW_ERROR("Unable to create " DRV_NAME " proc directory\n"); @@ -334,6 +336,3 @@ MODULE_PARM_DESC(debug, "debug output mask"); module_exit(libipw_exit); module_init(libipw_init); - -EXPORT_SYMBOL(alloc_ieee80211); -EXPORT_SYMBOL(free_ieee80211); -- cgit v1.2.3 From d6e36ec1d04edec73fedeea89ec8027e3d215dcb Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 15 Mar 2010 17:22:26 +0100 Subject: rt2x00: fix warning when building rt2800pci with just soc support Fix compile warning "rt2800pci.c:1248: warning: 'rt2800pci_device_table' defined but not used" when building rt2800pci with only soc support (without pci). Signed-off-by: Helmut Schaa Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 91cce2d0f6db..549a60ab3b64 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1184,6 +1184,7 @@ static const struct rt2x00_ops rt2800pci_ops = { /* * RT2800pci module information. */ +#ifdef CONFIG_RT2800PCI_PCI static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, @@ -1211,6 +1212,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { #endif { 0, } }; +#endif /* CONFIG_RT2800PCI_PCI */ MODULE_AUTHOR(DRV_PROJECT); MODULE_VERSION(DRV_VERSION); -- cgit v1.2.3 From 632dd959d13d7b96b8eeb2af77b4511053c04633 Mon Sep 17 00:00:00 2001 From: Alban Browaeys Date: Fri, 26 Feb 2010 23:19:59 +0100 Subject: rt2x00: txdone implementation supporting hw encryption. This is an implementation that support WCID being the encryption key. Wireless Cli Id was set to be the encryption key in rt2800pci_write_tx_desc and read (TX_STA_FIFO_WCID) as the current queue entry index. Signed-off-by: Benoit Papillault Signed-off-by: Alban Browaeys Acked-by: Ivo van Doorn Signed-off-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 57 +++++++++++++++------------------ 1 file changed, 25 insertions(+), 32 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 549a60ab3b64..2f42e01eb99d 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -907,14 +907,12 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; struct queue_entry *entry; - struct queue_entry *entry_done; - struct queue_entry_priv_pci *entry_priv; + __le32 *txwi; struct txdone_entry_desc txdesc; u32 word; u32 reg; u32 old_reg; - unsigned int type; - unsigned int index; + int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; u16 mcs, real_mcs; /* @@ -936,47 +934,41 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) break; old_reg = reg; + wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); + ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); + pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); + /* * Skip this entry when it contains an invalid * queue identication number. */ - type = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE) - 1; - if (type >= QID_RX) + if (pid <= 0 || pid > QID_RX) continue; - queue = rt2x00queue_get_queue(rt2x00dev, type); + queue = rt2x00queue_get_queue(rt2x00dev, pid - 1); if (unlikely(!queue)) continue; /* - * Skip this entry when it contains an invalid - * index number. + * Inside each queue, we process each entry in a chronological + * order. We first check that the queue is not empty. */ - index = rt2x00_get_field32(reg, TX_STA_FIFO_WCID) - 1; - if (unlikely(index >= queue->limit)) + if (rt2x00queue_empty(queue)) continue; + entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - entry = &queue->entries[index]; - entry_priv = entry->priv_data; - rt2x00_desc_read((__le32 *)entry->skb->data, 0, &word); - - entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - while (entry != entry_done) { - /* - * Catch up. - * Just report any entries we missed as failed. - */ - WARNING(rt2x00dev, - "TX status report missed for entry %d\n", - entry_done->entry_idx); - - txdesc.flags = 0; - __set_bit(TXDONE_UNKNOWN, &txdesc.flags); - txdesc.retry = 0; - - rt2x00lib_txdone(entry_done, &txdesc); - entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - } + /* Check if we got a match by looking at WCID/ACK/PID + * fields */ + txwi = (__le32 *)(entry->skb->data - + rt2x00dev->ops->extra_tx_headroom); + + rt2x00_desc_read(txwi, 1, &word); + tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); + tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK); + tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID); + + if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) + WARNING(rt2x00dev, "invalid TX_STA_FIFO content\n"); /* * Obtain the status about this packet. @@ -997,6 +989,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) * we have mcs = tx_mcs - 1. So the number of * retry is (tx_mcs - mcs). */ + rt2x00_desc_read(txwi, 0, &word); mcs = rt2x00_get_field32(word, TXWI_W0_MCS); real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); __set_bit(TXDONE_FALLBACK, &txdesc.flags); -- cgit v1.2.3 From bf18723d50206a0b485e438f14c22faf91a3908f Mon Sep 17 00:00:00 2001 From: Alban Browaeys Date: Sun, 28 Feb 2010 17:14:40 +0100 Subject: rt2x00: Fix TX status reporting for rt2800pci. After testing, we found that TX_STA_FIFO_MCS is the last MCS value tried. If the transmission failed, 8 frames have been transmitted. If the transmission succeed, we can easily compute the number of retry. This patch fix the way status is reported to mac80211 rate control. It has 2 bugs : 1. mcs can contain the short preamble flag and it will lead to wrong computations. 2. minstrel nearly always say that 54 Mbits is the best rate, even if we are very far from the AP Signed-off-by: Benoit Papillault Signed-off-by: Alban Browaeys Acked-by: Ivo van Doorn Signed-off-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 40 ++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 2f42e01eb99d..b1f5643f83fc 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -974,26 +974,36 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) * Obtain the status about this packet. */ txdesc.flags = 0; - if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) - __set_bit(TXDONE_SUCCESS, &txdesc.flags); - else - __set_bit(TXDONE_FAILURE, &txdesc.flags); + rt2x00_desc_read(txwi, 0, &word); + mcs = rt2x00_get_field32(word, TXWI_W0_MCS); + real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); /* * Ralink has a retry mechanism using a global fallback - * table. We setup this fallback table to try immediate - * lower rate for all rates. In the TX_STA_FIFO, - * the MCS field contains the MCS used for the successfull - * transmission. If the first transmission succeed, - * we have mcs == tx_mcs. On the second transmission, - * we have mcs = tx_mcs - 1. So the number of - * retry is (tx_mcs - mcs). + * table. We setup this fallback table to try the immediate + * lower rate for all rates. In the TX_STA_FIFO, the MCS field + * always contains the MCS used for the last transmission, be + * it successful or not. */ - rt2x00_desc_read(txwi, 0, &word); - mcs = rt2x00_get_field32(word, TXWI_W0_MCS); - real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); + if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) { + /* + * Transmission succeeded. The number of retries is + * mcs - real_mcs + */ + __set_bit(TXDONE_SUCCESS, &txdesc.flags); + txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0); + } else { + /* + * Transmission failed. The number of retries is + * always 7 in this case (for a total number of 8 + * frames sent). + */ + __set_bit(TXDONE_FAILURE, &txdesc.flags); + txdesc.retry = 7; + } + __set_bit(TXDONE_FALLBACK, &txdesc.flags); - txdesc.retry = mcs - min(mcs, real_mcs); + rt2x00lib_txdone(entry, &txdesc); } -- cgit v1.2.3 From 647291f5c1596839eb69d6c1f231b2249a703c27 Mon Sep 17 00:00:00 2001 From: Ben Cahill Date: Tue, 2 Mar 2010 12:48:25 -0800 Subject: iwlagn: Add Flow-handler (FH) register dump for 4965. FH register dump debug feature was recently added for 5000 and later; 4965 can use it also. Signed-off-by: Ben Cahill Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 644aacfbd7df..271576ab5747 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2187,6 +2187,7 @@ static struct iwl_lib_ops iwl4965_lib = { .load_ucode = iwl4965_load_bsm, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, + .dump_fh = iwl_dump_fh, .set_channel_switch = iwl4965_hw_channel_switch, .apm_ops = { .init = iwl_apm_init, -- cgit v1.2.3 From 7e2461910e9115c9964975f77584baf8c2f76bfe Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Thu, 18 Feb 2010 22:58:32 -0800 Subject: iwlwifi: only add broadcast station once Currently the broadcast station is added after every RXON command. Change this to only add the broadcast station when interface is added by mac80211. With this we need some extra work to ensure broadcast station is always present since station table is cleared when RXON without ASSOC bit set is sent. To deal with this we re-add all driver known stations to uCode after such an RXON command is sent. We also do some cleanup and remove the various calls to clear the station table. We now only clear the station table in two scenarios: - only clear uCode portion of station table when RXON command without ASSOC bit is sent - clear uCode and driver portion when interface goes down or is removed. We need to do this clearing when interface goes down to deal with the device restart/reconfigure routines which do not remove the interface, but do add the interface during reconfiguration. Previously the keys were also cleared when station table in driver is cleared, this is not done anymore since mac80211 will take care that keys are set and cleared correctly. There is a known issue with this change. Associating with different AP without bringing interface down fails with a firmware error. This is because of the lack of full station notification support and the later patches in this series that complete the station notification support will fix this. Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945.c | 10 +-- drivers/net/wireless/iwlwifi/iwl-5000.c | 1 - drivers/net/wireless/iwlwifi/iwl-agn.c | 27 +++---- drivers/net/wireless/iwlwifi/iwl-core.c | 8 ++- drivers/net/wireless/iwlwifi/iwl-sta.c | 108 ++++++++++++++++++++++------ drivers/net/wireless/iwlwifi/iwl-sta.h | 9 ++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 11 +-- 7 files changed, 117 insertions(+), 57 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index ed59e2744ca4..7f95f9019093 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1911,6 +1911,8 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) "configuration (%d).\n", rc); return rc; } + iwl_clear_ucode_stations(priv, false); + iwl_restore_stations(priv); } IWL_DEBUG_INFO(priv, "Sending RXON\n" @@ -1941,7 +1943,10 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); - iwl_clear_stations_table(priv); + if (!new_assoc) { + iwl_clear_ucode_stations(priv, false); + iwl_restore_stations(priv); + } /* If we issue a new RXON command which required a tune then we must * send a new TXPOWER command or we won't be able to Tx any frames */ @@ -1951,9 +1956,6 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) return rc; } - /* Add the broadcast address so we can send broadcast frames */ - priv->cfg->ops->lib->add_bcast_station(priv); - /* If we have set the ASSOC_MSK and we are in BSS mode then * add the IWL_AP_ID to the station rate table */ if (iwl_is_associated(priv) && diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 37e1e77f513d..046bdd96e5a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -544,7 +544,6 @@ void iwl5000_init_alive_start(struct iwl_priv *priv) goto restart; } - iwl_clear_stations_table(priv); ret = priv->cfg->ops->lib->alive_notify(priv); if (ret) { IWL_WARN(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d6e1a059b9b0..85ff1552481f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -166,6 +166,8 @@ int iwl_commit_rxon(struct iwl_priv *priv) IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); return ret; } + iwl_clear_ucode_stations(priv, false); + iwl_restore_stations(priv); } IWL_DEBUG_INFO(priv, "Sending RXON\n" @@ -179,9 +181,8 @@ int iwl_commit_rxon(struct iwl_priv *priv) iwl_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto); /* Apply the new configuration - * RXON unassoc clears the station table in uCode, send it before - * we add the bcast station. If assoc bit is set, we will send RXON - * after having added the bcast and bssid station. + * RXON unassoc clears the station table in uCode so restoration of + * stations is needed after it (the RXON command) completes */ if (!new_assoc) { ret = iwl_send_cmd_pdu(priv, REPLY_RXON, @@ -190,17 +191,14 @@ int iwl_commit_rxon(struct iwl_priv *priv) IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); return ret; } + IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON. \n"); memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); + iwl_clear_ucode_stations(priv, false); + iwl_restore_stations(priv); } - iwl_clear_stations_table(priv); - priv->start_calib = 0; - /* Add the broadcast address so we can send broadcast frames */ - priv->cfg->ops->lib->add_bcast_station(priv); - - /* If we have set the ASSOC_MSK and we are in BSS mode then * add the IWL_AP_ID to the station rate table */ if (new_assoc) { @@ -2087,7 +2085,6 @@ static void iwl_alive_start(struct iwl_priv *priv) goto restart; } - iwl_clear_stations_table(priv); ret = priv->cfg->ops->lib->alive_notify(priv); if (ret) { IWL_WARN(priv, @@ -2143,6 +2140,8 @@ static void iwl_alive_start(struct iwl_priv *priv) wake_up_interruptible(&priv->wait_command_queue); iwl_power_update_mode(priv, true); + IWL_DEBUG_INFO(priv, "Updated power mode\n"); + return; @@ -2162,7 +2161,7 @@ static void __iwl_down(struct iwl_priv *priv) if (!exit_pending) set_bit(STATUS_EXIT_PENDING, &priv->status); - iwl_clear_stations_table(priv); + iwl_clear_ucode_stations(priv, true); /* Unblock any waiting calls */ wake_up_interruptible_all(&priv->wait_command_queue); @@ -2359,8 +2358,6 @@ static int __iwl_up(struct iwl_priv *priv) for (i = 0; i < MAX_HW_RESTARTS; i++) { - iwl_clear_stations_table(priv); - /* load bootstrap state machine, * load bootstrap program into processor's memory, * prepare to load the "initialize" uCode */ @@ -3270,9 +3267,6 @@ static int iwl_init_drv(struct iwl_priv *priv) mutex_init(&priv->mutex); mutex_init(&priv->sync_cmd_mutex); - /* Clear the driver's (not device's) station table */ - iwl_clear_stations_table(priv); - priv->ieee_channels = NULL; priv->ieee_rates = NULL; priv->band = IEEE80211_BAND_2GHZ; @@ -3649,7 +3643,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) iwl_rx_queue_free(priv, &priv->rxq); iwl_hw_txq_ctx_free(priv); - iwl_clear_stations_table(priv); iwl_eeprom_free(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index ec435e5491d9..a33e4536657a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2283,8 +2283,6 @@ static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); - iwl_clear_stations_table(priv); - return iwlcore_commit_rxon(priv); } @@ -2317,6 +2315,10 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) err = iwl_set_mode(priv, vif); if (err) goto out_err; + + /* Add the broadcast address so we can send broadcast frames */ + priv->cfg->ops->lib->add_bcast_station(priv); + goto out; out_err: @@ -2339,6 +2341,8 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); + iwl_clear_ucode_stations(priv, true); + if (iwl_is_ready_rf(priv)) { iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index b1aad306efa9..312099099ed3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -34,9 +34,6 @@ #include "iwl-core.h" #include "iwl-sta.h" -#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */ -#define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */ - u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) { int i; @@ -495,37 +492,102 @@ out: } /** - * iwl_clear_stations_table - Clear the driver's station table - * - * NOTE: This does not clear or otherwise alter the device's station table. + * iwl_clear_ucode_stations() - clear entire station table driver and/or ucode + * @priv: + * @force: If set then the uCode station table needs to be cleared here. If + * not set then the uCode station table has already been cleared, + * for example after sending it a RXON command without ASSOC bit + * set, and we just need to change driver state here. */ -void iwl_clear_stations_table(struct iwl_priv *priv) +void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force) { - unsigned long flags; int i; + unsigned long flags_spin; + bool cleared = false; + + IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver%s\n", + force ? " and ucode" : ""); + + if (force) { + if (!iwl_is_ready(priv)) { + /* + * If device is not ready at this point the station + * table is likely already empty (uCode not ready + * to receive station requests) or will soon be + * due to interface going down. + */ + IWL_DEBUG_INFO(priv, "Unable to remove stations from device - device not ready\n"); + } else { + iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL); + } + } - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags_spin); + if (force) { + IWL_DEBUG_INFO(priv, "Clearing all station information in driver\n"); + priv->num_stations = 0; + memset(priv->stations, 0, sizeof(priv->stations)); + } else { + for (i = 0; i < priv->hw_params.max_stations; i++) { + if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { + IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d \n", i); + priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; + cleared = true; + } + } + } + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + + if (!cleared) + IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n"); +} +EXPORT_SYMBOL(iwl_clear_ucode_stations); - if (iwl_is_alive(priv) && - !test_bit(STATUS_EXIT_PENDING, &priv->status) && - iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL)) - IWL_ERR(priv, "Couldn't clear the station table\n"); +/** + * iwl_restore_stations() - Restore driver known stations to device + * + * All stations considered active by driver, but not present in ucode, is + * restored. + */ +void iwl_restore_stations(struct iwl_priv *priv) +{ + unsigned long flags_spin; + int i; + bool found = false; - priv->num_stations = 0; - memset(priv->stations, 0, sizeof(priv->stations)); + if (!iwl_is_ready(priv)) { + IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); + return; + } - /* clean ucode key table bit map */ - priv->ucode_key_table = 0; + IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n"); + spin_lock_irqsave(&priv->sta_lock, flags_spin); + for (i = 0; i < priv->hw_params.max_stations; i++) { + if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) && + !(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) { + IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n", + priv->stations[i].sta.sta.addr); + priv->stations[i].sta.mode = 0; + priv->stations[i].used |= IWL_STA_UCODE_INPROGRESS; + found = true; + } + } - /* keep track of static keys */ - for (i = 0; i < WEP_KEYS_MAX ; i++) { - if (priv->wep_keys[i].key_size) - set_bit(i, &priv->ucode_key_table); + for (i = 0; i < priv->hw_params.max_stations; i++) { + if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) { + iwl_send_add_sta(priv, &priv->stations[i].sta, + CMD_ASYNC); + priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; + } } - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + if (!found) + IWL_DEBUG_INFO(priv, "Restoring all known stations .... no stations to be restored.\n"); + else + IWL_DEBUG_INFO(priv, "Restoring all known stations .... in progress.\n"); } -EXPORT_SYMBOL(iwl_clear_stations_table); +EXPORT_SYMBOL(iwl_restore_stations); int iwl_get_free_ucode_key_index(struct iwl_priv *priv) { diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 2dc35fe28f56..50367e83defd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -32,6 +32,12 @@ #define HW_KEY_DYNAMIC 0 #define HW_KEY_DEFAULT 1 +#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */ +#define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */ +#define IWL_STA_UCODE_INPROGRESS BIT(2) /* ucode entry is in process of + being activated */ + + /** * iwl_find_station - Find station id for a given BSSID * @bssid: MAC address of station ID to find @@ -55,7 +61,8 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); void iwl_add_bcast_station(struct iwl_priv *priv); void iwl3945_add_bcast_station(struct iwl_priv *priv); int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); -void iwl_clear_stations_table(struct iwl_priv *priv); +void iwl_restore_stations(struct iwl_priv *priv); +void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force); int iwl_get_free_ucode_key_index(struct iwl_priv *priv); int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 2579bbcaab36..6d3e6a85f932 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2480,8 +2480,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv) goto restart; } - iwl_clear_stations_table(priv); - rfkill = iwl_read_prph(priv, APMG_RFKILL_REG); IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill); @@ -2558,7 +2556,8 @@ static void __iwl3945_down(struct iwl_priv *priv) if (!exit_pending) set_bit(STATUS_EXIT_PENDING, &priv->status); - iwl_clear_stations_table(priv); + /* Station information will now be cleared in device */ + iwl_clear_ucode_stations(priv, true); /* Unblock any waiting calls */ wake_up_interruptible_all(&priv->wait_command_queue); @@ -2692,8 +2691,6 @@ static int __iwl3945_up(struct iwl_priv *priv) for (i = 0; i < MAX_HW_RESTARTS; i++) { - iwl_clear_stations_table(priv); - /* load bootstrap state machine, * load bootstrap program into processor's memory, * prepare to load the "initialize" uCode */ @@ -3834,9 +3831,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) mutex_init(&priv->mutex); mutex_init(&priv->sync_cmd_mutex); - /* Clear the driver's (not device's) station table */ - iwl_clear_stations_table(priv); - priv->ieee_channels = NULL; priv->ieee_rates = NULL; priv->band = IEEE80211_BAND_2GHZ; @@ -4196,7 +4190,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl3945_hw_txq_ctx_free(priv); iwl3945_unset_hw_params(priv); - iwl_clear_stations_table(priv); /*netif_stop_queue(dev); */ flush_workqueue(priv->workqueue); -- cgit v1.2.3 From fe6b23dd361199bfbc50b0cbce6bed37c5797c75 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Mon, 22 Feb 2010 16:24:47 -0800 Subject: iwlwifi: implement new mac80211 station add/remove calls mac80211 recently implemented two new callbacks that are used to request station add/remove from the driver. The benefot from these new callbacks are that they enable the driver to sleep while performing this work. This is a big patch since a few things need to be coordinated in this move. First we need to decouple station management from rate scaling, which caused a lot of code to be moved and/or deleted. Next we needed to tie in with mac80211's station management callback and let it direct our station management as well as trigger the rate scaling initialization. Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 83 +++-- drivers/net/wireless/iwlwifi/iwl-3945.c | 10 - drivers/net/wireless/iwlwifi/iwl-3945.h | 1 - drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 120 +++---- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 7 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 95 ++--- drivers/net/wireless/iwlwifi/iwl-core.c | 1 - drivers/net/wireless/iwlwifi/iwl-core.h | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 8 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 528 +++++++++++++++------------- drivers/net/wireless/iwlwifi/iwl-sta.h | 11 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 45 ++- 12 files changed, 522 insertions(+), 389 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index b588cb69536a..605aca4c78c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -329,16 +329,25 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, } -static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta) +/* + * Called after adding a new station to initialize rate scaling + */ +void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id) { - struct iwl3945_rs_sta *rs_sta = priv_sta; - struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct ieee80211_hw *hw = priv->hw; + struct ieee80211_conf *conf = &priv->hw->conf; + struct iwl3945_sta_priv *psta; + struct iwl3945_rs_sta *rs_sta; + struct ieee80211_supported_band *sband; int i; - IWL_DEBUG_RATE(priv, "enter\n"); + IWL_DEBUG_INFO(priv, "enter \n"); + if (sta_id == priv->hw_params.bcast_sta_id) + goto out; - spin_lock_init(&rs_sta->lock); + psta = (struct iwl3945_sta_priv *) sta->drv_priv; + rs_sta = &psta->rs_sta; + sband = hw->wiphy->bands[conf->channel->band]; rs_sta->priv = priv; @@ -351,9 +360,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, rs_sta->last_flush = jiffies; rs_sta->flush_time = IWL_RATE_FLUSH; rs_sta->last_tx_packets = 0; - rs_sta->ibss_sta_added = 0; - init_timer(&rs_sta->rate_scale_flush); rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; rs_sta->rate_scale_flush.function = iwl3945_bg_rate_scale_flush; @@ -380,8 +387,10 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, IWL_FIRST_OFDM_RATE; } +out: + priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; - IWL_DEBUG_RATE(priv, "leave\n"); + IWL_DEBUG_INFO(priv, "leave\n"); } static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) @@ -405,6 +414,9 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) rs_sta = &psta->rs_sta; + spin_lock_init(&rs_sta->lock); + init_timer(&rs_sta->rate_scale_flush); + IWL_DEBUG_RATE(priv, "leave\n"); return rs_sta; @@ -413,13 +425,14 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta, void *priv_sta) { - struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; - struct iwl3945_rs_sta *rs_sta = &psta->rs_sta; - struct iwl_priv *priv __maybe_unused = rs_sta->priv; + struct iwl3945_rs_sta *rs_sta = priv_sta; - IWL_DEBUG_RATE(priv, "enter\n"); + /* + * Be careful not to use any members of iwl3945_rs_sta (like trying + * to use iwl_priv to print out debugging) since it may not be fully + * initialized at this point. + */ del_timer_sync(&rs_sta->rate_scale_flush); - IWL_DEBUG_RATE(priv, "leave\n"); } @@ -458,6 +471,13 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband return; } + /* Treat uninitialized rate scaling data same as non-existing. */ + if (!rs_sta->priv) { + IWL_DEBUG_RATE(priv, "leave: STA priv data uninitialized!\n"); + return; + } + + rs_sta->tx_packets++; scale_rate_index = first_index; @@ -625,7 +645,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, u32 fail_count; s8 scale_action = 0; unsigned long flags; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; s8 max_rate_idx = -1; struct iwl_priv *priv = (struct iwl_priv *)priv_r; @@ -633,6 +652,12 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, IWL_DEBUG_RATE(priv, "enter\n"); + /* Treat uninitialized rate scaling data same as non-existing. */ + if (rs_sta && !rs_sta->priv) { + IWL_DEBUG_RATE(priv, "Rate scaling information not initialized yet.\n"); + priv_sta = NULL; + } + if (rate_control_send_low(sta, priv_sta, txrc)) return; @@ -650,20 +675,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, if (sband->band == IEEE80211_BAND_5GHZ) rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && - !rs_sta->ibss_sta_added) { - u8 sta_id = iwl_find_station(priv, hdr->addr1); - - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", - hdr->addr1); - sta_id = iwl_add_station(priv, hdr->addr1, false, - CMD_ASYNC, NULL); - } - if (sta_id != IWL_INVALID_STATION) - rs_sta->ibss_sta_added = 1; - } - spin_lock_irqsave(&rs_sta->lock, flags); /* for recent assoc, choose best rate regarding @@ -883,12 +894,22 @@ static void iwl3945_remove_debugfs(void *priv, void *priv_sta) } #endif +/* + * Initialization of rate scaling information is done by driver after + * the station is added. Since mac80211 calls this function before a + * station is added we ignore it. + */ +static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) +{ +} + static struct rate_control_ops rs_ops = { .module = NULL, .name = RS_NAME, .tx_status = rs_tx_status, .get_rate = rs_get_rate, - .rate_init = rs_rate_init, + .rate_init = rs_rate_init_stub, .alloc = rs_alloc, .free = rs_free, .alloc_sta = rs_alloc_sta, @@ -899,7 +920,6 @@ static struct rate_control_ops rs_ops = { #endif }; - void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) { struct iwl_priv *priv = hw->priv; @@ -916,6 +936,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) sta = ieee80211_find_sta(priv->vif, priv->stations[sta_id].sta.sta.addr); if (!sta) { + IWL_DEBUG_RATE(priv, "Unable to find station to initialize rate scaling.\n"); rcu_read_unlock(); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 7f95f9019093..11785e2c767a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1956,16 +1956,6 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) return rc; } - /* If we have set the ASSOC_MSK and we are in BSS mode then - * add the IWL_AP_ID to the station rate table */ - if (iwl_is_associated(priv) && - (priv->iw_mode == NL80211_IFTYPE_STATION)) - if (iwl_add_station(priv, priv->active_rxon.bssid_addr, - true, CMD_SYNC, NULL) == IWL_INVALID_STATION) { - IWL_ERR(priv, "Error adding AP address for transmit\n"); - return -EIO; - } - /* Init the hardware's rate fallback order based on the band */ rc = iwl3945_init_hw_rate_table(priv); if (rc) { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 452dfd5456c6..b89219573b91 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -95,7 +95,6 @@ struct iwl3945_rs_sta { u8 tgg; u8 flush_pending; u8 start_rate; - u8 ibss_sta_added; struct timer_list rate_scale_flush; struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945]; #ifdef CONFIG_MAC80211_DEBUGFS diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 84271cc62afa..970eec82d106 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -769,6 +769,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); + /* Treat uninitialized rate scaling data same as non-existing. */ + if (!lq_sta) { + IWL_DEBUG_RATE(priv, "Station rate scaling not created yet.\n"); + return; + } else if (!lq_sta->drv) { + IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n"); + return; + } + if (!ieee80211_is_data(hdr->frame_control) || info->flags & IEEE80211_TX_CTL_NO_ACK) return; @@ -778,10 +787,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, !(info->flags & IEEE80211_TX_STAT_AMPDU)) return; - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && - !lq_sta->ibss_sta_added) - return; - /* * Ignore this Tx frame response if its initial rate doesn't match * that of latest Link Quality command. There may be stragglers @@ -827,7 +832,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, lq_sta->missed_rate_counter++; if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { lq_sta->missed_rate_counter = 0; - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); } /* Regardless, ignore this status info for outdated rate */ return; @@ -1915,7 +1920,7 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv, /* Update uCode's rate table. */ rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); rs_fill_link_cmd(priv, lq_sta, rate); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); return rate; } @@ -2291,7 +2296,7 @@ lq_update: IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n", tbl->current_rate, index); rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); } else done_search = 1; } @@ -2340,7 +2345,20 @@ out: return; } - +/** + * rs_initialize_lq - Initialize a station's hardware rate table + * + * The uCode's station table contains a table of fallback rates + * for automatic fallback during transmission. + * + * NOTE: This sets up a default set of values. These will be replaced later + * if the driver's iwl-agn-rs rate scaling algorithm is used, instead of + * rc80211_simple. + * + * NOTE: Run REPLY_ADD_STA command to set up station table entry, before + * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, + * which requires station table entry to exist). + */ static void rs_initialize_lq(struct iwl_priv *priv, struct ieee80211_conf *conf, struct ieee80211_sta *sta, @@ -2390,7 +2408,8 @@ static void rs_initialize_lq(struct iwl_priv *priv, tbl->current_rate = rate; rs_set_expected_tpt_table(lq_sta, tbl); rs_fill_link_cmd(NULL, lq_sta, rate); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq; + iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_SYNC, true); out: return; } @@ -2402,9 +2421,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb = txrc->skb; struct ieee80211_supported_band *sband = txrc->sband; struct iwl_priv *priv = (struct iwl_priv *)priv_r; - struct ieee80211_conf *conf = &priv->hw->conf; - struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_lq_sta *lq_sta = priv_sta; int rate_idx; @@ -2422,30 +2438,18 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, lq_sta->max_rate_idx = -1; } + /* Treat uninitialized rate scaling data same as non-existing. */ + if (lq_sta && !lq_sta->drv) { + IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n"); + priv_sta = NULL; + } + /* Send management frames and NO_ACK data using lowest rate. */ if (rate_control_send_low(sta, priv_sta, txrc)) return; rate_idx = lq_sta->last_txrate_idx; - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && - !lq_sta->ibss_sta_added) { - u8 sta_id = iwl_find_station(priv, hdr->addr1); - - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", - hdr->addr1); - sta_id = iwl_add_station(priv, hdr->addr1, - false, CMD_ASYNC, ht_cap); - } - if ((sta_id != IWL_INVALID_STATION)) { - lq_sta->lq.sta_id = sta_id; - lq_sta->lq.rs_table[0].rate_n_flags = 0; - lq_sta->ibss_sta_added = 1; - rs_initialize_lq(priv, conf, sta, lq_sta); - } - } - if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { rate_idx -= IWL_FIRST_OFDM_RATE; /* 6M and 9M shared same MCS index */ @@ -2495,16 +2499,25 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, return lq_sta; } -static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta) +/* + * Called after adding a new station to initialize rate scaling + */ +void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id) { int i, j; - struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct ieee80211_hw *hw = priv->hw; struct ieee80211_conf *conf = &priv->hw->conf; struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; - struct iwl_lq_sta *lq_sta = priv_sta; + struct iwl_station_priv *sta_priv; + struct iwl_lq_sta *lq_sta; + struct ieee80211_supported_band *sband; + + sta_priv = (struct iwl_station_priv *) sta->drv_priv; + lq_sta = &sta_priv->lq_sta; + sband = hw->wiphy->bands[conf->channel->band]; - lq_sta->lq.sta_id = 0xff; + + lq_sta->lq.sta_id = sta_id; for (j = 0; j < LQ_SIZE; j++) for (i = 0; i < IWL_RATE_COUNT; i++) @@ -2516,33 +2529,13 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); - IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init ***\n"); + IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init for station %d ***\n", + sta_id); /* TODO: what is a good starting rate for STA? About middle? Maybe not * the lowest or the highest rate.. Could consider using RSSI from * previous packets? Need to have IEEE 802.1X auth succeed immediately * after assoc.. */ - lq_sta->ibss_sta_added = 0; - if (priv->iw_mode == NL80211_IFTYPE_AP) { - u8 sta_id = iwl_find_station(priv, - sta->addr); - - /* for IBSS the call are from tasklet */ - IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); - - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); - sta_id = iwl_add_station(priv, sta->addr, false, - CMD_ASYNC, ht_cap); - } - if ((sta_id != IWL_INVALID_STATION)) { - lq_sta->lq.sta_id = sta_id; - lq_sta->lq.rs_table[0].rate_n_flags = 0; - } - /* FIXME: this is w/a remove it later */ - priv->assoc_station_added = 1; - } - lq_sta->is_dup = 0; lq_sta->max_rate_idx = -1; lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; @@ -2795,7 +2788,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, if (lq_sta->dbg_fixed_rate) { rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); - iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); + iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false); } return count; @@ -2992,12 +2985,21 @@ static void rs_remove_debugfs(void *priv, void *priv_sta) } #endif +/* + * Initialization of rate scaling information is done by driver after + * the station is added. Since mac80211 calls this function before a + * station is added we ignore it. + */ +static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) +{ +} static struct rate_control_ops rs_ops = { .module = NULL, .name = RS_NAME, .tx_status = rs_tx_status, .get_rate = rs_get_rate, - .rate_init = rs_rate_init, + .rate_init = rs_rate_init_stub, .alloc = rs_alloc, .free = rs_free, .alloc_sta = rs_alloc_sta, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index e182f5a0f736..8292f6d48ec6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -403,7 +403,6 @@ struct iwl_lq_sta { u8 is_green; u8 is_dup; enum ieee80211_band band; - u8 ibss_sta_added; /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ u32 supp_rates; @@ -478,6 +477,12 @@ static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) */ extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); +/* Initialize station's rate scaling information after adding station */ +extern void iwl_rs_rate_init(struct iwl_priv *priv, + struct ieee80211_sta *sta, u8 sta_id); +extern void iwl3945_rs_rate_init(struct iwl_priv *priv, + struct ieee80211_sta *sta, u8 sta_id); + /** * iwl_rate_control_register - Register the rate control algorithm callbacks * diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 85ff1552481f..4b4b47676ad8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -144,9 +144,6 @@ int iwl_commit_rxon(struct iwl_priv *priv) return 0; } - /* station table will be cleared */ - priv->assoc_station_added = 0; - /* If we are currently associated and the new config requires * an RXON_ASSOC and the new config wants the associated mask enabled, * we must clear the associated from the active configuration @@ -198,25 +195,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) } priv->start_calib = 0; - - /* If we have set the ASSOC_MSK and we are in BSS mode then - * add the IWL_AP_ID to the station rate table */ if (new_assoc) { - if (priv->iw_mode == NL80211_IFTYPE_STATION) { - ret = iwl_rxon_add_station(priv, - priv->active_rxon.bssid_addr, 1); - if (ret == IWL_INVALID_STATION) { - IWL_ERR(priv, - "Error adding AP address for TX.\n"); - return -EIO; - } - priv->assoc_station_added = 1; - if (priv->default_wep_key && - iwl_send_static_wepkey_cmd(priv, 0)) - IWL_ERR(priv, - "Could not send WEP static key.\n"); - } - /* * allow CTS-to-self if possible for new association. * this is relevant only for 5000 series and up, @@ -2498,10 +2477,6 @@ void iwl_post_associate(struct iwl_priv *priv) return; } - IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", - priv->assoc_id, priv->active_rxon.bssid_addr); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -2553,6 +2528,9 @@ void iwl_post_associate(struct iwl_priv *priv) iwlcore_commit_rxon(priv); + IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", + priv->assoc_id, priv->active_rxon.bssid_addr); + switch (priv->iw_mode) { case NL80211_IFTYPE_STATION: break; @@ -2562,7 +2540,7 @@ void iwl_post_associate(struct iwl_priv *priv) /* assume default assoc id */ priv->assoc_id = 1; - iwl_rxon_add_station(priv, priv->bssid, 0); + iwl_add_local_station(priv, priv->bssid, true); iwl_send_beacon_cmd(priv); break; @@ -2573,9 +2551,6 @@ void iwl_post_associate(struct iwl_priv *priv) break; } - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) - priv->assoc_station_added = 1; - spin_lock_irqsave(&priv->lock, flags); iwl_activate_qos(priv, 0); spin_unlock_irqrestore(&priv->lock, flags); @@ -2974,18 +2949,7 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; int sta_id; - /* - * TODO: We really should use this callback to - * actually maintain the station table in - * the device. - */ - switch (cmd) { - case STA_NOTIFY_ADD: - atomic_set(&sta_priv->pending_frames, 0); - if (vif->type == NL80211_IFTYPE_AP) - sta_priv->client = true; - break; case STA_NOTIFY_SLEEP: WARN_ON(!sta_priv->client); sta_priv->asleep = true; @@ -3006,6 +2970,55 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, } } +/** + * iwl_restore_wepkeys - Restore WEP keys to device + */ +static void iwl_restore_wepkeys(struct iwl_priv *priv) +{ + mutex_lock(&priv->mutex); + if (priv->iw_mode == NL80211_IFTYPE_STATION && + priv->default_wep_key && + iwl_send_static_wepkey_cmd(priv, 0)) + IWL_ERR(priv, "Could not send WEP static key\n"); + mutex_unlock(&priv->mutex); +} + +static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; + bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; + int ret; + u8 sta_id; + + IWL_DEBUG_INFO(priv, "received request to add station %pM\n", + sta->addr); + + atomic_set(&sta_priv->pending_frames, 0); + if (vif->type == NL80211_IFTYPE_AP) + sta_priv->client = true; + + ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap, + &sta_id); + if (ret) { + IWL_ERR(priv, "Unable to add station %pM (%d)\n", + sta->addr, ret); + /* Should we return success if return code is EEXIST ? */ + return ret; + } + + iwl_restore_wepkeys(priv); + + /* Initialize rate scaling */ + IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM \n", + sta->addr); + iwl_rs_rate_init(priv, sta, sta_id); + + return ret; +} + /***************************************************************************** * * sysfs attributes @@ -3359,6 +3372,8 @@ static struct ieee80211_ops iwl_hw_ops = { .ampdu_action = iwl_mac_ampdu_action, .hw_scan = iwl_mac_hw_scan, .sta_notify = iwl_mac_sta_notify, + .sta_add = iwlagn_mac_sta_add, + .sta_remove = iwl_mac_sta_remove, }; static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index a33e4536657a..d4c2a3e17c53 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2530,7 +2530,6 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) spin_lock_irqsave(&priv->lock, flags); priv->assoc_id = 0; priv->assoc_capability = 0; - priv->assoc_station_added = 0; /* new association get rid of ibss beacon skb */ if (priv->ibss_beacon) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index aced12f1611e..2482a25d543f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -667,7 +667,7 @@ extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear); extern int iwl_verify_ucode(struct iwl_priv *priv); extern int iwl_send_lq_cmd(struct iwl_priv *priv, - struct iwl_link_quality_cmd *lq, u8 flags); + struct iwl_link_quality_cmd *lq, u8 flags, bool init); extern void iwl_rx_reply_rx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 2e4d47c7139b..9c676ea420b9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -544,11 +544,18 @@ struct iwl_qos_info { struct iwl_qosparam_cmd def_qos_parm; }; +/* + * Structure should be accessed with sta_lock held. When station addition + * is in progress (IWL_STA_UCODE_INPROGRESS) it is possible to access only + * the commands (iwl_addsta_cmd and iwl_link_quality_cmd) without sta_lock + * held. + */ struct iwl_station_entry { struct iwl_addsta_cmd sta; struct iwl_tid_data tid[MAX_TID_COUNT]; u8 used; struct iwl_hw_key keyinfo; + struct iwl_link_quality_cmd *lq; }; /* @@ -1163,7 +1170,6 @@ struct iwl_priv { u16 active_rate; - u8 assoc_station_added; u8 start_calib; struct iwl_sensitivity_data sensitivity_data; struct iwl_chain_noise_data chain_noise_data; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 312099099ed3..d401b6f226f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -29,6 +29,7 @@ #include #include +#include #include "iwl-dev.h" #include "iwl-core.h" @@ -61,6 +62,19 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) addr, priv->num_stations); out: + /* + * It may be possible that more commands interacting with stations + * arrive before we completed processing the adding of + * station + */ + if (ret != IWL_INVALID_STATION && + (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) || + ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) && + (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) { + IWL_ERR(priv, "Requested station info for sta %d before ready. \n", + ret); + ret = IWL_INVALID_STATION; + } spin_unlock_irqrestore(&priv->sta_lock, flags); return ret; } @@ -155,13 +169,6 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv, priv->stations[sta_id].sta.mode == STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", addsta->sta.addr); - - /* - * Determine if we wanted to modify or add a station, - * if adding a station succeeded we have some more initialization - * to do when using station notification. TODO - */ - spin_unlock_irqrestore(&priv->sta_lock, flags); } @@ -187,6 +194,10 @@ int iwl_send_add_sta(struct iwl_priv *priv, .flags = flags, .data = data, }; + u8 sta_id = sta->sta.sta_id; + + IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n", + sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); if (flags & CMD_ASYNC) cmd.callback = iwl_add_sta_callback; @@ -260,18 +271,19 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, } /** - * iwl_add_station - Add station to tables in driver and device + * iwl_prep_station - Prepare station information for addition + * + * should be called with sta_lock held */ -u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, - struct ieee80211_sta_ht_cap *ht_info) +static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr, + bool is_ap, + struct ieee80211_sta_ht_cap *ht_info) { struct iwl_station_entry *station; - unsigned long flags_spin; int i; - int sta_id = IWL_INVALID_STATION; + u8 sta_id = IWL_INVALID_STATION; u16 rate; - spin_lock_irqsave(&priv->sta_lock, flags_spin); if (is_ap) sta_id = IWL_AP_ID; else if (is_broadcast_ether_addr(addr)) @@ -289,20 +301,32 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, sta_id = i; } - /* These two conditions have the same outcome, but keep them separate - since they have different meanings */ - if (unlikely(sta_id == IWL_INVALID_STATION)) { - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + /* + * These two conditions have the same outcome, but keep them + * separate + */ + if (unlikely(sta_id == IWL_INVALID_STATION)) + return sta_id; + + /* + * uCode is not able to deal with multiple requests to add a + * station. Keep track if one is in progress so that we do not send + * another. + */ + if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) { + IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n", + sta_id); return sta_id; } - if (priv->stations[sta_id].used && + if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) && + (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) && !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) { - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n", + sta_id, addr); return sta_id; } - station = &priv->stations[sta_id]; station->used = IWL_STA_DRIVER_ACTIVE; IWL_DEBUG_ASSOC(priv, "Add STA to driver ID %d: %pM\n", @@ -327,86 +351,185 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, /* Turn on both antennas for the station... */ station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK); + return sta_id; + +} + +#define STA_WAIT_TIMEOUT (HZ/2) + +/** + * iwl_add_station_common - + */ +int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, + bool is_ap, + struct ieee80211_sta_ht_cap *ht_info, + u8 *sta_id_r) +{ + struct iwl_station_entry *station; + unsigned long flags_spin; + int ret = 0; + u8 sta_id; + + *sta_id_r = 0; + spin_lock_irqsave(&priv->sta_lock, flags_spin); + sta_id = iwl_prep_station(priv, addr, is_ap, ht_info); + if (sta_id == IWL_INVALID_STATION) { + IWL_ERR(priv, "Unable to prepare station %pM for addition\n", + addr); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + return -EINVAL; + } + + /* + * uCode is not able to deal with multiple requests to add a + * station. Keep track if one is in progress so that we do not send + * another. + */ + if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) { + IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n", + sta_id); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + return -EEXIST; + } + + if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) && + (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { + IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n", + sta_id, addr); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + return -EEXIST; + } + + priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; + station = &priv->stations[sta_id]; spin_unlock_irqrestore(&priv->sta_lock, flags_spin); /* Add station to device's station table */ - iwl_send_add_sta(priv, &station->sta, flags); - return sta_id; - + ret = iwl_send_add_sta(priv, &station->sta, CMD_SYNC); + if (ret) { + IWL_ERR(priv, "Adding station %pM failed.\n", station->sta.sta.addr); + spin_lock_irqsave(&priv->sta_lock, flags_spin); + priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; + priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + } + *sta_id_r = sta_id; + return ret; } -EXPORT_SYMBOL(iwl_add_station); +EXPORT_SYMBOL(iwl_add_station_common); -static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const u8 *addr) +static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) { - unsigned long flags; - u8 sta_id = iwl_find_station(priv, addr); + int i, r; + struct iwl_link_quality_cmd link_cmd = { + .reserved1 = 0, + }; + u32 rate_flags; + + /* Set up the rate scaling to start at selected rate, fall back + * all the way down to 1M in IEEE order, and then spin on 1M */ + if (is_ap) + r = IWL_RATE_54M_INDEX; + else if (priv->band == IEEE80211_BAND_5GHZ) + r = IWL_RATE_6M_INDEX; + else + r = IWL_RATE_1M_INDEX; - BUG_ON(sta_id == IWL_INVALID_STATION); + for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { + rate_flags = 0; + if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) + rate_flags |= RATE_MCS_CCK_MSK; - IWL_DEBUG_ASSOC(priv, "Removed STA from Ucode: %pM\n", addr); + rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << + RATE_MCS_ANT_POS; - spin_lock_irqsave(&priv->sta_lock, flags); + link_cmd.rs_table[i].rate_n_flags = + iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); + r = iwl_get_prev_ieee_rate(r); + } - /* Ucode must be active and driver must be non active */ - if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE) - IWL_ERR(priv, "removed non active STA %d\n", sta_id); + link_cmd.general_params.single_stream_ant_msk = + first_antenna(priv->hw_params.valid_tx_ant); + link_cmd.general_params.dual_stream_ant_msk = 3; + link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; + link_cmd.agg_params.agg_time_limit = + cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); - priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE; + /* Update the rate scaling for control frame Tx to AP */ + link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; - memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry)); - spin_unlock_irqrestore(&priv->sta_lock, flags); + iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, + sizeof(link_cmd), &link_cmd); } -static void iwl_remove_sta_callback(struct iwl_priv *priv, - struct iwl_device_cmd *cmd, - struct iwl_rx_packet *pkt) +/* + * iwl_add_local_stations - Add stations not requested by mac80211 + * + * This will be either the broadcast station or the bssid station needed by + * ad-hoc. + * + * Function sleeps. + */ +int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs) { - struct iwl_rem_sta_cmd *rm_sta = - (struct iwl_rem_sta_cmd *)cmd->cmd.payload; - const u8 *addr = rm_sta->addr; + int ret; + u8 sta_id; - if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", - pkt->hdr.flags); - return; + ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); + if (ret) { + IWL_ERR(priv, "Unable to add station %pM\n", addr); + return ret; } - switch (pkt->u.rem_sta.status) { - case REM_STA_SUCCESS_MSK: - iwl_sta_ucode_deactivate(priv, addr); - break; - default: - IWL_ERR(priv, "REPLY_REMOVE_STA failed\n"); - break; - } + if (init_rs) + /* Set up default rate scaling table in device's station table */ + iwl_sta_init_lq(priv, addr, false); + return 0; +} +EXPORT_SYMBOL(iwl_add_local_station); + +/** + * iwl_sta_ucode_deactivate - deactivate ucode status for a station + * + * priv->sta_lock must be held + */ +static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) +{ + /* Ucode must be active and driver must be non active */ + if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE) + IWL_ERR(priv, "removed non active STA %u\n", sta_id); + + priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE; + + memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry)); + IWL_DEBUG_ASSOC(priv, "Removed STA %u\n", sta_id); } -static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, - u8 flags) +static int iwl_send_remove_station(struct iwl_priv *priv, + struct iwl_station_entry *station) { struct iwl_rx_packet *pkt; int ret; + unsigned long flags_spin; struct iwl_rem_sta_cmd rm_sta_cmd; struct iwl_host_cmd cmd = { .id = REPLY_REMOVE_STA, .len = sizeof(struct iwl_rem_sta_cmd), - .flags = flags, + .flags = CMD_SYNC, .data = &rm_sta_cmd, }; memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); rm_sta_cmd.num_sta = 1; - memcpy(&rm_sta_cmd.addr, addr , ETH_ALEN); + memcpy(&rm_sta_cmd.addr, &station->sta.sta.addr , ETH_ALEN); + + cmd.flags |= CMD_WANT_SKB; - if (flags & CMD_ASYNC) - cmd.callback = iwl_remove_sta_callback; - else - cmd.flags |= CMD_WANT_SKB; ret = iwl_send_cmd(priv, &cmd); - if (ret || (flags & CMD_ASYNC)) + if (ret) return ret; pkt = (struct iwl_rx_packet *)cmd.reply_page; @@ -419,7 +542,9 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, if (!ret) { switch (pkt->u.rem_sta.status) { case REM_STA_SUCCESS_MSK: - iwl_sta_ucode_deactivate(priv, addr); + spin_lock_irqsave(&priv->sta_lock, flags_spin); + iwl_sta_ucode_deactivate(priv, station->sta.sta.sta_id); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); break; default: @@ -436,23 +561,35 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, /** * iwl_remove_station - Remove driver's knowledge of station. */ -int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) +static int iwl_remove_station(struct iwl_priv *priv, struct ieee80211_sta *sta) { int sta_id = IWL_INVALID_STATION; int i, ret = -EINVAL; unsigned long flags; + bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; + struct iwl_station_entry *station; + + if (!iwl_is_ready(priv)) { + IWL_DEBUG_INFO(priv, + "Unable to remove station %pM, device not ready. \n", + sta->addr); + /* + * It is typical for stations to be removed when we are + * going down. Return success since device will be down + * soon anyway + */ + return 0; + } spin_lock_irqsave(&priv->sta_lock, flags); if (is_ap) sta_id = IWL_AP_ID; - else if (is_broadcast_ether_addr(addr)) - sta_id = priv->hw_params.bcast_sta_id; else for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) if (priv->stations[i].used && !compare_ether_addr(priv->stations[i].sta.sta.addr, - addr)) { + sta->addr)) { sta_id = i; break; } @@ -461,17 +598,17 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) goto out; IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", - sta_id, addr); + sta_id, sta->addr); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { - IWL_ERR(priv, "Removing %pM but non DRIVER active\n", - addr); + IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", + sta->addr); goto out; } if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { - IWL_ERR(priv, "Removing %pM but non UCODE active\n", - addr); + IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n", + sta->addr); goto out; } @@ -482,9 +619,10 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) BUG_ON(priv->num_stations < 0); + station = &priv->stations[sta_id]; spin_unlock_irqrestore(&priv->sta_lock, flags); - ret = iwl_send_remove_station(priv, addr, CMD_ASYNC); + ret = iwl_send_remove_station(priv, station); return ret; out: spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -548,12 +686,16 @@ EXPORT_SYMBOL(iwl_clear_ucode_stations); * * All stations considered active by driver, but not present in ucode, is * restored. + * + * Function sleeps. */ void iwl_restore_stations(struct iwl_priv *priv) { + struct iwl_station_entry *station; unsigned long flags_spin; int i; bool found = false; + int ret; if (!iwl_is_ready(priv)) { IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); @@ -575,8 +717,24 @@ void iwl_restore_stations(struct iwl_priv *priv) for (i = 0; i < priv->hw_params.max_stations; i++) { if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) { - iwl_send_add_sta(priv, &priv->stations[i].sta, - CMD_ASYNC); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + station = &priv->stations[i]; + ret = iwl_send_add_sta(priv, &priv->stations[i].sta, CMD_SYNC); + if (ret) { + IWL_ERR(priv, "Adding station %pM failed.\n", + station->sta.sta.addr); + spin_lock_irqsave(&priv->sta_lock, flags_spin); + priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE; + priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + } + /* + * Rate scaling has already been initialized, send + * current LQ command + */ + if (station->lq) + iwl_send_lq_cmd(priv, station->lq, CMD_SYNC, true); + spin_lock_irqsave(&priv->sta_lock, flags_spin); priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; } } @@ -585,7 +743,7 @@ void iwl_restore_stations(struct iwl_priv *priv) if (!found) IWL_DEBUG_INFO(priv, "Restoring all known stations .... no stations to be restored.\n"); else - IWL_DEBUG_INFO(priv, "Restoring all known stations .... in progress.\n"); + IWL_DEBUG_INFO(priv, "Restoring all known stations .... complete.\n"); } EXPORT_SYMBOL(iwl_restore_stations); @@ -1010,9 +1168,22 @@ static inline void iwl_dump_lq_cmd(struct iwl_priv *priv, } #endif +/** + * iwl_send_lq_cmd() - Send link quality command + * @init: This command is sent as part of station initialization right + * after station has been added. + * + * The link quality command is sent as the last step of station creation. + * This is the special case in which init is set and we call a callback in + * this case to clear the state indicating that station creation is in + * progress. + */ int iwl_send_lq_cmd(struct iwl_priv *priv, - struct iwl_link_quality_cmd *lq, u8 flags) + struct iwl_link_quality_cmd *lq, u8 flags, bool init) { + int ret = 0; + unsigned long flags_spin; + struct iwl_host_cmd cmd = { .id = REPLY_TX_LINK_QUALITY_CMD, .len = sizeof(struct iwl_link_quality_cmd), @@ -1028,167 +1199,31 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, lq->sta_id = IWL_AP_ID; iwl_dump_lq_cmd(priv, lq); + BUG_ON(init && (cmd.flags & CMD_ASYNC)); - if (iwl_is_associated(priv) && priv->assoc_station_added) - return iwl_send_cmd(priv, &cmd); + iwl_dump_lq_cmd(priv, lq); + ret = iwl_send_cmd(priv, &cmd); + if (ret || (cmd.flags & CMD_ASYNC)) + return ret; + if (init) { + IWL_DEBUG_INFO(priv, "init LQ command complete, clearing sta addition status for sta %d \n", + lq->sta_id); + spin_lock_irqsave(&priv->sta_lock, flags_spin); + priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + } return 0; } EXPORT_SYMBOL(iwl_send_lq_cmd); -/** - * iwl_sta_init_lq - Initialize a station's hardware rate table - * - * The uCode's station table contains a table of fallback rates - * for automatic fallback during transmission. - * - * NOTE: This sets up a default set of values. These will be replaced later - * if the driver's iwl-agn-rs rate scaling algorithm is used, instead of - * rc80211_simple. - * - * NOTE: Run REPLY_ADD_STA command to set up station table entry, before - * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, - * which requires station table entry to exist). - */ -static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) -{ - int i, r; - struct iwl_link_quality_cmd link_cmd = { - .reserved1 = 0, - }; - u32 rate_flags; - - /* Set up the rate scaling to start at selected rate, fall back - * all the way down to 1M in IEEE order, and then spin on 1M */ - if (is_ap) - r = IWL_RATE_54M_INDEX; - else if (priv->band == IEEE80211_BAND_5GHZ) - r = IWL_RATE_6M_INDEX; - else - r = IWL_RATE_1M_INDEX; - - for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { - rate_flags = 0; - if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) - rate_flags |= RATE_MCS_CCK_MSK; - - rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << - RATE_MCS_ANT_POS; - - link_cmd.rs_table[i].rate_n_flags = - iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); - r = iwl_get_prev_ieee_rate(r); - } - - link_cmd.general_params.single_stream_ant_msk = - first_antenna(priv->hw_params.valid_tx_ant); - link_cmd.general_params.dual_stream_ant_msk = 3; - link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; - link_cmd.agg_params.agg_time_limit = - cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); - - /* Update the rate scaling for control frame Tx to AP */ - link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; - - iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, - sizeof(link_cmd), &link_cmd, NULL); -} - -/** - * iwl_rxon_add_station - add station into station table. - * - * there is only one AP station with id= IWL_AP_ID - * NOTE: mutex must be held before calling this function - */ -int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) -{ - struct ieee80211_sta *sta; - struct ieee80211_sta_ht_cap ht_config; - struct ieee80211_sta_ht_cap *cur_ht_config = NULL; - u8 sta_id; - - /* - * Set HT capabilities. It is ok to set this struct even if not using - * HT config: the priv->current_ht_config.is_ht flag will just be false - */ - rcu_read_lock(); - sta = ieee80211_find_sta(priv->vif, addr); - if (sta) { - memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config)); - cur_ht_config = &ht_config; - } - rcu_read_unlock(); - - /* Add station to device's station table */ - sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config); - - /* Set up default rate scaling table in device's station table */ - iwl_sta_init_lq(priv, addr, is_ap); - - return sta_id; -} -EXPORT_SYMBOL(iwl_rxon_add_station); - -/** - * iwl_sta_init_bcast_lq - Initialize a bcast station's hardware rate table - * - * NOTE: Run REPLY_ADD_STA command to set up station table entry, before - * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, - * which requires station table entry to exist). - */ -static void iwl_sta_init_bcast_lq(struct iwl_priv *priv) -{ - int i, r; - struct iwl_link_quality_cmd link_cmd = { - .reserved1 = 0, - }; - u32 rate_flags; - - /* Set up the rate scaling to start at selected rate, fall back - * all the way down to 1M in IEEE order, and then spin on 1M */ - if (priv->band == IEEE80211_BAND_5GHZ) - r = IWL_RATE_6M_INDEX; - else - r = IWL_RATE_1M_INDEX; - - for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { - rate_flags = 0; - if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) - rate_flags |= RATE_MCS_CCK_MSK; - - rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << - RATE_MCS_ANT_POS; - - link_cmd.rs_table[i].rate_n_flags = - iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); - r = iwl_get_prev_ieee_rate(r); - } - - link_cmd.general_params.single_stream_ant_msk = - first_antenna(priv->hw_params.valid_tx_ant); - link_cmd.general_params.dual_stream_ant_msk = 3; - link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; - link_cmd.agg_params.agg_time_limit = - cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); - - /* Update the rate scaling for control frame Tx to AP */ - link_cmd.sta_id = priv->hw_params.bcast_sta_id; - - iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, - sizeof(link_cmd), &link_cmd, NULL); -} - - /** * iwl_add_bcast_station - add broadcast station into station table. */ void iwl_add_bcast_station(struct iwl_priv *priv) { IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); - iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL); - - /* Set up default rate scaling table in device's station table */ - iwl_sta_init_bcast_lq(priv); + iwl_add_local_station(priv, iwl_bcast_addr, true); } EXPORT_SYMBOL(iwl_add_bcast_station); @@ -1198,7 +1233,14 @@ EXPORT_SYMBOL(iwl_add_bcast_station); void iwl3945_add_bcast_station(struct iwl_priv *priv) { IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); - iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL); + iwl_add_local_station(priv, iwl_bcast_addr, false); + /* + * It is assumed that when station is added more initialization + * needs to be done, but for 3945 it is not the case and we can + * just release station table access right here. + */ + priv->stations[priv->hw_params.bcast_sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; + } EXPORT_SYMBOL(iwl3945_add_bcast_station); @@ -1221,6 +1263,13 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) /* If we are a client station in a BSS network, use the special * AP station entry (that's the only station we communicate with) */ case NL80211_IFTYPE_STATION: + /* + * If addition of station not complete yet, which means + * that rate scaling has not been initialized, then return + * the broadcast station. + */ + if (!(priv->stations[IWL_AP_ID].used & IWL_STA_UCODE_ACTIVE)) + return priv->hw_params.bcast_sta_id; return IWL_AP_ID; /* If we are an AP, then find the station, or use BCAST */ @@ -1237,13 +1286,6 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) if (sta_id != IWL_INVALID_STATION) return sta_id; - /* Create new station table entry */ - sta_id = iwl_add_station(priv, hdr->addr1, false, - CMD_ASYNC, NULL); - - if (sta_id != IWL_INVALID_STATION) - return sta_id; - IWL_DEBUG_DROP(priv, "Station %pM not in station map. " "Defaulting to broadcast...\n", hdr->addr1); @@ -1353,3 +1395,19 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); } + +int iwl_mac_sta_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + int ret; + struct iwl_priv *priv = hw->priv; + IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", + sta->addr); + ret = iwl_remove_station(priv, sta); + if (ret) + IWL_ERR(priv, "Error removing station %pM\n", + sta->addr); + return ret; +} +EXPORT_SYMBOL(iwl_mac_sta_remove); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 50367e83defd..87a34997a758 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -57,10 +57,8 @@ void iwl_update_tkip_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, const u8 *addr, u32 iv32, u16 *phase1key); -int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); void iwl_add_bcast_station(struct iwl_priv *priv); void iwl3945_add_bcast_station(struct iwl_priv *priv); -int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); void iwl_restore_stations(struct iwl_priv *priv); void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force); int iwl_get_free_ucode_key_index(struct iwl_priv *priv); @@ -68,8 +66,13 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_addsta_cmd *sta, u8 flags); -u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, - struct ieee80211_sta_ht_cap *ht_info); +int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs); +int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, + bool is_ap, + struct ieee80211_sta_ht_cap *ht_info, + u8 *sta_id_r); +int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); int iwl_sta_rx_agg_start(struct iwl_priv *priv, const u8 *addr, int tid, u16 ssn); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 6d3e6a85f932..6687b9456554 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3116,12 +3116,13 @@ void iwl3945_post_associate(struct iwl_priv *priv) case NL80211_IFTYPE_ADHOC: priv->assoc_id = 1; - iwl_add_station(priv, priv->bssid, 0, CMD_SYNC, NULL); + iwl_add_local_station(priv, priv->bssid, false); iwl3945_sync_sta(priv, IWL_STA_ID, - (priv->band == IEEE80211_BAND_5GHZ) ? - IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, + (priv->band == IEEE80211_BAND_5GHZ) ? + IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, CMD_ASYNC); iwl3945_rate_scale_init(priv->hw, IWL_STA_ID); + iwl3945_send_beacon_cmd(priv); break; @@ -3306,7 +3307,7 @@ void iwl3945_config_ap(struct iwl_priv *priv) /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv); - iwl_add_station(priv, iwl_bcast_addr, 0, CMD_SYNC, NULL); + iwl_add_local_station(priv, iwl_bcast_addr, false); } iwl3945_send_beacon_cmd(priv); @@ -3373,6 +3374,38 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } +static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct iwl_priv *priv = hw->priv; + int ret; + bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; + u8 sta_id; + + IWL_DEBUG_INFO(priv, "received request to add station %pM\n", + sta->addr); + + ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap, + &sta_id); + if (ret) { + IWL_ERR(priv, "Unable to add station %pM (%d)\n", + sta->addr, ret); + /* Should we return success if return code is EEXIST ? */ + return ret; + } + + /* Initialize rate scaling */ + IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM \n", + sta->addr); + iwl3945_rs_rate_init(priv, sta, sta_id); + + return 0; + + + + return ret; +} /***************************************************************************** * * sysfs attributes @@ -3812,7 +3845,9 @@ static struct ieee80211_ops iwl3945_hw_ops = { .conf_tx = iwl_mac_conf_tx, .reset_tsf = iwl_mac_reset_tsf, .bss_info_changed = iwl_bss_info_changed, - .hw_scan = iwl_mac_hw_scan + .hw_scan = iwl_mac_hw_scan, + .sta_add = iwl3945_mac_sta_add, + .sta_remove = iwl_mac_sta_remove, }; static int iwl3945_init_drv(struct iwl_priv *priv) -- cgit v1.2.3 From fe0b3b96ab28b7e5fb6c5aea68e6dd88115873da Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 07:07:44 -0800 Subject: iwlwifi: sta_id cannot be invalid in rs_initialize_lq The only caller of this is iwl_rs_rate_init which is only called with a valid sta_id. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 970eec82d106..5155b1a027eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2377,10 +2377,6 @@ static void rs_initialize_lq(struct iwl_priv *priv, i = lq_sta->last_txrate_idx; - if ((lq_sta->lq.sta_id == 0xff) && - (priv->iw_mode == NL80211_IFTYPE_ADHOC)) - goto out; - valid_tx_ant = priv->hw_params.valid_tx_ant; if (!lq_sta->search_better_tbl) -- cgit v1.2.3 From c11362c01b280f8b2c728bc64793d484282b8734 Mon Sep 17 00:00:00 2001 From: Shanyu Zhao Date: Fri, 5 Mar 2010 17:05:20 -0800 Subject: iwlwifi: clean up driver names for 1000/5000/6000 Align the driver names with official product names for 1000/5000/6000 series. This change mainly affects the debug messages show up in system log. No functional changes. Signed-off-by: Shanyu Zhao Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 14 +++++++------- drivers/net/wireless/iwlwifi/iwl-6000.c | 12 ++++++------ drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 59b092eaa829..e31e8a3459b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -223,7 +223,7 @@ static const struct iwl_ops iwl1000_ops = { }; struct iwl_cfg iwl1000_bgn_cfg = { - .name = "1000 Series BGN", + .name = "Intel(R) Centrino(R) Wireless-N 1000 BGN", .fw_name_pre = IWL1000_FW_PRE, .ucode_api_max = IWL1000_UCODE_API_MAX, .ucode_api_min = IWL1000_UCODE_API_MIN, @@ -252,7 +252,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { }; struct iwl_cfg iwl1000_bg_cfg = { - .name = "1000 Series BG", + .name = "Intel(R) Centrino(R) Wireless-N 1000 BG", .fw_name_pre = IWL1000_FW_PRE, .ucode_api_max = IWL1000_UCODE_API_MAX, .ucode_api_min = IWL1000_UCODE_API_MIN, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 271576ab5747..7f9e448fe5e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2232,7 +2232,7 @@ static const struct iwl_ops iwl4965_ops = { }; struct iwl_cfg iwl4965_agn_cfg = { - .name = "4965AGN", + .name = "Intel(R) Wireless WiFi Link 4965AGN", .fw_name_pre = IWL4965_FW_PRE, .ucode_api_max = IWL4965_UCODE_API_MAX, .ucode_api_min = IWL4965_UCODE_API_MIN, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 046bdd96e5a0..8ab28a760157 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1579,7 +1579,7 @@ struct iwl_mod_params iwl50_mod_params = { struct iwl_cfg iwl5300_agn_cfg = { - .name = "5300AGN", + .name = "Intel(R) Ultimate N WiFi Link 5300 AGN", .fw_name_pre = IWL5000_FW_PRE, .ucode_api_max = IWL5000_UCODE_API_MAX, .ucode_api_min = IWL5000_UCODE_API_MIN, @@ -1605,7 +1605,7 @@ struct iwl_cfg iwl5300_agn_cfg = { }; struct iwl_cfg iwl5100_bgn_cfg = { - .name = "5100BGN", + .name = "Intel(R) WiFi Link 5100 BGN", .fw_name_pre = IWL5000_FW_PRE, .ucode_api_max = IWL5000_UCODE_API_MAX, .ucode_api_min = IWL5000_UCODE_API_MIN, @@ -1631,7 +1631,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { }; struct iwl_cfg iwl5100_abg_cfg = { - .name = "5100ABG", + .name = "Intel(R) WiFi Link 5100 ABG", .fw_name_pre = IWL5000_FW_PRE, .ucode_api_max = IWL5000_UCODE_API_MAX, .ucode_api_min = IWL5000_UCODE_API_MIN, @@ -1655,7 +1655,7 @@ struct iwl_cfg iwl5100_abg_cfg = { }; struct iwl_cfg iwl5100_agn_cfg = { - .name = "5100AGN", + .name = "Intel(R) WiFi Link 5100 AGN", .fw_name_pre = IWL5000_FW_PRE, .ucode_api_max = IWL5000_UCODE_API_MAX, .ucode_api_min = IWL5000_UCODE_API_MIN, @@ -1681,7 +1681,7 @@ struct iwl_cfg iwl5100_agn_cfg = { }; struct iwl_cfg iwl5350_agn_cfg = { - .name = "5350AGN", + .name = "Intel(R) WiMAX/WiFi Link 5350 AGN", .fw_name_pre = IWL5000_FW_PRE, .ucode_api_max = IWL5000_UCODE_API_MAX, .ucode_api_min = IWL5000_UCODE_API_MIN, @@ -1707,7 +1707,7 @@ struct iwl_cfg iwl5350_agn_cfg = { }; struct iwl_cfg iwl5150_agn_cfg = { - .name = "5150AGN", + .name = "Intel(R) WiMAX/WiFi Link 5150 AGN", .fw_name_pre = IWL5150_FW_PRE, .ucode_api_max = IWL5150_UCODE_API_MAX, .ucode_api_min = IWL5150_UCODE_API_MIN, @@ -1733,7 +1733,7 @@ struct iwl_cfg iwl5150_agn_cfg = { }; struct iwl_cfg iwl5150_abg_cfg = { - .name = "5150ABG", + .name = "Intel(R) WiMAX/WiFi Link 5150 ABG", .fw_name_pre = IWL5150_FW_PRE, .ucode_api_max = IWL5150_UCODE_API_MAX, .ucode_api_min = IWL5150_UCODE_API_MIN, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 4b7bc008220f..fb7012289c3d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -357,7 +357,7 @@ static const struct iwl_ops iwl6050_ops = { * "i": Internal configuration, use internal Power Amplifier */ struct iwl_cfg iwl6000i_2agn_cfg = { - .name = "6000 Series 2x2 AGN", + .name = "Intel(R) Centrino(R) Advanced-N 6200 AGN", .fw_name_pre = IWL6000_FW_PRE, .ucode_api_max = IWL6000_UCODE_API_MAX, .ucode_api_min = IWL6000_UCODE_API_MIN, @@ -389,7 +389,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { }; struct iwl_cfg iwl6000i_2abg_cfg = { - .name = "6000 Series 2x2 ABG", + .name = "Intel(R) Centrino(R) Advanced-N 6200 ABG", .fw_name_pre = IWL6000_FW_PRE, .ucode_api_max = IWL6000_UCODE_API_MAX, .ucode_api_min = IWL6000_UCODE_API_MIN, @@ -420,7 +420,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = { }; struct iwl_cfg iwl6000i_2bg_cfg = { - .name = "6000 Series 2x2 BG", + .name = "Intel(R) Centrino(R) Advanced-N 6200 BG", .fw_name_pre = IWL6000_FW_PRE, .ucode_api_max = IWL6000_UCODE_API_MAX, .ucode_api_min = IWL6000_UCODE_API_MIN, @@ -451,7 +451,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = { }; struct iwl_cfg iwl6050_2agn_cfg = { - .name = "6050 Series 2x2 AGN", + .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN", .fw_name_pre = IWL6050_FW_PRE, .ucode_api_max = IWL6050_UCODE_API_MAX, .ucode_api_min = IWL6050_UCODE_API_MIN, @@ -483,7 +483,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { }; struct iwl_cfg iwl6050_2abg_cfg = { - .name = "6050 Series 2x2 ABG", + .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG", .fw_name_pre = IWL6050_FW_PRE, .ucode_api_max = IWL6050_UCODE_API_MAX, .ucode_api_min = IWL6050_UCODE_API_MIN, @@ -514,7 +514,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { }; struct iwl_cfg iwl6000_3agn_cfg = { - .name = "6000 Series 3x3 AGN", + .name = "Intel(R) Centrino(R) Ultimate-N 6300 AGN", .fw_name_pre = IWL6000_FW_PRE, .ucode_api_max = IWL6000_UCODE_API_MAX, .ucode_api_min = IWL6000_UCODE_API_MIN, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4b4b47676ad8..93931b61304b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3477,7 +3477,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); iwl_hw_detect(priv); - IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", + IWL_INFO(priv, "Detected %s, REV=0x%X\n", priv->cfg->name, priv->hw_rev); /* We disable the RETRY_TIMEOUT register (0x41) to keep -- cgit v1.2.3 From b74e31a9bc1013e69b85b139072485dc153453dd Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 1 Mar 2010 17:23:50 -0800 Subject: iwlwifi: Recover TX flow stall due to stuck queue Monitors the internal TX queues periodically. When a queue is stuck for some unknown conditions causing the throughput to drop and the transfer is stop, the driver will force firmware reload and bring the system back to normal operational state. The iwlwifi devices behave differently in this regard so this feature is made part of the ops infrastructure so we can have more control on how to monitor and recover from tx queue stall case per device. Signed-off-by: Trieu 'Andrew' Nguyen Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 3 + drivers/net/wireless/iwlwifi/iwl-3945.c | 2 + drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 9 +++ drivers/net/wireless/iwlwifi/iwl-6000.c | 8 +++ drivers/net/wireless/iwlwifi/iwl-agn.c | 16 +++++ drivers/net/wireless/iwlwifi/iwl-core.c | 93 +++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 7 +++ drivers/net/wireless/iwlwifi/iwl-dev.h | 10 ++++ drivers/net/wireless/iwlwifi/iwl-tx.c | 2 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 16 +++++ 11 files changed, 167 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index e31e8a3459b5..5a9cb70160f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -212,6 +212,7 @@ static struct iwl_lib_ops iwl1000_lib = { .set_ct_kill = iwl1000_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .recover_from_tx_stall = iwl_bg_monitor_recover, }; static const struct iwl_ops iwl1000_ops = { @@ -249,6 +250,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; struct iwl_cfg iwl1000_bg_cfg = { @@ -277,6 +279,7 @@ struct iwl_cfg iwl1000_bg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 11785e2c767a..21ae61dd3d51 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2820,6 +2820,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { .led_compensation = 64, .broken_powersave = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; static struct iwl_cfg iwl3945_abg_cfg = { @@ -2838,6 +2839,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .led_compensation = 64, .broken_powersave = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 7f9e448fe5e1..acca89a635a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2255,6 +2255,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .led_compensation = 61, .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; /* Module firmware */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 8ab28a760157..a01b3c59a5a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1499,6 +1499,7 @@ struct iwl_lib_ops iwl5000_lib = { .set_ct_kill = iwl5000_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .recover_from_tx_stall = iwl_bg_monitor_recover, }; static struct iwl_lib_ops iwl5150_lib = { @@ -1553,6 +1554,7 @@ static struct iwl_lib_ops iwl5150_lib = { .set_ct_kill = iwl5150_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .recover_from_tx_stall = iwl_bg_monitor_recover, }; static const struct iwl_ops iwl5000_ops = { @@ -1602,6 +1604,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; struct iwl_cfg iwl5100_bgn_cfg = { @@ -1628,6 +1631,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; struct iwl_cfg iwl5100_abg_cfg = { @@ -1652,6 +1656,7 @@ struct iwl_cfg iwl5100_abg_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; struct iwl_cfg iwl5100_agn_cfg = { @@ -1678,6 +1683,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; struct iwl_cfg iwl5350_agn_cfg = { @@ -1704,6 +1710,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; struct iwl_cfg iwl5150_agn_cfg = { @@ -1730,6 +1737,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; struct iwl_cfg iwl5150_abg_cfg = { @@ -1754,6 +1762,7 @@ struct iwl_cfg iwl5150_abg_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index fb7012289c3d..4fbc38cfd911 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -278,6 +278,7 @@ static struct iwl_lib_ops iwl6000_lib = { .set_ct_kill = iwl6000_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .recover_from_tx_stall = iwl_bg_monitor_recover, }; static const struct iwl_ops iwl6000_ops = { @@ -343,6 +344,7 @@ static struct iwl_lib_ops iwl6050_lib = { .set_calib_version = iwl6050_set_calib_version, }, .add_bcast_station = iwl_add_bcast_station, + .recover_from_tx_stall = iwl_bg_monitor_recover, }; static const struct iwl_ops iwl6050_ops = { @@ -386,6 +388,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; struct iwl_cfg iwl6000i_2abg_cfg = { @@ -417,6 +420,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; struct iwl_cfg iwl6000i_2bg_cfg = { @@ -448,6 +452,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; struct iwl_cfg iwl6050_2agn_cfg = { @@ -480,6 +485,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1500, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; struct iwl_cfg iwl6050_2abg_cfg = { @@ -511,6 +517,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1500, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; struct iwl_cfg iwl6000_3agn_cfg = { @@ -543,6 +550,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 93931b61304b..82b1a3fb54ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2074,6 +2074,13 @@ static void iwl_alive_start(struct iwl_priv *priv) /* After the ALIVE response, we can send host commands to the uCode */ set_bit(STATUS_ALIVE, &priv->status); + if (priv->cfg->ops->lib->recover_from_tx_stall) { + /* Enable timer to monitor the driver queues */ + mod_timer(&priv->monitor_recover, + jiffies + + msecs_to_jiffies(priv->cfg->monitor_recover_period)); + } + if (iwl_is_rfkill(priv)) return; @@ -3224,6 +3231,13 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) priv->ucode_trace.data = (unsigned long)priv; priv->ucode_trace.function = iwl_bg_ucode_trace; + if (priv->cfg->ops->lib->recover_from_tx_stall) { + init_timer(&priv->monitor_recover); + priv->monitor_recover.data = (unsigned long)priv; + priv->monitor_recover.function = + priv->cfg->ops->lib->recover_from_tx_stall; + } + if (!priv->cfg->use_isr_legacy) tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) iwl_irq_tasklet, (unsigned long)priv); @@ -3243,6 +3257,8 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) cancel_work_sync(&priv->beacon_update); del_timer_sync(&priv->statistics_periodic); del_timer_sync(&priv->ucode_trace); + if (priv->cfg->ops->lib->recover_from_tx_stall) + del_timer_sync(&priv->monitor_recover); } static void iwl_init_hw_rates(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d4c2a3e17c53..5180fb24cd38 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -3051,6 +3051,99 @@ int iwl_force_reset(struct iwl_priv *priv, int mode) } return 0; } +EXPORT_SYMBOL(iwl_force_reset); + +/** + * iwl_bg_monitor_recover - Timer callback to check for stuck queue and recover + * + * During normal condition (no queue is stuck), the timer is continually set to + * execute every monitor_recover_period milliseconds after the last timer + * expired. When the queue read_ptr is at the same place, the timer is + * shorten to 100mSecs. This is + * 1) to reduce the chance that the read_ptr may wrap around (not stuck) + * 2) to detect the stuck queues quicker before the station and AP can + * disassociate each other. + * + * This function monitors all the tx queues and recover from it if any + * of the queues are stuck. + * 1. It first check the cmd queue for stuck conditions. If it is stuck, + * it will recover by resetting the firmware and return. + * 2. Then, it checks for station association. If it associates it will check + * other queues. If any queue is stuck, it will recover by resetting + * the firmware. + * Note: It the number of times the queue read_ptr to be at the same place to + * be MAX_REPEAT+1 in order to consider to be stuck. + */ +/* + * The maximum number of times the read pointer of the tx queue at the + * same place without considering to be stuck. + */ +#define MAX_REPEAT (2) +static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt) +{ + struct iwl_tx_queue *txq; + struct iwl_queue *q; + + txq = &priv->txq[cnt]; + q = &txq->q; + /* queue is empty, skip */ + if (q->read_ptr != q->write_ptr) { + if (q->read_ptr == q->last_read_ptr) { + /* a queue has not been read from last time */ + if (q->repeat_same_read_ptr > MAX_REPEAT) { + IWL_ERR(priv, + "queue %d stuck %d time. Fw reload.\n", + q->id, q->repeat_same_read_ptr); + q->repeat_same_read_ptr = 0; + iwl_force_reset(priv, IWL_FW_RESET); + } else { + q->repeat_same_read_ptr++; + IWL_DEBUG_RADIO(priv, + "queue %d, not read %d time\n", + q->id, + q->repeat_same_read_ptr); + mod_timer(&priv->monitor_recover, jiffies + + msecs_to_jiffies(IWL_ONE_HUNDRED_MSECS)); + } + return 1; + } else { + q->last_read_ptr = q->read_ptr; + q->repeat_same_read_ptr = 0; + } + } + return 0; +} + +void iwl_bg_monitor_recover(unsigned long data) +{ + struct iwl_priv *priv = (struct iwl_priv *)data; + int cnt; + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + /* monitor and check for stuck cmd queue */ + if (iwl_check_stuck_queue(priv, IWL_CMD_QUEUE_NUM)) + return; + + /* monitor and check for other stuck queues */ + if (iwl_is_associated(priv)) { + for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { + /* skip as we already checked the command queue */ + if (cnt == IWL_CMD_QUEUE_NUM) + continue; + if (iwl_check_stuck_queue(priv, cnt)) + return; + } + } + /* + * Reschedule the timer to occur in + * priv->cfg->monitor_recover_period + */ + mod_timer(&priv->monitor_recover, + jiffies + msecs_to_jiffies(priv->cfg->monitor_recover_period)); +} +EXPORT_SYMBOL(iwl_bg_monitor_recover); #ifdef CONFIG_PM diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 2482a25d543f..c4cd1deb3b3e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -191,6 +191,8 @@ struct iwl_lib_ops { struct iwl_temp_ops temp_ops; /* station management */ void (*add_bcast_station)(struct iwl_priv *priv); + /* recover from tx queue stall */ + void (*recover_from_tx_stall)(unsigned long data); }; struct iwl_led_ops { @@ -295,6 +297,8 @@ struct iwl_cfg { const bool support_wimax_coexist; u8 plcp_delta_threshold; s32 chain_noise_scale; + /* timer period for monitor the driver queues */ + u32 monitor_recover_period; }; /*************************** @@ -568,6 +572,9 @@ static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); return pci_lnk_ctl; } + +void iwl_bg_monitor_recover(unsigned long data); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state); int iwl_pci_resume(struct pci_dev *pdev); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 9c676ea420b9..bb4cba508acf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -183,6 +183,10 @@ struct iwl_queue { int n_bd; /* number of BDs in this queue */ int write_ptr; /* 1-st empty entry (index) host_w*/ int read_ptr; /* last used entry (index) host_r*/ + /* use for monitoring and recovering the stuck queue */ + int last_read_ptr; /* storing the last read_ptr */ + /* number of time read_ptr and last_read_ptr are the same */ + u8 repeat_same_read_ptr; dma_addr_t dma_addr; /* physical addr for BD's */ int n_window; /* safe queue window */ u32 id; @@ -1044,6 +1048,11 @@ struct iwl_event_log { #define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) +/* timer constants use to monitor and recover stuck tx queues in mSecs */ +#define IWL_MONITORING_PERIOD (1000) +#define IWL_ONE_HUNDRED_MSECS (100) +#define IWL_SIXTY_SECS (60000) + enum iwl_reset { IWL_RF_RESET = 0, IWL_FW_RESET, @@ -1354,6 +1363,7 @@ struct iwl_priv { struct work_struct run_time_calib_work; struct timer_list statistics_periodic; struct timer_list ucode_trace; + struct timer_list monitor_recover; bool hw_ready; struct iwl_event_log event_log; diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 045e4a67344b..34c983833a8f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -322,6 +322,8 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, q->high_mark = 2; q->write_ptr = q->read_ptr = 0; + q->last_read_ptr = 0; + q->repeat_same_read_ptr = 0; return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 6687b9456554..4995134d7e4a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2501,6 +2501,13 @@ static void iwl3945_alive_start(struct iwl_priv *priv) /* After the ALIVE response, we can send commands to 3945 uCode */ set_bit(STATUS_ALIVE, &priv->status); + if (priv->cfg->ops->lib->recover_from_tx_stall) { + /* Enable timer to monitor the driver queues */ + mod_timer(&priv->monitor_recover, + jiffies + + msecs_to_jiffies(priv->cfg->monitor_recover_period)); + } + if (iwl_is_rfkill(priv)) return; @@ -3796,6 +3803,13 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) iwl3945_hw_setup_deferred_work(priv); + if (priv->cfg->ops->lib->recover_from_tx_stall) { + init_timer(&priv->monitor_recover); + priv->monitor_recover.data = (unsigned long)priv; + priv->monitor_recover.function = + priv->cfg->ops->lib->recover_from_tx_stall; + } + tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) iwl3945_irq_tasklet, (unsigned long)priv); } @@ -3808,6 +3822,8 @@ static void iwl3945_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work(&priv->scan_check); cancel_delayed_work(&priv->alive_start); cancel_work_sync(&priv->beacon_update); + if (priv->cfg->ops->lib->recover_from_tx_stall) + del_timer_sync(&priv->monitor_recover); } static struct attribute *iwl3945_sysfs_entries[] = { -- cgit v1.2.3 From beac5498b792ed8420885ee23e8d4f2885ee2d13 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 4 Mar 2010 13:38:58 -0800 Subject: iwlwifi: move plcp check to separated function Move the plcp error checking into stand alone function and pointed by ops to accommodate devices not needing this recovery. Signed-off-by: Trieu 'Andrew' Nguyen Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 + drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-6000.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-core.h | 5 +++ drivers/net/wireless/iwlwifi/iwl-rx.c | 58 ++++++++++++++++++++------------- 6 files changed, 47 insertions(+), 22 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 5a9cb70160f6..c6d6a0c2cd3c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -213,6 +213,7 @@ static struct iwl_lib_ops iwl1000_lib = { }, .add_bcast_station = iwl_add_bcast_station, .recover_from_tx_stall = iwl_bg_monitor_recover, + .recover_from_statistics = iwl_recover_from_statistics, }; static const struct iwl_ops iwl1000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index acca89a635a5..5efd60a5b988 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2221,6 +2221,7 @@ static struct iwl_lib_ops iwl4965_lib = { .set_ct_kill = iwl4965_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .recover_from_statistics = iwl_recover_from_statistics, }; static const struct iwl_ops iwl4965_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index a01b3c59a5a7..75f2a5156beb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1500,6 +1500,7 @@ struct iwl_lib_ops iwl5000_lib = { }, .add_bcast_station = iwl_add_bcast_station, .recover_from_tx_stall = iwl_bg_monitor_recover, + .recover_from_statistics = iwl_recover_from_statistics, }; static struct iwl_lib_ops iwl5150_lib = { @@ -1555,6 +1556,7 @@ static struct iwl_lib_ops iwl5150_lib = { }, .add_bcast_station = iwl_add_bcast_station, .recover_from_tx_stall = iwl_bg_monitor_recover, + .recover_from_statistics = iwl_recover_from_statistics, }; static const struct iwl_ops iwl5000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 4fbc38cfd911..b1f0e5c7e287 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -279,6 +279,7 @@ static struct iwl_lib_ops iwl6000_lib = { }, .add_bcast_station = iwl_add_bcast_station, .recover_from_tx_stall = iwl_bg_monitor_recover, + .recover_from_statistics = iwl_recover_from_statistics, }; static const struct iwl_ops iwl6000_ops = { @@ -345,6 +346,7 @@ static struct iwl_lib_ops iwl6050_lib = { }, .add_bcast_station = iwl_add_bcast_station, .recover_from_tx_stall = iwl_bg_monitor_recover, + .recover_from_statistics = iwl_recover_from_statistics, }; static const struct iwl_ops iwl6050_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index c4cd1deb3b3e..4251afb8bf5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -193,6 +193,9 @@ struct iwl_lib_ops { void (*add_bcast_station)(struct iwl_priv *priv); /* recover from tx queue stall */ void (*recover_from_tx_stall)(unsigned long data); + /* recover from errors showed in statistics */ + void (*recover_from_statistics)(struct iwl_priv *priv, + struct iwl_rx_packet *pkt); }; struct iwl_led_ops { @@ -434,6 +437,8 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); +void iwl_recover_from_statistics(struct iwl_priv *priv, + struct iwl_rx_packet *pkt); void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_reply_statistics(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 8116aa0d7678..d368b8df8d87 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -617,28 +617,18 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, #define REG_RECALIB_PERIOD (60) #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" -void iwl_rx_statistics(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) +/* + * This function checks for plcp error. + * - When the plcp error is exceeding the thresholds, it will reset the radio + * to improve the throughput. + */ +void iwl_recover_from_statistics(struct iwl_priv *priv, + struct iwl_rx_packet *pkt) { - int change; - struct iwl_rx_packet *pkt = rxb_addr(rxb); int combined_plcp_delta; unsigned int plcp_msec; unsigned long plcp_received_jiffies; - IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", - (int)sizeof(priv->statistics), - le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); - - change = ((priv->statistics.general.temperature != - pkt->u.stats.general.temperature) || - ((priv->statistics.flag & - STATISTICS_REPLY_FLG_HT40_MODE_MSK) != - (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); - -#ifdef CONFIG_IWLWIFI_DEBUG - iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); -#endif /* * check for plcp_err and trigger radio reset if it exceeds * the plcp error threshold plcp_delta. @@ -659,11 +649,11 @@ void iwl_rx_statistics(struct iwl_priv *priv, le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err)); if ((combined_plcp_delta > 0) && - ((combined_plcp_delta * 100) / plcp_msec) > + ((combined_plcp_delta * 100) / plcp_msec) > priv->cfg->plcp_delta_threshold) { /* - * if plcp_err exceed the threshold, the following - * data is printed in csv format: + * if plcp_err exceed the threshold, + * the following data is printed in csv format: * Text: plcp_err exceeded %d, * Received ofdm.plcp_err, * Current ofdm.plcp_err, @@ -678,9 +668,8 @@ void iwl_rx_statistics(struct iwl_priv *priv, le32_to_cpu(priv->statistics.rx.ofdm.plcp_err), le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err), le32_to_cpu( - priv->statistics.rx.ofdm_ht.plcp_err), + priv->statistics.rx.ofdm_ht.plcp_err), combined_plcp_delta, plcp_msec); - /* * Reset the RF radio due to the high plcp * error rate @@ -688,6 +677,31 @@ void iwl_rx_statistics(struct iwl_priv *priv, iwl_force_reset(priv, IWL_RF_RESET); } } +} +EXPORT_SYMBOL(iwl_recover_from_statistics); + +void iwl_rx_statistics(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + int change; + struct iwl_rx_packet *pkt = rxb_addr(rxb); + + + IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", + (int)sizeof(priv->statistics), + le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); + + change = ((priv->statistics.general.temperature != + pkt->u.stats.general.temperature) || + ((priv->statistics.flag & + STATISTICS_REPLY_FLG_HT40_MODE_MSK) != + (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); + +#ifdef CONFIG_IWLWIFI_DEBUG + iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); +#endif + if (priv->cfg->ops->lib->recover_from_statistics) + priv->cfg->ops->lib->recover_from_statistics(priv, pkt); memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); -- cgit v1.2.3 From d5a0ffa3eaf9e898f25a925813f1a723be7808f8 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 4 Mar 2010 13:38:59 -0800 Subject: iwlwifi: Recover TX flow failure Monitors the tx statistics to detect the drop in throughput. When the throughput drops, the ratio of the actual_ack_count and the expected_ack_count also drops. At the same time, the aggregated ba_timeout (the number of ba timeout retries) also rises. If the actual_ack_count/expected_ack_count ratio is 0 and the number of ba timeout retries rises to BA_TIMEOUT_MAX, no tx packets can be delivered. Reloading the uCode and bring the system back to normal operational state. Signed-off-by: Trieu 'Andrew' Nguyen Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 14 +++++++++- drivers/net/wireless/iwlwifi/iwl-dev.h | 5 ++++ drivers/net/wireless/iwlwifi/iwl-rx.c | 50 +++++++++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 82b1a3fb54ef..e69e6256a41b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2916,10 +2916,21 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return ret; case IEEE80211_AMPDU_TX_START: IWL_DEBUG_HT(priv, "start Tx\n"); - return iwl_tx_agg_start(priv, sta->addr, tid, ssn); + ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn); + if (ret == 0) { + priv->_agn.agg_tids_count++; + IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", + priv->_agn.agg_tids_count); + } + return ret; case IEEE80211_AMPDU_TX_STOP: IWL_DEBUG_HT(priv, "stop Tx\n"); ret = iwl_tx_agg_stop(priv, sta->addr, tid); + if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { + priv->_agn.agg_tids_count--; + IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", + priv->_agn.agg_tids_count); + } if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return 0; else @@ -3303,6 +3314,7 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->iw_mode = NL80211_IFTYPE_STATION; priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; + priv->_agn.agg_tids_count = 0; /* initialize force reset */ priv->force_reset[IWL_RF_RESET].reset_duration = diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index bb4cba508acf..e847e6197a3d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1300,6 +1300,11 @@ struct iwl_priv { int ict_index; u32 inta; bool use_ict; + /* + * reporting the number of tids has AGG on. 0 means + * no AGGREGATION + */ + u8 agg_tids_count; } _agn; #endif }; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index d368b8df8d87..7aef285d2818 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -616,9 +616,18 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, #define REG_RECALIB_PERIOD (60) +/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ +#define ACK_CNT_RATIO (50) +#define BA_TIMEOUT_CNT (5) +#define BA_TIMEOUT_MAX (16) + #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" /* - * This function checks for plcp error. + * This function checks for plcp error, ACK count ratios, aggregated BA + * timeout retries. + * - When the ACK count ratio is 0 and aggregated BA timeout retries is + * exceeding the BA_TIMEOUT_MAX, it will recover the failure by resetting + * the firmware. * - When the plcp error is exceeding the thresholds, it will reset the radio * to improve the throughput. */ @@ -628,6 +637,45 @@ void iwl_recover_from_statistics(struct iwl_priv *priv, int combined_plcp_delta; unsigned int plcp_msec; unsigned long plcp_received_jiffies; + int actual_ack_cnt_delta; + int expected_ack_cnt_delta; + int ba_timeout_delta; + + actual_ack_cnt_delta = + le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - + le32_to_cpu(priv->statistics.tx.actual_ack_cnt); + expected_ack_cnt_delta = + le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) - + le32_to_cpu(priv->statistics.tx.expected_ack_cnt); + ba_timeout_delta = + le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) - + le32_to_cpu(priv->statistics.tx.agg.ba_timeout); + if ((priv->_agn.agg_tids_count > 0) && + (expected_ack_cnt_delta > 0) && + (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) + < ACK_CNT_RATIO) && + (ba_timeout_delta > BA_TIMEOUT_CNT)) { + IWL_DEBUG_RADIO(priv, "actual_ack_cnt delta = %d," + " expected_ack_cnt = %d\n", + actual_ack_cnt_delta, expected_ack_cnt_delta); + +#ifdef CONFIG_IWLWIFI_DEBUG + IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", + priv->delta_statistics.tx.rx_detected_cnt); + IWL_DEBUG_RADIO(priv, + "ack_or_ba_timeout_collision delta = %d\n", + priv->delta_statistics.tx. + ack_or_ba_timeout_collision); +#endif + IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", + ba_timeout_delta); + if ((actual_ack_cnt_delta == 0) && + (ba_timeout_delta >= BA_TIMEOUT_MAX)) { + IWL_DEBUG_RADIO(priv, + "call iwl_force_reset(IWL_FW_RESET)\n"); + iwl_force_reset(priv, IWL_FW_RESET); + } + } /* * check for plcp_err and trigger radio reset if it exceeds -- cgit v1.2.3 From fa8f130c504223d25c116b3d23787f465dfb1317 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 5 Mar 2010 14:22:46 -0800 Subject: iwlwifi: code cleanup for connectivity recovery Split the connectivity check and recovery routine into separated functions based on the types 1. iwl_good_ack_health() - check for ack count 2. iwl_good_plcp_health() - check for plcp error Based on the type of errors being detected, different recovery methods will be used to bring the system back to normal operational state. Because different NIC has different HW and uCode, the behavior is also different; these functions thus now form part of the ops infrastructure, so we can have more control on how to monitor and recover from error condition case per device. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 3 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 6 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 6 +- drivers/net/wireless/iwlwifi/iwl-core.h | 11 +++- drivers/net/wireless/iwlwifi/iwl-rx.c | 97 ++++++++++++++++++++++----------- 6 files changed, 85 insertions(+), 40 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index c6d6a0c2cd3c..9e392896005d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -213,7 +213,8 @@ static struct iwl_lib_ops iwl1000_lib = { }, .add_bcast_station = iwl_add_bcast_station, .recover_from_tx_stall = iwl_bg_monitor_recover, - .recover_from_statistics = iwl_recover_from_statistics, + .check_plcp_health = iwl_good_plcp_health, + .check_ack_health = iwl_good_ack_health, }; static const struct iwl_ops iwl1000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 5efd60a5b988..3949133d9ee2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2221,7 +2221,7 @@ static struct iwl_lib_ops iwl4965_lib = { .set_ct_kill = iwl4965_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, - .recover_from_statistics = iwl_recover_from_statistics, + .check_plcp_health = iwl_good_plcp_health, }; static const struct iwl_ops iwl4965_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 75f2a5156beb..2267cad49cbf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1500,7 +1500,8 @@ struct iwl_lib_ops iwl5000_lib = { }, .add_bcast_station = iwl_add_bcast_station, .recover_from_tx_stall = iwl_bg_monitor_recover, - .recover_from_statistics = iwl_recover_from_statistics, + .check_plcp_health = iwl_good_plcp_health, + .check_ack_health = iwl_good_ack_health, }; static struct iwl_lib_ops iwl5150_lib = { @@ -1556,7 +1557,8 @@ static struct iwl_lib_ops iwl5150_lib = { }, .add_bcast_station = iwl_add_bcast_station, .recover_from_tx_stall = iwl_bg_monitor_recover, - .recover_from_statistics = iwl_recover_from_statistics, + .check_plcp_health = iwl_good_plcp_health, + .check_ack_health = iwl_good_ack_health, }; static const struct iwl_ops iwl5000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index b1f0e5c7e287..d75799946a7e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -279,7 +279,8 @@ static struct iwl_lib_ops iwl6000_lib = { }, .add_bcast_station = iwl_add_bcast_station, .recover_from_tx_stall = iwl_bg_monitor_recover, - .recover_from_statistics = iwl_recover_from_statistics, + .check_plcp_health = iwl_good_plcp_health, + .check_ack_health = iwl_good_ack_health, }; static const struct iwl_ops iwl6000_ops = { @@ -346,7 +347,8 @@ static struct iwl_lib_ops iwl6050_lib = { }, .add_bcast_station = iwl_add_bcast_station, .recover_from_tx_stall = iwl_bg_monitor_recover, - .recover_from_statistics = iwl_recover_from_statistics, + .check_plcp_health = iwl_good_plcp_health, + .check_ack_health = iwl_good_ack_health, }; static const struct iwl_ops iwl6050_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4251afb8bf5e..b3e698b576e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -193,8 +193,11 @@ struct iwl_lib_ops { void (*add_bcast_station)(struct iwl_priv *priv); /* recover from tx queue stall */ void (*recover_from_tx_stall)(unsigned long data); - /* recover from errors showed in statistics */ - void (*recover_from_statistics)(struct iwl_priv *priv, + /* check for plcp health */ + bool (*check_plcp_health)(struct iwl_priv *priv, + struct iwl_rx_packet *pkt); + /* check for ack health */ + bool (*check_ack_health)(struct iwl_priv *priv, struct iwl_rx_packet *pkt); }; @@ -437,7 +440,9 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); -void iwl_recover_from_statistics(struct iwl_priv *priv, +bool iwl_good_plcp_health(struct iwl_priv *priv, + struct iwl_rx_packet *pkt); +bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt); void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 7aef285d2818..b6a64d83718a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -621,24 +621,18 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, #define BA_TIMEOUT_CNT (5) #define BA_TIMEOUT_MAX (16) -#define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" -/* - * This function checks for plcp error, ACK count ratios, aggregated BA - * timeout retries. - * - When the ACK count ratio is 0 and aggregated BA timeout retries is - * exceeding the BA_TIMEOUT_MAX, it will recover the failure by resetting - * the firmware. - * - When the plcp error is exceeding the thresholds, it will reset the radio - * to improve the throughput. +/** + * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries. + * + * When the ACK count ratio is 0 and aggregated BA timeout retries exceeding + * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal + * operation state. */ -void iwl_recover_from_statistics(struct iwl_priv *priv, - struct iwl_rx_packet *pkt) +bool iwl_good_ack_health(struct iwl_priv *priv, + struct iwl_rx_packet *pkt) { - int combined_plcp_delta; - unsigned int plcp_msec; - unsigned long plcp_received_jiffies; - int actual_ack_cnt_delta; - int expected_ack_cnt_delta; + bool rc = true; + int actual_ack_cnt_delta, expected_ack_cnt_delta; int ba_timeout_delta; actual_ack_cnt_delta = @@ -669,13 +663,27 @@ void iwl_recover_from_statistics(struct iwl_priv *priv, #endif IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", ba_timeout_delta); - if ((actual_ack_cnt_delta == 0) && - (ba_timeout_delta >= BA_TIMEOUT_MAX)) { - IWL_DEBUG_RADIO(priv, - "call iwl_force_reset(IWL_FW_RESET)\n"); - iwl_force_reset(priv, IWL_FW_RESET); - } + if (!actual_ack_cnt_delta && + (ba_timeout_delta >= BA_TIMEOUT_MAX)) + rc = false; } + return rc; +} +EXPORT_SYMBOL(iwl_good_ack_health); + +/** + * iwl_good_plcp_health - checks for plcp error. + * + * When the plcp error is exceeding the thresholds, reset the radio + * to improve the throughput. + */ +bool iwl_good_plcp_health(struct iwl_priv *priv, + struct iwl_rx_packet *pkt) +{ + bool rc = true; + int combined_plcp_delta; + unsigned int plcp_msec; + unsigned long plcp_received_jiffies; /* * check for plcp_err and trigger radio reset if it exceeds @@ -710,7 +718,8 @@ void iwl_recover_from_statistics(struct iwl_priv *priv, * combined_plcp_delta, * plcp_msec */ - IWL_DEBUG_RADIO(priv, PLCP_MSG, + IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " + "%u, %u, %u, %u, %d, %u mSecs\n", priv->cfg->plcp_delta_threshold, le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err), le32_to_cpu(priv->statistics.rx.ofdm.plcp_err), @@ -718,15 +727,42 @@ void iwl_recover_from_statistics(struct iwl_priv *priv, le32_to_cpu( priv->statistics.rx.ofdm_ht.plcp_err), combined_plcp_delta, plcp_msec); - /* - * Reset the RF radio due to the high plcp - * error rate - */ - iwl_force_reset(priv, IWL_RF_RESET); + rc = false; + } + } + return rc; +} +EXPORT_SYMBOL(iwl_good_plcp_health); + +static void iwl_recover_from_statistics(struct iwl_priv *priv, + struct iwl_rx_packet *pkt) +{ + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + if (iwl_is_associated(priv)) { + if (priv->cfg->ops->lib->check_ack_health) { + if (!priv->cfg->ops->lib->check_ack_health( + priv, pkt)) { + /* + * low ack count detected + * restart Firmware + */ + IWL_ERR(priv, "low ack count detected, " + "restart firmware\n"); + iwl_force_reset(priv, IWL_FW_RESET); + } + } else if (priv->cfg->ops->lib->check_plcp_health) { + if (!priv->cfg->ops->lib->check_plcp_health( + priv, pkt)) { + /* + * high plcp error detected + * reset Radio + */ + iwl_force_reset(priv, IWL_RF_RESET); + } } } } -EXPORT_SYMBOL(iwl_recover_from_statistics); void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) @@ -748,8 +784,7 @@ void iwl_rx_statistics(struct iwl_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); #endif - if (priv->cfg->ops->lib->recover_from_statistics) - priv->cfg->ops->lib->recover_from_statistics(priv, pkt); + iwl_recover_from_statistics(priv, pkt); memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); -- cgit v1.2.3 From e21247cc4a37296f57281a472e961ff09de0e98d Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Mon, 1 Mar 2010 23:13:29 +0800 Subject: ath9k: decrease size of ath9k.ko From e74b075cdb143d45be9b371ee8a8e2dcfc15ab34 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 27 Feb 2010 23:50:54 +0800 Subject: [PATCH] ath9k: decrease size of ath9k.ko The patch defines the fields of 'valid_single_stream' and 'valid' in struct ath_rate_table as char type, so decrease the size of ath9k.ko about 2KB. old ath9k.ko [tom@tom-lei ath9k]$ size ath9k.ko text data bss dec hex filename 69344 3080 168 72592 11b90 ath9k.ko new ath9k.ko [tom@tom-lei ath9k]$ size ath9k.ko text data bss dec hex filename 67304 3080 168 70552 11398 ath9k.ko Signed-off-by: Larry Finger Signed-off-by: Ming Lei Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index f4818e4fa4b0..36083dde863d 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -110,8 +110,8 @@ struct ath_rate_table { int rate_cnt; int mcs_start; struct { - int valid; - int valid_single_stream; + u8 valid; + u8 valid_single_stream; u8 phy; u32 ratekbps; u32 user_ratekbps; -- cgit v1.2.3 From 70807e99dbb0c5847668b617caf0ad7f876a23d9 Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Mar 2010 14:25:14 +0530 Subject: ath9k_hw: update initialization values for AR9271 Update the register initialization values for AR9271. This is based on our last review from our systems team. Signed-off-by: Sujith Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 65 ++++++++------ drivers/net/wireless/ath/ath9k/hw.h | 5 ++ drivers/net/wireless/ath/ath9k/initvals.h | 141 +++++++++++++++++++++--------- 3 files changed, 146 insertions(+), 65 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 1fb14edfcb2a..9de46036db0e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -603,9 +603,23 @@ static void ath9k_hw_init_mode_regs(struct ath_hw *ah) ARRAY_SIZE(ar9271Modes_9271), 6); INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271, ARRAY_SIZE(ar9271Common_9271), 2); + INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271, + ar9271Common_normal_cck_fir_coeff_9271, + ARRAY_SIZE(ar9271Common_normal_cck_fir_coeff_9271), 2); + INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271, + ar9271Common_japan_2484_cck_fir_coeff_9271, + ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2); INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only, ar9271Modes_9271_1_0_only, ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6); + INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg, + ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6); + INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271, + ar9271Modes_high_power_tx_gain_9271, + ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6); + INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, + ar9271Modes_normal_power_tx_gain_9271, + ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6); return; } @@ -1266,26 +1280,6 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, { u32 val; - if (AR_SREV_9271(ah)) { - /* - * Enable spectral scan to solution for issues with stuck - * beacons on AR9271 1.0. The beacon stuck issue is not seeon on - * AR9271 1.1 - */ - if (AR_SREV_9271_10(ah)) { - val = REG_READ(ah, AR_PHY_SPECTRAL_SCAN) | - AR_PHY_SPECTRAL_SCAN_ENABLE; - REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); - } - else if (AR_SREV_9271_11(ah)) - /* - * change AR_PHY_RF_CTL3 setting to fix MAC issue - * present on AR9271 1.1 - */ - REG_WRITE(ah, AR_PHY_RF_CTL3, 0x3a020001); - return; - } - /* * Set the RX_ABORT and RX_DIS and clear if off only after * RXE is set for MAC. This prevents frames with corrupted @@ -1294,8 +1288,10 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); if (AR_SREV_9280_10_OR_LATER(ah)) { - val = REG_READ(ah, AR_PCU_MISC_MODE2) & - (~AR_PCU_MISC_MODE2_HWWAR1); + val = REG_READ(ah, AR_PCU_MISC_MODE2); + + if (!AR_SREV_9271(ah)) + val &= ~AR_PCU_MISC_MODE2_HWWAR1; if (AR_SREV_9287_10_OR_LATER(ah)) val = val & (~AR_PCU_MISC_MODE2_HWWAR2); @@ -1439,7 +1435,10 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, return -EINVAL; } + /* Set correct baseband to analog shift setting to access analog chips */ REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Write ADDAC shifts */ REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); ah->eep_ops->set_addac(ah, chan); @@ -1451,9 +1450,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, sizeof(u32) * ah->iniAddac.ia_rows * ah->iniAddac.ia_columns; + /* For AR5416 2.0/2.1 */ memcpy(ah->addac5416_21, ah->iniAddac.ia_array, addacSize); + /* override CLKDRV value at [row, column] = [31, 1] */ (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0; temp.ia_array = ah->addac5416_21; @@ -1485,6 +1486,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, AR_SREV_9287_10_OR_LATER(ah)) REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); + if (AR_SREV_9271_10(ah)) + REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only, + modesIndex, regWrites); + + /* Write common array parameters */ for (i = 0; i < ah->iniCommon.ia_rows; i++) { u32 reg = INI_RA(&ah->iniCommon, i, 0); u32 val = INI_RA(&ah->iniCommon, i, 1); @@ -1499,11 +1505,16 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, DO_DELAY(regWrites); } - ath9k_hw_write_regs(ah, freqIndex, regWrites); + if (AR_SREV_9271(ah)) { + if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1) + REG_WRITE_ARRAY(&ah->iniModes_high_power_tx_gain_9271, + modesIndex, regWrites); + else + REG_WRITE_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, + modesIndex, regWrites); + } - if (AR_SREV_9271_10(ah)) - REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only, - modesIndex, regWrites); + ath9k_hw_write_regs(ah, freqIndex, regWrites); if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, @@ -1517,6 +1528,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, if (OLC_FOR_AR9280_20_LATER) ath9k_olc_init(ah); + /* Set TX power */ ah->eep_ops->set_txpower(ah, chan, ath9k_regd_get_ctl(regulatory, chan), channel->max_antenna_gain * 2, @@ -1524,6 +1536,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, min((u32) MAX_RATE_POWER, (u32) regulatory->power_limit)); + /* Write analog registers */ if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, "ar5416SetRfRegs failed\n"); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 20d90268ce31..e63edfb91590 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -599,6 +599,11 @@ struct ath_hw { struct ar5416IniArray iniModes_9271_1_0_only; struct ar5416IniArray iniCckfirNormal; struct ar5416IniArray iniCckfirJapan2484; + struct ar5416IniArray iniCommon_normal_cck_fir_coeff_9271; + struct ar5416IniArray iniCommon_japan_2484_cck_fir_coeff_9271; + struct ar5416IniArray iniModes_9271_ANI_reg; + struct ar5416IniArray iniModes_high_power_tx_gain_9271; + struct ar5416IniArray iniModes_normal_power_tx_gain_9271; u32 intr_gen_timer_trigger; u32 intr_gen_timer_thresh; diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h index 8a3bf3ab998d..177bdeb84ad7 100644 --- a/drivers/net/wireless/ath/ath9k/initvals.h +++ b/drivers/net/wireless/ath/ath9k/initvals.h @@ -6441,7 +6441,7 @@ static const u_int32_t ar9271Modes_9271[][6] = { { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, + { 0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, @@ -6455,8 +6455,8 @@ static const u_int32_t ar9271Modes_9271[][6] = { { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, + { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, @@ -6569,7 +6569,7 @@ static const u_int32_t ar9271Modes_9271[][6] = { { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, + { 0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, @@ -6583,8 +6583,8 @@ static const u_int32_t ar9271Modes_9271[][6] = { { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, + { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, @@ -6683,25 +6683,6 @@ static const u_int32_t ar9271Modes_9271[][6] = { { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652 }, - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000 }, - { 0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000 }, - { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, - { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, - { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, }; @@ -6879,7 +6860,7 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x00008258, 0x00000000 }, { 0x0000825c, 0x400000ff }, { 0x00008260, 0x00080922 }, - { 0x00008264, 0x88a00010 }, + { 0x00008264, 0xa8a00010 }, { 0x00008270, 0x00000000 }, { 0x00008274, 0x40000000 }, { 0x00008278, 0x003e4180 }, @@ -6910,13 +6891,10 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x00007810, 0x71c0d388 }, { 0x00007814, 0x924934a8 }, { 0x0000781c, 0x00000000 }, - { 0x00007820, 0x00000c04 }, - { 0x00007824, 0x00d8abff }, { 0x00007828, 0x66964300 }, { 0x0000782c, 0x8db6d961 }, { 0x00007830, 0x8db6d96c }, { 0x00007834, 0x6140008b }, - { 0x00007838, 0x00000029 }, { 0x0000783c, 0x72ee0a72 }, { 0x00007840, 0xbbfffffc }, { 0x00007844, 0x000c0db6 }, @@ -6929,7 +6907,6 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x00007860, 0x21084210 }, { 0x00007864, 0xf7d7ffde }, { 0x00007868, 0xc2034080 }, - { 0x0000786c, 0x48609eb4 }, { 0x00007870, 0x10142c00 }, { 0x00009808, 0x00000000 }, { 0x0000980c, 0xafe68e30 }, @@ -6982,9 +6959,6 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x000099e8, 0x3c466478 }, { 0x000099ec, 0x0cc80caa }, { 0x000099f0, 0x00000000 }, - { 0x0000a1f4, 0x00000000 }, - { 0x0000a1f8, 0x71733d01 }, - { 0x0000a1fc, 0xd0ad5c12 }, { 0x0000a208, 0x803e68c8 }, { 0x0000a210, 0x4080a333 }, { 0x0000a214, 0x00206c10 }, @@ -7004,13 +6978,9 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x0000a260, 0xdfa90f01 }, { 0x0000a268, 0x00000000 }, { 0x0000a26c, 0x0ebae9e6 }, - { 0x0000a278, 0x3bdef7bd }, - { 0x0000a27c, 0x050e83bd }, { 0x0000a388, 0x0c000000 }, { 0x0000a38c, 0x20202020 }, { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x3bdef7bd }, - { 0x0000a398, 0x000003bd }, { 0x0000a39c, 0x00000001 }, { 0x0000a3a0, 0x00000000 }, { 0x0000a3a4, 0x00000000 }, @@ -7025,8 +6995,6 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x0000a3cc, 0x20202020 }, { 0x0000a3d0, 0x20202020 }, { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x3bdef7bd }, - { 0x0000a3e0, 0x000003bd }, { 0x0000a3e4, 0x00000000 }, { 0x0000a3e8, 0x18c43433 }, { 0x0000a3ec, 0x00f70081 }, @@ -7046,7 +7014,102 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x0000d384, 0xf3307ff0 }, }; +static const u_int32_t ar9271Common_normal_cck_fir_coeff_9271[][2] = { + { 0x0000a1f4, 0x00fffeff }, + { 0x0000a1f8, 0x00f5f9ff }, + { 0x0000a1fc, 0xb79f6427 }, +}; + +static const u_int32_t ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = { + { 0x0000a1f4, 0x00000000 }, + { 0x0000a1f8, 0xefff0301 }, + { 0x0000a1fc, 0xca9228ee }, +}; + static const u_int32_t ar9271Modes_9271_1_0_only[][6] = { { 0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311 }, { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, }; + +static const u_int32_t ar9271Modes_9271_ANI_reg[][6] = { + { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, + { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, + { 0x0000986c, 0x06903881, 0x06903881, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, + { 0x0000a208, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8 }, + { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, +}; + +static const u_int32_t ar9271Modes_normal_power_tx_gain_9271[][6] = { + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000 }, + { 0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007838, 0x00000029, 0x00000029, 0x00000029, 0x00000029, 0x00000029 }, + { 0x00007824, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff }, + { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, + { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, + { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652 }, + { 0x0000a278, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd }, + { 0x0000a27c, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd }, + { 0x0000a394, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd }, + { 0x0000a398, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd }, + { 0x0000a3dc, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd }, + { 0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd }, +}; + +static const u_int32_t ar9271Modes_high_power_tx_gain_9271[][6] = { + { 0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0001b240, 0x0001b240, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x0001d241, 0x0001d241, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0001f600, 0x0001f600, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00022800, 0x00022800, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00026802, 0x00026802, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0002b805, 0x0002b805, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0002ea41, 0x0002ea41, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x00038b00, 0x00038b00, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0003ab40, 0x0003ab40, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0003cd80, 0x0003cd80, 0x00000000 }, + { 0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007838, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b }, + { 0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff }, + { 0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba, 0x08609eb6 }, + { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a212652, 0x0a212652, 0x0a22a652 }, + { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063, 0x05018063 }, + { 0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63 }, + { 0x0000a398, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063 }, + { 0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63 }, + { 0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063 }, +}; -- cgit v1.2.3 From 5b5fa3558db7451f4744ef92f2b1830d05b9307b Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Mar 2010 14:25:15 +0530 Subject: ath9k_hw: add GPIO setup code for AR9271 Assign the proper number of GPIO pins for AR9271. Signed-off-by: Sujith Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 11 +++++++++-- drivers/net/wireless/ath/ath9k/reg.h | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 9de46036db0e..7b1ba6fa4bec 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -3229,7 +3229,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) else pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; - if (AR_SREV_9285_10_OR_LATER(ah)) + if (AR_SREV_9271(ah)) + pCap->num_gpio_pins = AR9271_NUM_GPIO; + else if (AR_SREV_9285_10_OR_LATER(ah)) pCap->num_gpio_pins = AR9285_NUM_GPIO; else if (AR_SREV_9280_10_OR_LATER(ah)) pCap->num_gpio_pins = AR928X_NUM_GPIO; @@ -3465,7 +3467,9 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) if (gpio >= ah->caps.num_gpio_pins) return 0xffffffff; - if (AR_SREV_9287_10_OR_LATER(ah)) + if (AR_SREV_9271(ah)) + return MS_REG_READ(AR9271, gpio) != 0; + else if (AR_SREV_9287_10_OR_LATER(ah)) return MS_REG_READ(AR9287, gpio) != 0; else if (AR_SREV_9285_10_OR_LATER(ah)) return MS_REG_READ(AR9285, gpio) != 0; @@ -3494,6 +3498,9 @@ EXPORT_SYMBOL(ath9k_hw_cfg_output); void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) { + if (AR_SREV_9271(ah)) + val = ~val; + REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), AR_GPIO_BIT(gpio)); } diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 72cfa8ebd9ae..198e41dd38a6 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -940,6 +940,7 @@ enum { #define AR928X_NUM_GPIO 10 #define AR9285_NUM_GPIO 12 #define AR9287_NUM_GPIO 11 +#define AR9271_NUM_GPIO 16 #define AR_GPIO_IN_OUT 0x4048 #define AR_GPIO_IN_VAL 0x0FFFC000 @@ -950,6 +951,8 @@ enum { #define AR9285_GPIO_IN_VAL_S 12 #define AR9287_GPIO_IN_VAL 0x003FF800 #define AR9287_GPIO_IN_VAL_S 11 +#define AR9271_GPIO_IN_VAL 0xFFFF0000 +#define AR9271_GPIO_IN_VAL_S 16 #define AR_GPIO_OE_OUT 0x404c #define AR_GPIO_OE_OUT_DRV 0x3 -- cgit v1.2.3 From 527d485fd8765e1df1dd9114f5c623253d6349c3 Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Mar 2010 14:25:16 +0530 Subject: ath9k_hw: skip chip tests for AR9271 The chip test is not required for AR9271 on the host driver code as the firmware will do the test internally on its own. Signed-off-by: Sujith Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 7b1ba6fa4bec..b1a4a8352f40 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -499,8 +499,10 @@ static int ath9k_hw_post_init(struct ath_hw *ah) { int ecode; - if (!ath9k_hw_chip_test(ah)) - return -ENODEV; + if (!AR_SREV_9271(ah)) { + if (!ath9k_hw_chip_test(ah)) + return -ENODEV; + } ecode = ath9k_hw_rf_claim(ah); if (ecode != 0) -- cgit v1.2.3 From e492d7cfdbb49f364529bc1642b978d85654c398 Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Mar 2010 14:25:17 +0530 Subject: ath9k_hw: fix TX descriptor setup for AR9271 The TX descriptors setup for AR971 requires the same setup as AR9285, so use that. Signed-off-by: Sujith Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 589490b69ddc..7af823a1527d 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -351,7 +351,7 @@ void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, ads->ds_ctl6 = SM(keyType, AR_EncrType); - if (AR_SREV_9285(ah)) { + if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) { ads->ds_ctl8 = 0; ads->ds_ctl9 = 0; ads->ds_ctl10 = 0; -- cgit v1.2.3 From 14b3af381df6359b15416df350e4e11892a52ab3 Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Mar 2010 14:25:18 +0530 Subject: ath9k_hw: Fix full sleep setup for AR9271 After telling the AR9271 to go into full sleep we do not need to clear the RTC reset signal. Signed-off-by: Sujith Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index b1a4a8352f40..023c38bb846b 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2453,7 +2453,7 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) if (!AR_SREV_9100(ah)) REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); - if(!AR_SREV_5416(ah)) + if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah)) REG_CLR_BIT(ah, (AR_RTC_RESET), AR_RTC_RESET_EN); } -- cgit v1.2.3 From 6398dc039d92b12805a900b3f82a033007a5b465 Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Mar 2010 14:25:19 +0530 Subject: ath9k_hw: fix noisefloor history buffer usage on AR9271 Noisefloor calibration involves querying hardware for samples and storing this information on a history buffer in hardware for actual noisefloor calibration processing in hardware. The history buffer supports collecting information for all Atheros hardware, one history buffer slot for each chain on each channel used for MIMO operation. For current hardware this means one history buffer slot for each chain on both the control (or primary) channel and the extension (or secondary) channel. We know which noisefloor registers to poke for collecting noisefloor data through the chainmask. For AR9285 and AR9271 devices, both 1x1, the chaimmask is defined as 0x9 = 0b0001001. The first four bits represent each chain out of a maximum of 4 chains [0-3] on the primary channel. The last four bits represent each chain on the extension channel. A chainmask of 0x9 therefore indicates chain 1 is active on both the primary and the extension channel. AR9271 only requires collecting and storing noisefloor history buffer data for the first chain on both the control and extension channel (nfarray[0] and nfarray[3]) so fix the code and avoid which reads and writes to the history buffer for the other chains. Since the noisefloor varies depending on the number of chains your device supports also initialize the noisefloor history buffer with reasonable values seen on 1x1 devices such as AR9285. Signed-off-by: Sujith Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 238a5744d8e9..0c3e9c8fa017 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -103,7 +103,7 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, "NF calibrated [ctl] [chain 0] is %d\n", nf); nfarray[0] = nf; - if (!AR_SREV_9285(ah)) { + if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) { if (AR_SREV_9280_10_OR_LATER(ah)) nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR); @@ -141,7 +141,7 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, "NF calibrated [ext] [chain 0] is %d\n", nf); nfarray[3] = nf; - if (!AR_SREV_9285(ah)) { + if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) { if (AR_SREV_9280_10_OR_LATER(ah)) nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR); @@ -621,7 +621,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) u8 chainmask, rx_chain_status; rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); - if (AR_SREV_9285(ah)) + if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) chainmask = 0x9; else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) @@ -715,7 +715,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) if (AR_SREV_9280(ah)) noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; - else if (AR_SREV_9285(ah)) + else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; else if (AR_SREV_9287(ah)) noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE; -- cgit v1.2.3 From 2cbfaea48500ce98588e31bd806bbfb524b36b31 Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Mar 2010 14:25:20 +0530 Subject: ath9k_hw: restrict valid nf readings for AR9271 to -114 Noisefloor values read on AR9271 are unreliable if they are less than -114, set those statically to -116. Signed-off-by: Sujith Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 0c3e9c8fa017..e76dd7498653 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -101,6 +101,10 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, nf = 0 - ((nf ^ 0x1ff) + 1); ath_print(common, ATH_DBG_CALIBRATE, "NF calibrated [ctl] [chain 0] is %d\n", nf); + + if (AR_SREV_9271(ah) && (nf >= -114)) + nf = -116; + nfarray[0] = nf; if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) { @@ -139,6 +143,10 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, nf = 0 - ((nf ^ 0x1ff) + 1); ath_print(common, ATH_DBG_CALIBRATE, "NF calibrated [ext] [chain 0] is %d\n", nf); + + if (AR_SREV_9271(ah) && (nf >= -114)) + nf = -116; + nfarray[3] = nf; if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) { -- cgit v1.2.3 From 02afa2a01b74ed3e8f3a85be11919b33f4ad4f02 Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Mar 2010 14:25:21 +0530 Subject: ath9k_hw: use the skip count for PA calibration on AR9271 Periodic power amplifier offset calibration is skipped on ath9k algorithmically, this is required on AR9271. Signed-off-by: Sujith Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index e76dd7498653..d5026e4f484b 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -1059,9 +1059,12 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, /* Do NF cal only at longer intervals */ if (longcal) { /* Do periodic PAOffset Cal */ - if (AR_SREV_9271(ah)) - ath9k_hw_9271_pa_cal(ah, false); - else if (AR_SREV_9285_11_OR_LATER(ah)) { + if (AR_SREV_9271(ah)) { + if (!ah->pacal_info.skipcount) + ath9k_hw_9271_pa_cal(ah, false); + else + ah->pacal_info.skipcount--; + } else if (AR_SREV_9285_11_OR_LATER(ah)) { if (!ah->pacal_info.skipcount) ath9k_hw_9285_pa_cal(ah, false); else -- cgit v1.2.3 From 25e2ab17fd77e752597050980cec4efae7f87854 Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Mar 2010 14:25:22 +0530 Subject: ath9k_hw: always set the core clock for AR9271 When initializing the PLL on AR9271 we always need to set the core clock to 117MHz. While at it remove the baud rate settings for the serial device on the AR9271, the default settings work well unless you want to customize it. Signed-off-by: Sujith Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 023c38bb846b..5bc5f5fdff57 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1006,22 +1006,6 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); } -static void ath9k_hw_change_target_baud(struct ath_hw *ah, u32 freq, u32 baud) -{ - u32 lcr; - u32 baud_divider = freq * 1000 * 1000 / 16 / baud; - - lcr = REG_READ(ah , 0x5100c); - lcr |= 0x80; - - REG_WRITE(ah, 0x5100c, lcr); - REG_WRITE(ah, 0x51004, (baud_divider >> 8)); - REG_WRITE(ah, 0x51000, (baud_divider & 0xff)); - - lcr &= ~0x80; - REG_WRITE(ah, 0x5100c, lcr); -} - static void ath9k_hw_init_pll(struct ath_hw *ah, struct ath9k_channel *chan) { @@ -1087,22 +1071,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, /* Switch the core clock for ar9271 to 117Mhz */ if (AR_SREV_9271(ah)) { - if ((pll == 0x142c) || (pll == 0x2850) ) { - udelay(500); - /* set CLKOBS to output AHB clock */ - REG_WRITE(ah, 0x7020, 0xe); - /* - * 0x304: 117Mhz, ahb_ratio: 1x1 - * 0x306: 40Mhz, ahb_ratio: 1x1 - */ - REG_WRITE(ah, 0x50040, 0x304); - /* - * makes adjustments for the baud dividor to keep the - * targetted baud rate based on the used core clock. - */ - ath9k_hw_change_target_baud(ah, AR9271_CORE_CLOCK, - AR9271_TARGET_BAUD_RATE); - } + udelay(500); + REG_WRITE(ah, 0x50040, 0x304); } udelay(RTC_PLL_SETTLE_DELAY); -- cgit v1.2.3 From 05020d236e91ddab1cb42483843a8995b3be1adf Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Mar 2010 14:25:23 +0530 Subject: ath9k_hw: add HTC init hardware call for special resets for AR9271 AR9271 needs a full reset only upon the first reset, add a call for the driver to enable these special resets. We can optimize this out later without an export. Signed-off-by: Sujith Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 12 ++++++++++++ drivers/net/wireless/ath/ath9k/hw.h | 3 +++ 2 files changed, 15 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 5bc5f5fdff57..05aeb511c686 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1951,6 +1951,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_mark_phy_inactive(ah); + /* Only required on the first reset */ if (AR_SREV_9271(ah) && ah->htc_reset_init) { REG_WRITE(ah, AR9271_RESET_POWER_DOWN_CONTROL, @@ -1963,6 +1964,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, return -EINVAL; } + /* Only required on the first reset */ if (AR_SREV_9271(ah) && ah->htc_reset_init) { ah->htc_reset_init = false; REG_WRITE(ah, @@ -3857,6 +3859,16 @@ void ath_gen_timer_isr(struct ath_hw *ah) } EXPORT_SYMBOL(ath_gen_timer_isr); +/********/ +/* HTC */ +/********/ + +void ath9k_hw_htc_resetinit(struct ath_hw *ah) +{ + ah->htc_reset_init = true; +} +EXPORT_SYMBOL(ath9k_hw_htc_resetinit); + static struct { u32 version; const char * name; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e63edfb91590..6b03e1688b22 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -707,6 +707,9 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah); void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len); +/* HTC */ +void ath9k_hw_htc_resetinit(struct ath_hw *ah); + #define ATH_PCIE_CAP_LINK_CTRL 0x70 #define ATH_PCIE_CAP_LINK_L0S 1 #define ATH_PCIE_CAP_LINK_L1 2 -- cgit v1.2.3 From 736b3a27b3c50c4a23717b802240435a69e8d0ff Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Mar 2010 14:25:24 +0530 Subject: ath9k_hw: fix hardware deinit Without this you will get a panic if the device initialization fails. Also, free ath_hw instance properly. ath9k_hw_deinit() shouldn't do it. Cc: stable@kernel.org Signed-off-by: Sujith Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 4 +--- drivers/net/wireless/ath/ath9k/init.c | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 05aeb511c686..77db932c3137 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1227,7 +1227,7 @@ void ath9k_hw_deinit(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); - if (common->state <= ATH_HW_INITIALIZED) + if (common->state < ATH_HW_INITIALIZED) goto free_hw; if (!AR_SREV_9100(ah)) @@ -1238,8 +1238,6 @@ void ath9k_hw_deinit(struct ath_hw *ah) free_hw: if (!AR_SREV_9280_10_OR_LATER(ah)) ath9k_hw_rf_free_ext_banks(ah); - kfree(ah); - ah = NULL; } EXPORT_SYMBOL(ath9k_hw_deinit); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 623c2f884987..6063f5463708 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -758,6 +758,9 @@ static void ath9k_deinit_softc(struct ath_softc *sc) tasklet_kill(&sc->intr_tq); tasklet_kill(&sc->bcon_tasklet); + + kfree(sc->sc_ah); + sc->sc_ah = NULL; } void ath9k_deinit_device(struct ath_softc *sc) -- cgit v1.2.3 From fb9987d0f748c983bb795a86f47522313f701a08 Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Mar 2010 14:25:25 +0530 Subject: ath9k_htc: Support for AR9271 chipset. Features: * Station mode * IBSS mode * Monitor mode * Legacy support * HT support * TX/RX 11n Aggregation * HW encryption * LED * Suspend/Resume For more information: http://wireless.kernel.org/en/users/Drivers/ath9k_htc Signed-off-by: Sujith Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/Kconfig | 2 +- drivers/net/wireless/ath/ath9k/Kconfig | 21 + drivers/net/wireless/ath/ath9k/Makefile | 10 + drivers/net/wireless/ath/ath9k/common.c | 421 ++++++ drivers/net/wireless/ath/ath9k/common.h | 17 + drivers/net/wireless/ath/ath9k/hif_usb.c | 993 ++++++++++++++ drivers/net/wireless/ath/ath9k/hif_usb.h | 105 ++ drivers/net/wireless/ath/ath9k/htc.h | 441 ++++++ drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 260 ++++ drivers/net/wireless/ath/ath9k/htc_drv_init.c | 713 ++++++++++ drivers/net/wireless/ath/ath9k/htc_drv_main.c | 1626 +++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 604 +++++++++ drivers/net/wireless/ath/ath9k/htc_hst.c | 463 +++++++ drivers/net/wireless/ath/ath9k/htc_hst.h | 246 ++++ drivers/net/wireless/ath/ath9k/mac.h | 26 + drivers/net/wireless/ath/ath9k/wmi.c | 319 +++++ drivers/net/wireless/ath/ath9k/wmi.h | 126 ++ drivers/net/wireless/ath/debug.h | 1 + 18 files changed, 6393 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/ath/ath9k/hif_usb.c create mode 100644 drivers/net/wireless/ath/ath9k/hif_usb.h create mode 100644 drivers/net/wireless/ath/ath9k/htc.h create mode 100644 drivers/net/wireless/ath/ath9k/htc_drv_beacon.c create mode 100644 drivers/net/wireless/ath/ath9k/htc_drv_init.c create mode 100644 drivers/net/wireless/ath/ath9k/htc_drv_main.c create mode 100644 drivers/net/wireless/ath/ath9k/htc_drv_txrx.c create mode 100644 drivers/net/wireless/ath/ath9k/htc_hst.c create mode 100644 drivers/net/wireless/ath/ath9k/htc_hst.h create mode 100644 drivers/net/wireless/ath/ath9k/wmi.c create mode 100644 drivers/net/wireless/ath/ath9k/wmi.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 4e7a7fd695c8..0a75be027afa 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig @@ -3,7 +3,7 @@ menuconfig ATH_COMMON depends on CFG80211 ---help--- This will enable the support for the Atheros wireless drivers. - ath5k, ath9k and ar9170 drivers share some common code, this option + ath5k, ath9k, ath9k_htc and ar9170 drivers share some common code, this option enables the common ath.ko module which shares common helpers. For more information and documentation on this module you can visit: diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 5774cea23a3b..35f23bdc442f 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -32,3 +32,24 @@ config ATH9K_DEBUGFS Also required for changing debug message flags at run time. +config ATH9K_HTC + tristate "Atheros HTC based wireless cards support" + depends on USB && MAC80211 + select ATH9K_HW + select MAC80211_LEDS + select LEDS_CLASS + select NEW_LEDS + select ATH9K_COMMON + ---help--- + Support for Atheros HTC based cards. + Chipsets supported: AR9271 + + For more information: http://wireless.kernel.org/en/users/Drivers/ath9k_htc + + The built module will be ath9k_htc. + +config ATH9K_HTC_DEBUGFS + bool "Atheros ath9k_htc debugging" + depends on ATH9K_HTC && DEBUG_FS + ---help--- + Say Y, if you need access to ath9k_htc's statistics. diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 6b50d5eb9ec3..97133beda269 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -28,3 +28,13 @@ obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o ath9k_common-y:= common.o + +ath9k_htc-y += htc_hst.o \ + hif_usb.o \ + wmi.o \ + htc_drv_txrx.o \ + htc_drv_main.o \ + htc_drv_beacon.o \ + htc_drv_init.o + +obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 4d775ae141db..7902d287f671 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -286,6 +286,427 @@ int ath9k_cmn_padpos(__le16 frame_control) } EXPORT_SYMBOL(ath9k_cmn_padpos); +int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + + if (tx_info->control.hw_key) { + if (tx_info->control.hw_key->alg == ALG_WEP) + return ATH9K_KEY_TYPE_WEP; + else if (tx_info->control.hw_key->alg == ALG_TKIP) + return ATH9K_KEY_TYPE_TKIP; + else if (tx_info->control.hw_key->alg == ALG_CCMP) + return ATH9K_KEY_TYPE_AES; + } + + return ATH9K_KEY_TYPE_CLEAR; +} +EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); + +/* + * Calculate the RX filter to be set in the HW. + */ +u32 ath9k_cmn_calcrxfilter(struct ieee80211_hw *hw, struct ath_hw *ah, + unsigned int rxfilter) +{ +#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) + + u32 rfilt; + + rfilt = (ath9k_hw_getrxfilter(ah) & RX_FILTER_PRESERVE) + | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST + | ATH9K_RX_FILTER_MCAST; + + /* If not a STA, enable processing of Probe Requests */ + if (ah->opmode != NL80211_IFTYPE_STATION) + rfilt |= ATH9K_RX_FILTER_PROBEREQ; + + /* + * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station + * mode interface or when in monitor mode. AP mode does not need this + * since it receives all in-BSS frames anyway. + */ + if (((ah->opmode != NL80211_IFTYPE_AP) && + (rxfilter & FIF_PROMISC_IN_BSS)) || + (ah->opmode == NL80211_IFTYPE_MONITOR)) + rfilt |= ATH9K_RX_FILTER_PROM; + + if (rxfilter & FIF_CONTROL) + rfilt |= ATH9K_RX_FILTER_CONTROL; + + if ((ah->opmode == NL80211_IFTYPE_STATION) && + !(rxfilter & FIF_BCN_PRBRESP_PROMISC)) + rfilt |= ATH9K_RX_FILTER_MYBEACON; + else + rfilt |= ATH9K_RX_FILTER_BEACON; + + if ((AR_SREV_9280_10_OR_LATER(ah) || + AR_SREV_9285_10_OR_LATER(ah)) && + (ah->opmode == NL80211_IFTYPE_AP) && + (rxfilter & FIF_PSPOLL)) + rfilt |= ATH9K_RX_FILTER_PSPOLL; + + if (conf_is_ht(&hw->conf)) + rfilt |= ATH9K_RX_FILTER_COMP_BAR; + + return rfilt; + +#undef RX_FILTER_PRESERVE +} +EXPORT_SYMBOL(ath9k_cmn_calcrxfilter); + +/* + * Recv initialization for opmode change. + */ +void ath9k_cmn_opmode_init(struct ieee80211_hw *hw, struct ath_hw *ah, + unsigned int rxfilter) +{ + struct ath_common *common = ath9k_hw_common(ah); + + u32 rfilt, mfilt[2]; + + /* configure rx filter */ + rfilt = ath9k_cmn_calcrxfilter(hw, ah, rxfilter); + ath9k_hw_setrxfilter(ah, rfilt); + + /* configure bssid mask */ + if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) + ath_hw_setbssidmask(common); + + /* configure operational mode */ + ath9k_hw_setopmode(ah); + + /* Handle any link-level address change. */ + ath9k_hw_setmac(ah, common->macaddr); + + /* calculate and install multicast filter */ + mfilt[0] = mfilt[1] = ~0; + ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); +} +EXPORT_SYMBOL(ath9k_cmn_opmode_init); + +static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) +{ + u32 chanmode = 0; + + switch (chan->band) { + case IEEE80211_BAND_2GHZ: + switch (channel_type) { + case NL80211_CHAN_NO_HT: + case NL80211_CHAN_HT20: + chanmode = CHANNEL_G_HT20; + break; + case NL80211_CHAN_HT40PLUS: + chanmode = CHANNEL_G_HT40PLUS; + break; + case NL80211_CHAN_HT40MINUS: + chanmode = CHANNEL_G_HT40MINUS; + break; + } + break; + case IEEE80211_BAND_5GHZ: + switch (channel_type) { + case NL80211_CHAN_NO_HT: + case NL80211_CHAN_HT20: + chanmode = CHANNEL_A_HT20; + break; + case NL80211_CHAN_HT40PLUS: + chanmode = CHANNEL_A_HT40PLUS; + break; + case NL80211_CHAN_HT40MINUS: + chanmode = CHANNEL_A_HT40MINUS; + break; + } + break; + default: + break; + } + + return chanmode; +} + +/* + * Update internal channel flags. + */ +void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, + struct ath9k_channel *ichan) +{ + struct ieee80211_channel *chan = hw->conf.channel; + struct ieee80211_conf *conf = &hw->conf; + + ichan->channel = chan->center_freq; + ichan->chan = chan; + + if (chan->band == IEEE80211_BAND_2GHZ) { + ichan->chanmode = CHANNEL_G; + ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G; + } else { + ichan->chanmode = CHANNEL_A; + ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; + } + + if (conf_is_ht(conf)) + ichan->chanmode = ath9k_get_extchanmode(chan, + conf->channel_type); +} +EXPORT_SYMBOL(ath9k_cmn_update_ichannel); + +/* + * Get the internal channel reference. + */ +struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, + struct ath_hw *ah) +{ + struct ieee80211_channel *curchan = hw->conf.channel; + struct ath9k_channel *channel; + u8 chan_idx; + + chan_idx = curchan->hw_value; + channel = &ah->channels[chan_idx]; + ath9k_cmn_update_ichannel(hw, channel); + + return channel; +} +EXPORT_SYMBOL(ath9k_cmn_get_curchannel); + +static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key, + struct ath9k_keyval *hk, const u8 *addr, + bool authenticator) +{ + struct ath_hw *ah = common->ah; + const u8 *key_rxmic; + const u8 *key_txmic; + + key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; + key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; + + if (addr == NULL) { + /* + * Group key installation - only two key cache entries are used + * regardless of splitmic capability since group key is only + * used either for TX or RX. + */ + if (authenticator) { + memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); + memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); + } else { + memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); + memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); + } + return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); + } + if (!common->splitmic) { + /* TX and RX keys share the same key cache entry. */ + memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); + memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); + return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); + } + + /* Separate key cache entries for TX and RX */ + + /* TX key goes at first index, RX key at +32. */ + memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); + if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) { + /* TX MIC entry failed. No need to proceed further */ + ath_print(common, ATH_DBG_FATAL, + "Setting TX MIC Key Failed\n"); + return 0; + } + + memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); + /* XXX delete tx key on failure? */ + return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr); +} + +static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) +{ + int i; + + for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { + if (test_bit(i, common->keymap) || + test_bit(i + 64, common->keymap)) + continue; /* At least one part of TKIP key allocated */ + if (common->splitmic && + (test_bit(i + 32, common->keymap) || + test_bit(i + 64 + 32, common->keymap))) + continue; /* At least one part of TKIP key allocated */ + + /* Found a free slot for a TKIP key */ + return i; + } + return -1; +} + +static int ath_reserve_key_cache_slot(struct ath_common *common) +{ + int i; + + /* First, try to find slots that would not be available for TKIP. */ + if (common->splitmic) { + for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { + if (!test_bit(i, common->keymap) && + (test_bit(i + 32, common->keymap) || + test_bit(i + 64, common->keymap) || + test_bit(i + 64 + 32, common->keymap))) + return i; + if (!test_bit(i + 32, common->keymap) && + (test_bit(i, common->keymap) || + test_bit(i + 64, common->keymap) || + test_bit(i + 64 + 32, common->keymap))) + return i + 32; + if (!test_bit(i + 64, common->keymap) && + (test_bit(i , common->keymap) || + test_bit(i + 32, common->keymap) || + test_bit(i + 64 + 32, common->keymap))) + return i + 64; + if (!test_bit(i + 64 + 32, common->keymap) && + (test_bit(i, common->keymap) || + test_bit(i + 32, common->keymap) || + test_bit(i + 64, common->keymap))) + return i + 64 + 32; + } + } else { + for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { + if (!test_bit(i, common->keymap) && + test_bit(i + 64, common->keymap)) + return i; + if (test_bit(i, common->keymap) && + !test_bit(i + 64, common->keymap)) + return i + 64; + } + } + + /* No partially used TKIP slots, pick any available slot */ + for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) { + /* Do not allow slots that could be needed for TKIP group keys + * to be used. This limitation could be removed if we know that + * TKIP will not be used. */ + if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) + continue; + if (common->splitmic) { + if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) + continue; + if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) + continue; + } + + if (!test_bit(i, common->keymap)) + return i; /* Found a free slot for a key */ + } + + /* No free slot found */ + return -1; +} + +/* + * Configure encryption in the HW. + */ +int ath9k_cmn_key_config(struct ath_common *common, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct ath_hw *ah = common->ah; + struct ath9k_keyval hk; + const u8 *mac = NULL; + int ret = 0; + int idx; + + memset(&hk, 0, sizeof(hk)); + + switch (key->alg) { + case ALG_WEP: + hk.kv_type = ATH9K_CIPHER_WEP; + break; + case ALG_TKIP: + hk.kv_type = ATH9K_CIPHER_TKIP; + break; + case ALG_CCMP: + hk.kv_type = ATH9K_CIPHER_AES_CCM; + break; + default: + return -EOPNOTSUPP; + } + + hk.kv_len = key->keylen; + memcpy(hk.kv_val, key->key, key->keylen); + + if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { + /* For now, use the default keys for broadcast keys. This may + * need to change with virtual interfaces. */ + idx = key->keyidx; + } else if (key->keyidx) { + if (WARN_ON(!sta)) + return -EOPNOTSUPP; + mac = sta->addr; + + if (vif->type != NL80211_IFTYPE_AP) { + /* Only keyidx 0 should be used with unicast key, but + * allow this for client mode for now. */ + idx = key->keyidx; + } else + return -EIO; + } else { + if (WARN_ON(!sta)) + return -EOPNOTSUPP; + mac = sta->addr; + + if (key->alg == ALG_TKIP) + idx = ath_reserve_key_cache_slot_tkip(common); + else + idx = ath_reserve_key_cache_slot(common); + if (idx < 0) + return -ENOSPC; /* no free key cache entries */ + } + + if (key->alg == ALG_TKIP) + ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, + vif->type == NL80211_IFTYPE_AP); + else + ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac); + + if (!ret) + return -EIO; + + set_bit(idx, common->keymap); + if (key->alg == ALG_TKIP) { + set_bit(idx + 64, common->keymap); + if (common->splitmic) { + set_bit(idx + 32, common->keymap); + set_bit(idx + 64 + 32, common->keymap); + } + } + + return idx; +} +EXPORT_SYMBOL(ath9k_cmn_key_config); + +/* + * Delete Key. + */ +void ath9k_cmn_key_delete(struct ath_common *common, + struct ieee80211_key_conf *key) +{ + struct ath_hw *ah = common->ah; + + ath9k_hw_keyreset(ah, key->hw_key_idx); + if (key->hw_key_idx < IEEE80211_WEP_NKID) + return; + + clear_bit(key->hw_key_idx, common->keymap); + if (key->alg != ALG_TKIP) + return; + + clear_bit(key->hw_key_idx + 64, common->keymap); + if (common->splitmic) { + ath9k_hw_keyreset(ah, key->hw_key_idx + 32); + clear_bit(key->hw_key_idx + 32, common->keymap); + clear_bit(key->hw_key_idx + 64 + 32, common->keymap); + } +} +EXPORT_SYMBOL(ath9k_cmn_key_delete); + static int __init ath9k_cmn_init(void) { return 0; diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 042999c2fe9c..bbcc57f6eba3 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -23,6 +23,8 @@ /* Common header for Atheros 802.11n base driver cores */ +#define IEEE80211_WEP_NKID 4 + #define WME_NUM_TID 16 #define WME_BA_BMP_SIZE 64 #define WME_MAX_BA WME_BA_BMP_SIZE @@ -125,3 +127,18 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, bool decrypt_error); int ath9k_cmn_padpos(__le16 frame_control); +int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); +u32 ath9k_cmn_calcrxfilter(struct ieee80211_hw *hw, struct ath_hw *ah, + unsigned int rxfilter); +void ath9k_cmn_opmode_init(struct ieee80211_hw *hw, struct ath_hw *ah, + unsigned int rxfilter); +void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, + struct ath9k_channel *ichan); +struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, + struct ath_hw *ah); +int ath9k_cmn_key_config(struct ath_common *common, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key); +void ath9k_cmn_key_delete(struct ath_common *common, + struct ieee80211_key_conf *key); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c new file mode 100644 index 000000000000..fc4f6e8c9ef3 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -0,0 +1,993 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "htc.h" + +#define ATH9K_FW_USB_DEV(devid, fw) \ + { USB_DEVICE(0x0cf3, devid), .driver_info = (unsigned long) fw } + +static struct usb_device_id ath9k_hif_usb_ids[] = { + ATH9K_FW_USB_DEV(0x9271, "ar9271.fw"), + { }, +}; + +MODULE_DEVICE_TABLE(usb, ath9k_hif_usb_ids); + +static int __hif_usb_tx(struct hif_device_usb *hif_dev); + +static void hif_usb_regout_cb(struct urb *urb) +{ + struct cmd_buf *cmd = (struct cmd_buf *)urb->context; + struct hif_device_usb *hif_dev = cmd->hif_dev; + + if (!hif_dev) { + usb_free_urb(urb); + if (cmd) { + if (cmd->skb) + dev_kfree_skb_any(cmd->skb); + kfree(cmd); + } + return; + } + + switch (urb->status) { + case 0: + break; + case -ENOENT: + case -ECONNRESET: + break; + case -ENODEV: + case -ESHUTDOWN: + return; + default: + break; + } + + if (cmd) { + ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, + cmd->skb, 1); + kfree(cmd); + usb_free_urb(urb); + } +} + +static int hif_usb_send_regout(struct hif_device_usb *hif_dev, + struct sk_buff *skb) +{ + struct urb *urb; + struct cmd_buf *cmd; + int ret = 0; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (urb == NULL) + return -ENOMEM; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) { + usb_free_urb(urb); + return -ENOMEM; + } + + cmd->skb = skb; + cmd->hif_dev = hif_dev; + + usb_fill_int_urb(urb, hif_dev->udev, + usb_sndintpipe(hif_dev->udev, USB_REG_OUT_PIPE), + skb->data, skb->len, + hif_usb_regout_cb, cmd, 1); + + ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret) { + usb_free_urb(urb); + kfree(cmd); + } + + return ret; +} + +static void hif_usb_tx_cb(struct urb *urb) +{ + struct tx_buf *tx_buf = (struct tx_buf *) urb->context; + struct hif_device_usb *hif_dev = tx_buf->hif_dev; + struct sk_buff *skb; + bool drop, flush; + + if (!hif_dev) + return; + + switch (urb->status) { + case 0: + break; + case -ENOENT: + case -ECONNRESET: + break; + case -ENODEV: + case -ESHUTDOWN: + return; + default: + break; + } + + if (tx_buf) { + spin_lock(&hif_dev->tx.tx_lock); + drop = !!(hif_dev->tx.flags & HIF_USB_TX_STOP); + flush = !!(hif_dev->tx.flags & HIF_USB_TX_FLUSH); + spin_unlock(&hif_dev->tx.tx_lock); + + while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) { + if (!drop && !flush) { + ath9k_htc_txcompletion_cb(hif_dev->htc_handle, + skb, 1); + TX_STAT_INC(skb_completed); + } else { + dev_kfree_skb_any(skb); + } + } + + if (flush) + return; + + tx_buf->len = tx_buf->offset = 0; + __skb_queue_head_init(&tx_buf->skb_queue); + + spin_lock(&hif_dev->tx.tx_lock); + list_del(&tx_buf->list); + list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf); + hif_dev->tx.tx_buf_cnt++; + if (!drop) + __hif_usb_tx(hif_dev); /* Check for pending SKBs */ + TX_STAT_INC(buf_completed); + spin_unlock(&hif_dev->tx.tx_lock); + } +} + +/* TX lock has to be taken */ +static int __hif_usb_tx(struct hif_device_usb *hif_dev) +{ + struct tx_buf *tx_buf = NULL; + struct sk_buff *nskb = NULL; + int ret = 0, i; + u16 *hdr, tx_skb_cnt = 0; + u8 *buf; + + if (hif_dev->tx.tx_skb_cnt == 0) + return 0; + + /* Check if a free TX buffer is available */ + if (list_empty(&hif_dev->tx.tx_buf)) + return 0; + + tx_buf = list_first_entry(&hif_dev->tx.tx_buf, struct tx_buf, list); + list_del(&tx_buf->list); + list_add_tail(&tx_buf->list, &hif_dev->tx.tx_pending); + hif_dev->tx.tx_buf_cnt--; + + tx_skb_cnt = min_t(u16, hif_dev->tx.tx_skb_cnt, MAX_TX_AGGR_NUM); + + for (i = 0; i < tx_skb_cnt; i++) { + nskb = __skb_dequeue(&hif_dev->tx.tx_skb_queue); + + /* Should never be NULL */ + BUG_ON(!nskb); + + hif_dev->tx.tx_skb_cnt--; + + buf = tx_buf->buf; + buf += tx_buf->offset; + hdr = (u16 *)buf; + *hdr++ = nskb->len; + *hdr++ = ATH_USB_TX_STREAM_MODE_TAG; + buf += 4; + memcpy(buf, nskb->data, nskb->len); + tx_buf->len = nskb->len + 4; + + if (i < (tx_skb_cnt - 1)) + tx_buf->offset += (((tx_buf->len - 1) / 4) + 1) * 4; + + if (i == (tx_skb_cnt - 1)) + tx_buf->len += tx_buf->offset; + + __skb_queue_tail(&tx_buf->skb_queue, nskb); + TX_STAT_INC(skb_queued); + } + + usb_fill_bulk_urb(tx_buf->urb, hif_dev->udev, + usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE), + tx_buf->buf, tx_buf->len, + hif_usb_tx_cb, tx_buf); + + ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC); + if (ret) { + tx_buf->len = tx_buf->offset = 0; + __skb_queue_purge(&tx_buf->skb_queue); + __skb_queue_head_init(&tx_buf->skb_queue); + list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); + hif_dev->tx.tx_buf_cnt++; + } + + if (!ret) + TX_STAT_INC(buf_queued); + + return ret; +} + +static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb, + struct ath9k_htc_tx_ctl *tx_ctl) +{ + unsigned long flags; + + spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + + if (hif_dev->tx.flags & HIF_USB_TX_STOP) { + spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); + return -ENODEV; + } + + /* Check if the max queue count has been reached */ + if (hif_dev->tx.tx_skb_cnt > MAX_TX_BUF_NUM) { + spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); + return -ENOMEM; + } + + __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); + hif_dev->tx.tx_skb_cnt++; + + /* Send normal frames immediately */ + if (!tx_ctl || (tx_ctl && (tx_ctl->type == ATH9K_HTC_NORMAL))) + __hif_usb_tx(hif_dev); + + /* Check if AMPDUs have to be sent immediately */ + if (tx_ctl && (tx_ctl->type == ATH9K_HTC_AMPDU) && + (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && + (hif_dev->tx.tx_skb_cnt < 2)) { + __hif_usb_tx(hif_dev); + } + + spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); + + return 0; +} + +static void hif_usb_start(void *hif_handle, u8 pipe_id) +{ + struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; + unsigned long flags; + + hif_dev->flags |= HIF_USB_START; + + spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + hif_dev->tx.flags &= ~HIF_USB_TX_STOP; + spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); +} + +static void hif_usb_stop(void *hif_handle, u8 pipe_id) +{ + struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; + unsigned long flags; + + spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + __skb_queue_purge(&hif_dev->tx.tx_skb_queue); + hif_dev->tx.tx_skb_cnt = 0; + hif_dev->tx.flags |= HIF_USB_TX_STOP; + spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); +} + +static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb, + struct ath9k_htc_tx_ctl *tx_ctl) +{ + struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; + int ret = 0; + + switch (pipe_id) { + case USB_WLAN_TX_PIPE: + ret = hif_usb_send_tx(hif_dev, skb, tx_ctl); + break; + case USB_REG_OUT_PIPE: + ret = hif_usb_send_regout(hif_dev, skb); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static struct ath9k_htc_hif hif_usb = { + .transport = ATH9K_HIF_USB, + .name = "ath9k_hif_usb", + + .control_ul_pipe = USB_REG_OUT_PIPE, + .control_dl_pipe = USB_REG_IN_PIPE, + + .start = hif_usb_start, + .stop = hif_usb_stop, + .send = hif_usb_send, +}; + +static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, + struct sk_buff *skb) +{ + struct sk_buff *nskb, *skb_pool[8]; + int index = 0, i = 0, chk_idx, len = skb->len; + int rx_remain_len = 0, rx_pkt_len = 0; + u16 pkt_len, pkt_tag, pool_index = 0; + u8 *ptr; + + rx_remain_len = hif_dev->rx_remain_len; + rx_pkt_len = hif_dev->rx_transfer_len; + + if (rx_remain_len != 0) { + struct sk_buff *remain_skb = hif_dev->remain_skb; + + if (remain_skb) { + ptr = (u8 *) remain_skb->data; + + index = rx_remain_len; + rx_remain_len -= hif_dev->rx_pad_len; + ptr += rx_pkt_len; + + memcpy(ptr, skb->data, rx_remain_len); + + rx_pkt_len += rx_remain_len; + hif_dev->rx_remain_len = 0; + skb_put(remain_skb, rx_pkt_len); + + skb_pool[pool_index++] = remain_skb; + + } else { + index = rx_remain_len; + } + } + + while (index < len) { + ptr = (u8 *) skb->data; + + pkt_len = ptr[index] + (ptr[index+1] << 8); + pkt_tag = ptr[index+2] + (ptr[index+3] << 8); + + if (pkt_tag == ATH_USB_RX_STREAM_MODE_TAG) { + u16 pad_len; + + pad_len = 4 - (pkt_len & 0x3); + if (pad_len == 4) + pad_len = 0; + + chk_idx = index; + index = index + 4 + pkt_len + pad_len; + + if (index > MAX_RX_BUF_SIZE) { + hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; + hif_dev->rx_transfer_len = + MAX_RX_BUF_SIZE - chk_idx - 4; + hif_dev->rx_pad_len = pad_len; + + nskb = __dev_alloc_skb(pkt_len + 32, + GFP_ATOMIC); + if (!nskb) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: RX memory allocation" + " error\n"); + goto err; + } + skb_reserve(nskb, 32); + RX_STAT_INC(skb_allocated); + + memcpy(nskb->data, &(skb->data[chk_idx+4]), + hif_dev->rx_transfer_len); + + /* Record the buffer pointer */ + hif_dev->remain_skb = nskb; + } else { + nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); + if (!nskb) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: RX memory allocation" + " error\n"); + goto err; + } + skb_reserve(nskb, 32); + RX_STAT_INC(skb_allocated); + + memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); + skb_put(nskb, pkt_len); + skb_pool[pool_index++] = nskb; + } + } else { + RX_STAT_INC(skb_dropped); + dev_kfree_skb_any(skb); + return; + } + } + +err: + dev_kfree_skb_any(skb); + + for (i = 0; i < pool_index; i++) { + ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i], + skb_pool[i]->len, USB_WLAN_RX_PIPE); + RX_STAT_INC(skb_completed); + } +} + +static void ath9k_hif_usb_rx_cb(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *) urb->context; + struct sk_buff *nskb; + struct hif_device_usb *hif_dev = (struct hif_device_usb *) + usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); + int ret; + + if (!hif_dev) + goto free; + + switch (urb->status) { + case 0: + break; + case -ENOENT: + case -ECONNRESET: + case -ENODEV: + case -ESHUTDOWN: + goto free; + default: + goto resubmit; + } + + if (likely(urb->actual_length != 0)) { + skb_put(skb, urb->actual_length); + + nskb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_ATOMIC); + if (!nskb) + goto resubmit; + + usb_fill_bulk_urb(urb, hif_dev->udev, + usb_rcvbulkpipe(hif_dev->udev, + USB_WLAN_RX_PIPE), + nskb->data, MAX_RX_BUF_SIZE, + ath9k_hif_usb_rx_cb, nskb); + + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) { + dev_kfree_skb_any(nskb); + goto free; + } + + ath9k_hif_usb_rx_stream(hif_dev, skb); + return; + } + +resubmit: + skb_reset_tail_pointer(skb); + skb_trim(skb, 0); + + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) + goto free; + + return; +free: + dev_kfree_skb_any(skb); +} + +static void ath9k_hif_usb_reg_in_cb(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *) urb->context; + struct sk_buff *nskb; + struct hif_device_usb *hif_dev = (struct hif_device_usb *) + usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); + int ret; + + if (!hif_dev) + goto free; + + switch (urb->status) { + case 0: + break; + case -ENOENT: + case -ECONNRESET: + case -ENODEV: + case -ESHUTDOWN: + goto free; + default: + goto resubmit; + } + + if (likely(urb->actual_length != 0)) { + skb_put(skb, urb->actual_length); + + nskb = __dev_alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); + if (!nskb) + goto resubmit; + + usb_fill_int_urb(urb, hif_dev->udev, + usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), + nskb->data, MAX_REG_IN_BUF_SIZE, + ath9k_hif_usb_reg_in_cb, nskb, 1); + + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) { + dev_kfree_skb_any(nskb); + goto free; + } + + ath9k_htc_rx_msg(hif_dev->htc_handle, skb, + skb->len, USB_REG_IN_PIPE); + + return; + } + +resubmit: + skb_reset_tail_pointer(skb); + skb_trim(skb, 0); + + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) + goto free; + + return; +free: + dev_kfree_skb_any(skb); +} + +static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) +{ + unsigned long flags; + struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; + + list_for_each_entry_safe(tx_buf, tx_buf_tmp, &hif_dev->tx.tx_buf, list) { + list_del(&tx_buf->list); + usb_free_urb(tx_buf->urb); + kfree(tx_buf->buf); + kfree(tx_buf); + } + + spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + hif_dev->tx.flags |= HIF_USB_TX_FLUSH; + spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); + + list_for_each_entry_safe(tx_buf, tx_buf_tmp, + &hif_dev->tx.tx_pending, list) { + usb_kill_urb(tx_buf->urb); + list_del(&tx_buf->list); + usb_free_urb(tx_buf->urb); + kfree(tx_buf->buf); + kfree(tx_buf); + } + + spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + hif_dev->tx.flags &= ~HIF_USB_TX_FLUSH; + spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); +} + +static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) +{ + struct tx_buf *tx_buf; + int i; + + INIT_LIST_HEAD(&hif_dev->tx.tx_buf); + INIT_LIST_HEAD(&hif_dev->tx.tx_pending); + spin_lock_init(&hif_dev->tx.tx_lock); + __skb_queue_head_init(&hif_dev->tx.tx_skb_queue); + + for (i = 0; i < MAX_TX_URB_NUM; i++) { + tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL); + if (!tx_buf) + goto err; + + tx_buf->buf = kzalloc(MAX_TX_BUF_SIZE, GFP_KERNEL); + if (!tx_buf->buf) + goto err; + + tx_buf->urb = usb_alloc_urb(0, GFP_KERNEL); + if (!tx_buf->urb) + goto err; + + tx_buf->hif_dev = hif_dev; + __skb_queue_head_init(&tx_buf->skb_queue); + + list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf); + } + + hif_dev->tx.tx_buf_cnt = MAX_TX_URB_NUM; + + return 0; +err: + ath9k_hif_usb_dealloc_tx_urbs(hif_dev); + return -ENOMEM; +} + +static void ath9k_hif_usb_dealloc_rx_skbs(struct hif_device_usb *hif_dev) +{ + int i; + + for (i = 0; i < MAX_RX_URB_NUM; i++) { + if (hif_dev->wlan_rx_data_urb[i]) { + if (hif_dev->wlan_rx_data_urb[i]->transfer_buffer) + dev_kfree_skb_any((void *) + hif_dev->wlan_rx_data_urb[i]->context); + } + } +} + +static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev) +{ + int i; + + for (i = 0; i < MAX_RX_URB_NUM; i++) { + if (hif_dev->wlan_rx_data_urb[i]) { + usb_kill_urb(hif_dev->wlan_rx_data_urb[i]); + usb_free_urb(hif_dev->wlan_rx_data_urb[i]); + hif_dev->wlan_rx_data_urb[i] = NULL; + } + } +} + +static int ath9k_hif_usb_prep_rx_urb(struct hif_device_usb *hif_dev, + struct urb *urb) +{ + struct sk_buff *skb; + + skb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + usb_fill_bulk_urb(urb, hif_dev->udev, + usb_rcvbulkpipe(hif_dev->udev, USB_WLAN_RX_PIPE), + skb->data, MAX_RX_BUF_SIZE, + ath9k_hif_usb_rx_cb, skb); + return 0; +} + +static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) +{ + int i, ret; + + for (i = 0; i < MAX_RX_URB_NUM; i++) { + + /* Allocate URB */ + hif_dev->wlan_rx_data_urb[i] = usb_alloc_urb(0, GFP_KERNEL); + if (hif_dev->wlan_rx_data_urb[i] == NULL) { + ret = -ENOMEM; + goto err_rx_urb; + } + + /* Allocate buffer */ + ret = ath9k_hif_usb_prep_rx_urb(hif_dev, + hif_dev->wlan_rx_data_urb[i]); + if (ret) + goto err_rx_urb; + + /* Submit URB */ + ret = usb_submit_urb(hif_dev->wlan_rx_data_urb[i], GFP_KERNEL); + if (ret) + goto err_rx_urb; + + } + + return 0; + +err_rx_urb: + ath9k_hif_usb_dealloc_rx_skbs(hif_dev); + ath9k_hif_usb_dealloc_rx_urbs(hif_dev); + return ret; +} + +static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev) +{ + if (hif_dev->reg_in_urb) { + usb_kill_urb(hif_dev->reg_in_urb); + usb_free_urb(hif_dev->reg_in_urb); + hif_dev->reg_in_urb = NULL; + } +} + +static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev) +{ + struct sk_buff *skb; + + hif_dev->reg_in_urb = usb_alloc_urb(0, GFP_KERNEL); + if (hif_dev->reg_in_urb == NULL) + return -ENOMEM; + + skb = __dev_alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); + if (!skb) + goto err; + + usb_fill_int_urb(hif_dev->reg_in_urb, hif_dev->udev, + usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), + skb->data, MAX_REG_IN_BUF_SIZE, + ath9k_hif_usb_reg_in_cb, skb, 1); + + if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0) + goto err_skb; + + return 0; + +err_skb: + dev_kfree_skb_any(skb); +err: + ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); + return -ENOMEM; +} + +static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) +{ + /* TX */ + if (ath9k_hif_usb_alloc_tx_urbs(hif_dev) < 0) + goto err; + + /* RX */ + if (ath9k_hif_usb_alloc_rx_urbs(hif_dev) < 0) + goto err; + + /* Register Read/Write */ + if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0) + goto err; + + return 0; +err: + return -ENOMEM; +} + +static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) +{ + int transfer, err; + const void *data = hif_dev->firmware->data; + size_t len = hif_dev->firmware->size; + u32 addr = AR9271_FIRMWARE; + u8 *buf = kzalloc(4096, GFP_KERNEL); + + if (!buf) + return -ENOMEM; + + while (len) { + transfer = min_t(int, len, 4096); + memcpy(buf, data, transfer); + + err = usb_control_msg(hif_dev->udev, + usb_sndctrlpipe(hif_dev->udev, 0), + FIRMWARE_DOWNLOAD, 0x40 | USB_DIR_OUT, + addr >> 8, 0, buf, transfer, HZ); + if (err < 0) { + kfree(buf); + return err; + } + + len -= transfer; + data += transfer; + addr += transfer; + } + kfree(buf); + + /* + * Issue FW download complete command to firmware. + */ + err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0), + FIRMWARE_DOWNLOAD_COMP, + 0x40 | USB_DIR_OUT, + AR9271_FIRMWARE_TEXT >> 8, 0, NULL, 0, HZ); + if (err) + return -EIO; + + dev_info(&hif_dev->udev->dev, "ath9k_htc: Transferred FW: %s, size: %ld\n", + "ar9271.fw", (unsigned long) hif_dev->firmware->size); + + return 0; +} + +static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, + const char *fw_name) +{ + int ret; + + /* Request firmware */ + ret = request_firmware(&hif_dev->firmware, fw_name, &hif_dev->udev->dev); + if (ret) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Firmware - %s not found\n", fw_name); + goto err_fw_req; + } + + /* Download firmware */ + ret = ath9k_hif_usb_download_fw(hif_dev); + if (ret) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Firmware - %s download failed\n", fw_name); + goto err_fw_download; + } + + /* Alloc URBs */ + ret = ath9k_hif_usb_alloc_urbs(hif_dev); + if (ret) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Unable to allocate URBs\n"); + goto err_urb; + } + + return 0; + +err_urb: + /* Nothing */ +err_fw_download: + release_firmware(hif_dev->firmware); +err_fw_req: + hif_dev->firmware = NULL; + return ret; +} + +static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) +{ + ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); + ath9k_hif_usb_dealloc_tx_urbs(hif_dev); + ath9k_hif_usb_dealloc_rx_urbs(hif_dev); +} + +static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev) +{ + ath9k_hif_usb_dealloc_urbs(hif_dev); + if (hif_dev->firmware) + release_firmware(hif_dev->firmware); +} + +static int ath9k_hif_usb_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(interface); + struct hif_device_usb *hif_dev; + const char *fw_name = (const char *) id->driver_info; + int ret = 0; + + hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL); + if (!hif_dev) { + ret = -ENOMEM; + goto err_alloc; + } + + usb_get_dev(udev); + hif_dev->udev = udev; + hif_dev->interface = interface; + hif_dev->device_id = id->idProduct; +#ifdef CONFIG_PM + udev->reset_resume = 1; +#endif + usb_set_intfdata(interface, hif_dev); + + ret = ath9k_hif_usb_dev_init(hif_dev, fw_name); + if (ret) { + ret = -EINVAL; + goto err_hif_init_usb; + } + + hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev); + if (hif_dev->htc_handle == NULL) { + ret = -ENOMEM; + goto err_htc_hw_alloc; + } + + ret = ath9k_htc_hw_init(&hif_usb, hif_dev->htc_handle, hif_dev, + &hif_dev->udev->dev, hif_dev->device_id, + ATH9K_HIF_USB); + if (ret) { + ret = -EINVAL; + goto err_htc_hw_init; + } + + dev_info(&hif_dev->udev->dev, "ath9k_htc: USB layer initialized\n"); + + return 0; + +err_htc_hw_init: + ath9k_htc_hw_free(hif_dev->htc_handle); +err_htc_hw_alloc: + ath9k_hif_usb_dev_deinit(hif_dev); +err_hif_init_usb: + usb_set_intfdata(interface, NULL); + kfree(hif_dev); + usb_put_dev(udev); +err_alloc: + return ret; +} + +static void ath9k_hif_usb_disconnect(struct usb_interface *interface) +{ + struct usb_device *udev = interface_to_usbdev(interface); + struct hif_device_usb *hif_dev = + (struct hif_device_usb *) usb_get_intfdata(interface); + + if (hif_dev) { + ath9k_htc_hw_deinit(hif_dev->htc_handle, true); + ath9k_htc_hw_free(hif_dev->htc_handle); + ath9k_hif_usb_dev_deinit(hif_dev); + usb_set_intfdata(interface, NULL); + } + + if (hif_dev->flags & HIF_USB_START) + usb_reset_device(udev); + + kfree(hif_dev); + dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n"); + usb_put_dev(udev); +} + +#ifdef CONFIG_PM +static int ath9k_hif_usb_suspend(struct usb_interface *interface, + pm_message_t message) +{ + struct hif_device_usb *hif_dev = + (struct hif_device_usb *) usb_get_intfdata(interface); + + ath9k_hif_usb_dealloc_urbs(hif_dev); + + return 0; +} + +static int ath9k_hif_usb_resume(struct usb_interface *interface) +{ + struct hif_device_usb *hif_dev = + (struct hif_device_usb *) usb_get_intfdata(interface); + int ret; + + ret = ath9k_hif_usb_alloc_urbs(hif_dev); + if (ret) + return ret; + + if (hif_dev->firmware) { + ret = ath9k_hif_usb_download_fw(hif_dev); + if (ret) + goto fail_resume; + } else { + ath9k_hif_usb_dealloc_urbs(hif_dev); + return -EIO; + } + + mdelay(100); + + ret = ath9k_htc_resume(hif_dev->htc_handle); + + if (ret) + goto fail_resume; + + return 0; + +fail_resume: + ath9k_hif_usb_dealloc_urbs(hif_dev); + + return ret; +} +#endif + +static struct usb_driver ath9k_hif_usb_driver = { + .name = "ath9k_hif_usb", + .probe = ath9k_hif_usb_probe, + .disconnect = ath9k_hif_usb_disconnect, +#ifdef CONFIG_PM + .suspend = ath9k_hif_usb_suspend, + .resume = ath9k_hif_usb_resume, + .reset_resume = ath9k_hif_usb_resume, +#endif + .id_table = ath9k_hif_usb_ids, + .soft_unbind = 1, +}; + +int ath9k_hif_usb_init(void) +{ + return usb_register(&ath9k_hif_usb_driver); +} + +void ath9k_hif_usb_exit(void) +{ + usb_deregister(&ath9k_hif_usb_driver); +} diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h new file mode 100644 index 000000000000..7cc3762a6789 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HTC_USB_H +#define HTC_USB_H + +#define AR9271_FIRMWARE 0x501000 +#define AR9271_FIRMWARE_TEXT 0x903000 + +#define FIRMWARE_DOWNLOAD 0x30 +#define FIRMWARE_DOWNLOAD_COMP 0x31 + +#define ATH_USB_RX_STREAM_MODE_TAG 0x4e00 +#define ATH_USB_TX_STREAM_MODE_TAG 0x697e + +/* FIXME: Verify these numbers (with Windows) */ +#define MAX_TX_URB_NUM 8 +#define MAX_TX_BUF_NUM 1024 +#define MAX_TX_BUF_SIZE 32768 +#define MAX_TX_AGGR_NUM 20 + +#define MAX_RX_URB_NUM 8 +#define MAX_RX_BUF_SIZE 16384 + +#define MAX_REG_OUT_URB_NUM 1 +#define MAX_REG_OUT_BUF_NUM 8 + +#define MAX_REG_IN_BUF_SIZE 64 + +/* USB Endpoint definition */ +#define USB_WLAN_TX_PIPE 1 +#define USB_WLAN_RX_PIPE 2 +#define USB_REG_IN_PIPE 3 +#define USB_REG_OUT_PIPE 4 + +#define HIF_USB_MAX_RXPIPES 2 +#define HIF_USB_MAX_TXPIPES 4 + +struct tx_buf { + u8 *buf; + u16 len; + u16 offset; + struct urb *urb; + struct sk_buff_head skb_queue; + struct hif_device_usb *hif_dev; + struct list_head list; +}; + +#define HIF_USB_TX_STOP BIT(0) +#define HIF_USB_TX_FLUSH BIT(1) + +struct hif_usb_tx { + u8 flags; + u8 tx_buf_cnt; + u16 tx_skb_cnt; + struct sk_buff_head tx_skb_queue; + struct list_head tx_buf; + struct list_head tx_pending; + spinlock_t tx_lock; +}; + +struct cmd_buf { + struct sk_buff *skb; + struct hif_device_usb *hif_dev; +}; + +#define HIF_USB_START BIT(0) + +struct hif_device_usb { + u16 device_id; + struct usb_device *udev; + struct usb_interface *interface; + const struct firmware *firmware; + struct htc_target *htc_handle; + u8 flags; + + struct hif_usb_tx tx; + + struct urb *wlan_rx_data_urb[MAX_RX_URB_NUM]; + struct urb *reg_in_urb; + + struct sk_buff *remain_skb; + int rx_remain_len; + int rx_pkt_len; + int rx_transfer_len; + int rx_pad_len; +}; + +int ath9k_hif_usb_init(void); +void ath9k_hif_usb_exit(void); + +#endif /* HTC_USB_H */ diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h new file mode 100644 index 000000000000..ab09fe3416c7 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HTC_H +#define HTC_H + +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "htc_hst.h" +#include "hif_usb.h" +#include "wmi.h" + +#define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ +#define ATH_ANI_POLLINTERVAL 100 /* 100 ms */ +#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ +#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ + +#define ATH_DEFAULT_BMISS_LIMIT 10 +#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) +#define TSF_TO_TU(_h, _l) \ + ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) + +extern struct ieee80211_ops ath9k_htc_ops; +extern int modparam_nohwcrypt; + +enum htc_phymode { + HTC_MODE_AUTO = 0, + HTC_MODE_11A = 1, + HTC_MODE_11B = 2, + HTC_MODE_11G = 3, + HTC_MODE_FH = 4, + HTC_MODE_TURBO_A = 5, + HTC_MODE_TURBO_G = 6, + HTC_MODE_11NA = 7, + HTC_MODE_11NG = 8 +}; + +enum htc_opmode { + HTC_M_STA = 1, + HTC_M_IBSS = 0, + HTC_M_AHDEMO = 3, + HTC_M_HOSTAP = 6, + HTC_M_MONITOR = 8, + HTC_M_WDS = 2 +}; + +#define ATH9K_HTC_HDRSPACE sizeof(struct htc_frame_hdr) +#define ATH9K_HTC_AMPDU 1 +#define ATH9K_HTC_NORMAL 2 + +#define ATH9K_HTC_TX_CTSONLY 0x1 +#define ATH9K_HTC_TX_RTSCTS 0x2 +#define ATH9K_HTC_TX_USE_MIN_RATE 0x100 + +struct tx_frame_hdr { + u8 data_type; + u8 node_idx; + u8 vif_idx; + u8 tidno; + u32 flags; /* ATH9K_HTC_TX_* */ + u8 key_type; + u8 keyix; + u8 reserved[26]; +} __packed; + +struct tx_mgmt_hdr { + u8 node_idx; + u8 vif_idx; + u8 tidno; + u8 flags; + u8 key_type; + u8 keyix; + u16 reserved; +} __packed; + +struct tx_beacon_header { + u8 len_changed; + u8 vif_index; + u16 rev; +} __packed; + +struct ath9k_htc_target_hw { + u32 flags; + u32 flags_ext; + u32 ampdu_limit; + u8 ampdu_subframes; + u8 tx_chainmask; + u8 tx_chainmask_legacy; + u8 rtscts_ratecode; + u8 protmode; +} __packed; + +struct ath9k_htc_cap_target { + u32 flags; + u32 flags_ext; + u32 ampdu_limit; + u8 ampdu_subframes; + u8 tx_chainmask; + u8 tx_chainmask_legacy; + u8 rtscts_ratecode; + u8 protmode; +} __packed; + +struct ath9k_htc_target_vif { + u8 index; + u8 des_bssid[ETH_ALEN]; + enum htc_opmode opmode; + u8 myaddr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u32 flags; + u32 flags_ext; + u16 ps_sta; + u16 rtsthreshold; + u8 ath_cap; + u8 node; + s8 mcast_rate; +} __packed; + +#define ATH_HTC_STA_AUTH 0x0001 +#define ATH_HTC_STA_QOS 0x0002 +#define ATH_HTC_STA_ERP 0x0004 +#define ATH_HTC_STA_HT 0x0008 + +/* FIXME: UAPSD variables */ +struct ath9k_htc_target_sta { + u16 associd; + u16 txpower; + u32 ucastkey; + u8 macaddr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u8 sta_index; + u8 vif_index; + u8 vif_sta; + u16 flags; /* ATH_HTC_STA_* */ + u16 htcap; + u8 valid; + u16 capinfo; + struct ath9k_htc_target_hw *hw; + struct ath9k_htc_target_vif *vif; + u16 txseqmgmt; + u8 is_vif_sta; + u16 maxampdu; + u16 iv16; + u32 iv32; +} __packed; + +struct ath9k_htc_target_aggr { + u8 sta_index; + u8 tidno; + u8 aggr_enable; + u8 padding; +} __packed; + +#define ATH_HTC_RATE_MAX 30 + +#define WLAN_RC_DS_FLAG 0x01 +#define WLAN_RC_40_FLAG 0x02 +#define WLAN_RC_SGI_FLAG 0x04 +#define WLAN_RC_HT_FLAG 0x08 + +struct ath9k_htc_rateset { + u8 rs_nrates; + u8 rs_rates[ATH_HTC_RATE_MAX]; +}; + +struct ath9k_htc_rate { + struct ath9k_htc_rateset legacy_rates; + struct ath9k_htc_rateset ht_rates; +} __packed; + +struct ath9k_htc_target_rate { + u8 sta_index; + u8 isnew; + u32 capflags; + struct ath9k_htc_rate rates; +}; + +struct ath9k_htc_target_stats { + u32 tx_shortretry; + u32 tx_longretry; + u32 tx_xretries; + u32 ht_txunaggr_xretry; + u32 ht_tx_xretries; +} __packed; + +struct ath9k_htc_vif { + u8 index; +}; + +#define ATH9K_HTC_MAX_STA 8 +#define ATH9K_HTC_MAX_TID 8 + +enum tid_aggr_state { + AGGR_STOP = 0, + AGGR_PROGRESS, + AGGR_START, + AGGR_OPERATIONAL +}; + +struct ath9k_htc_sta { + u8 index; + enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID]; +}; + +struct ath9k_htc_aggr_work { + u16 tid; + u8 sta_addr[ETH_ALEN]; + struct ieee80211_hw *hw; + struct ieee80211_vif *vif; + enum ieee80211_ampdu_mlme_action action; + struct mutex mutex; +}; + +#define ATH9K_HTC_RXBUF 256 +#define HTC_RX_FRAME_HEADER_SIZE 40 + +struct ath9k_htc_rxbuf { + bool in_process; + struct sk_buff *skb; + struct ath_htc_rx_status rxstatus; + struct list_head list; +}; + +struct ath9k_htc_rx { + int last_rssi; /* FIXME: per-STA */ + struct list_head rxbuf; + spinlock_t rxbuflock; +}; + +struct ath9k_htc_tx_ctl { + u8 type; /* ATH9K_HTC_* */ +}; + +#ifdef CONFIG_ATH9K_HTC_DEBUGFS + +#define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) +#define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) + +struct ath_tx_stats { + u32 buf_queued; + u32 buf_completed; + u32 skb_queued; + u32 skb_completed; +}; + +struct ath_rx_stats { + u32 skb_allocated; + u32 skb_completed; + u32 skb_dropped; +}; + +struct ath9k_debug { + struct dentry *debugfs_phy; + struct dentry *debugfs_tgt_stats; + struct dentry *debugfs_xmit; + struct dentry *debugfs_recv; + struct ath_tx_stats tx_stats; + struct ath_rx_stats rx_stats; + u32 txrate; +}; + +#else + +#define TX_STAT_INC(c) do { } while (0) +#define RX_STAT_INC(c) do { } while (0) + +#endif /* CONFIG_ATH9K_HTC_DEBUGFS */ + +#define ATH_LED_PIN_DEF 1 +#define ATH_LED_PIN_9287 8 +#define ATH_LED_PIN_9271 15 +#define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ +#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ + +enum ath_led_type { + ATH_LED_RADIO, + ATH_LED_ASSOC, + ATH_LED_TX, + ATH_LED_RX +}; + +struct ath_led { + struct ath9k_htc_priv *priv; + struct led_classdev led_cdev; + enum ath_led_type led_type; + struct delayed_work brightness_work; + char name[32]; + bool registered; + int brightness; +}; + +#define OP_INVALID BIT(0) +#define OP_SCANNING BIT(1) +#define OP_FULL_RESET BIT(2) +#define OP_LED_ASSOCIATED BIT(3) +#define OP_LED_ON BIT(4) +#define OP_PREAMBLE_SHORT BIT(5) +#define OP_PROTECT_ENABLE BIT(6) +#define OP_TXAGGR BIT(7) +#define OP_ASSOCIATED BIT(8) +#define OP_ENABLE_BEACON BIT(9) +#define OP_LED_DEINIT BIT(10) + +struct ath9k_htc_priv { + struct device *dev; + struct ieee80211_hw *hw; + struct ath_hw *ah; + struct htc_target *htc; + struct wmi *wmi; + + enum htc_endpoint_id wmi_cmd_ep; + enum htc_endpoint_id beacon_ep; + enum htc_endpoint_id cab_ep; + enum htc_endpoint_id uapsd_ep; + enum htc_endpoint_id mgmt_ep; + enum htc_endpoint_id data_be_ep; + enum htc_endpoint_id data_bk_ep; + enum htc_endpoint_id data_vi_ep; + enum htc_endpoint_id data_vo_ep; + + u16 op_flags; + u16 curtxpow; + u16 txpowlimit; + u16 nvifs; + u16 nstations; + u16 seq_no; + u32 bmiss_cnt; + + struct sk_buff *beacon; + spinlock_t beacon_lock; + + struct ieee80211_vif *vif; + unsigned int rxfilter; + struct tasklet_struct wmi_tasklet; + struct tasklet_struct rx_tasklet; + struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; + struct ath9k_htc_rx rx; + struct tasklet_struct tx_tasklet; + struct sk_buff_head tx_queue; + struct ath9k_htc_aggr_work aggr_work; + struct delayed_work ath9k_aggr_work; + struct delayed_work ath9k_ani_work; + + struct ath_led radio_led; + struct ath_led assoc_led; + struct ath_led tx_led; + struct ath_led rx_led; + struct delayed_work ath9k_led_blink_work; + int led_on_duration; + int led_off_duration; + int led_on_cnt; + int led_off_cnt; + int hwq_map[ATH9K_WME_AC_VO+1]; + +#ifdef CONFIG_ATH9K_HTC_DEBUGFS + struct ath9k_debug debug; +#endif + struct ath9k_htc_target_rate tgt_rate; + + struct mutex mutex; +}; + +static inline void ath_read_cachesize(struct ath_common *common, int *csz) +{ + common->bus_ops->read_cachesize(common, csz); +} + +void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf); +void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); +void ath9k_htc_beacon_update(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif); + +void ath9k_htc_rxep(void *priv, struct sk_buff *skb, + enum htc_endpoint_id ep_id); +void ath9k_htc_txep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id, + bool txok); + +void ath9k_htc_station_work(struct work_struct *work); +void ath9k_htc_aggr_work(struct work_struct *work); +void ath9k_ani_work(struct work_struct *work);; + +int ath9k_tx_init(struct ath9k_htc_priv *priv); +void ath9k_tx_tasklet(unsigned long data); +int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb); +void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); +bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, + enum ath9k_tx_queue_subtype qtype); +int get_hw_qnum(u16 queue, int *hwq_map); +int ath_txq_update(struct ath9k_htc_priv *priv, int qnum, + struct ath9k_tx_queue_info *qinfo); + +int ath9k_rx_init(struct ath9k_htc_priv *priv); +void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); +void ath9k_host_rx_init(struct ath9k_htc_priv *priv); +void ath9k_rx_tasklet(unsigned long data); + +void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); +void ath9k_init_leds(struct ath9k_htc_priv *priv); +void ath9k_deinit_leds(struct ath9k_htc_priv *priv); + +int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, + u16 devid); +void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); +#ifdef CONFIG_PM +int ath9k_htc_resume(struct htc_target *htc_handle); +#endif +#ifdef CONFIG_ATH9K_HTC_DEBUGFS +int ath9k_debug_create_root(void); +void ath9k_debug_remove_root(void); +int ath9k_init_debug(struct ath_hw *ah); +void ath9k_exit_debug(struct ath_hw *ah); +#else +static inline int ath9k_debug_create_root(void) { return 0; }; +static inline void ath9k_debug_remove_root(void) {}; +static inline int ath9k_init_debug(struct ath_hw *ah) { return 0; }; +static inline void ath9k_exit_debug(struct ath_hw *ah) {}; +#endif /* CONFIG_ATH9K_HTC_DEBUGFS */ + +#endif /* HTC_H */ diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c new file mode 100644 index 000000000000..25f5b5377bac --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "htc.h" + +#define FUDGE 2 + +static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, + struct ieee80211_bss_conf *bss_conf) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_beacon_state bs; + enum ath9k_int imask = 0; + int dtimperiod, dtimcount, sleepduration; + int cfpperiod, cfpcount, bmiss_timeout; + u32 nexttbtt = 0, intval, tsftu, htc_imask = 0; + u64 tsf; + int num_beacons, offset, dtim_dec_count, cfp_dec_count; + int ret; + u8 cmd_rsp; + + memset(&bs, 0, sizeof(bs)); + + intval = bss_conf->beacon_int & ATH9K_BEACON_PERIOD; + bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_int); + + /* + * Setup dtim and cfp parameters according to + * last beacon we received (which may be none). + */ + dtimperiod = bss_conf->dtim_period; + if (dtimperiod <= 0) /* NB: 0 if not known */ + dtimperiod = 1; + dtimcount = 1; + if (dtimcount >= dtimperiod) /* NB: sanity check */ + dtimcount = 0; + cfpperiod = 1; /* NB: no PCF support yet */ + cfpcount = 0; + + sleepduration = intval; + if (sleepduration <= 0) + sleepduration = intval; + + /* + * Pull nexttbtt forward to reflect the current + * TSF and calculate dtim+cfp state for the result. + */ + tsf = ath9k_hw_gettsf64(priv->ah); + tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; + + num_beacons = tsftu / intval + 1; + offset = tsftu % intval; + nexttbtt = tsftu - offset; + if (offset) + nexttbtt += intval; + + /* DTIM Beacon every dtimperiod Beacon */ + dtim_dec_count = num_beacons % dtimperiod; + /* CFP every cfpperiod DTIM Beacon */ + cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod; + if (dtim_dec_count) + cfp_dec_count++; + + dtimcount -= dtim_dec_count; + if (dtimcount < 0) + dtimcount += dtimperiod; + + cfpcount -= cfp_dec_count; + if (cfpcount < 0) + cfpcount += cfpperiod; + + bs.bs_intval = intval; + bs.bs_nexttbtt = nexttbtt; + bs.bs_dtimperiod = dtimperiod*intval; + bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; + bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; + bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; + bs.bs_cfpmaxduration = 0; + + /* + * Calculate the number of consecutive beacons to miss* before taking + * a BMISS interrupt. The configuration is specified in TU so we only + * need calculate based on the beacon interval. Note that we clamp the + * result to at most 15 beacons. + */ + if (sleepduration > intval) { + bs.bs_bmissthreshold = ATH_DEFAULT_BMISS_LIMIT / 2; + } else { + bs.bs_bmissthreshold = DIV_ROUND_UP(bmiss_timeout, intval); + if (bs.bs_bmissthreshold > 15) + bs.bs_bmissthreshold = 15; + else if (bs.bs_bmissthreshold <= 0) + bs.bs_bmissthreshold = 1; + } + + /* + * Calculate sleep duration. The configuration is given in ms. + * We ensure a multiple of the beacon period is used. Also, if the sleep + * duration is greater than the DTIM period then it makes senses + * to make it a multiple of that. + * + * XXX fixed at 100ms + */ + + bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration); + if (bs.bs_sleepduration > bs.bs_dtimperiod) + bs.bs_sleepduration = bs.bs_dtimperiod; + + /* TSF out of range threshold fixed at 1 second */ + bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; + + ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); + ath_print(common, ATH_DBG_BEACON, + "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", + bs.bs_bmissthreshold, bs.bs_sleepduration, + bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); + + /* Set the computed STA beacon timers */ + + WMI_CMD(WMI_DISABLE_INTR_CMDID); + ath9k_hw_set_sta_beacon_timers(priv->ah, &bs); + imask |= ATH9K_INT_BMISS; + htc_imask = cpu_to_be32(imask); + WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); +} + +static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, + struct ieee80211_bss_conf *bss_conf) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + enum ath9k_int imask = 0; + u32 nexttbtt, intval, htc_imask = 0; + int ret; + u8 cmd_rsp; + + intval = bss_conf->beacon_int & ATH9K_BEACON_PERIOD; + nexttbtt = intval; + intval |= ATH9K_BEACON_ENA; + if (priv->op_flags & OP_ENABLE_BEACON) + imask |= ATH9K_INT_SWBA; + + ath_print(common, ATH_DBG_BEACON, + "IBSS Beacon config, intval: %d, imask: 0x%x\n", + bss_conf->beacon_int, imask); + + WMI_CMD(WMI_DISABLE_INTR_CMDID); + ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); + priv->bmiss_cnt = 0; + htc_imask = cpu_to_be32(imask); + WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); +} + +void ath9k_htc_beacon_update(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + + spin_lock_bh(&priv->beacon_lock); + + if (priv->beacon) + dev_kfree_skb_any(priv->beacon); + + priv->beacon = ieee80211_beacon_get(priv->hw, vif); + if (!priv->beacon) + ath_print(common, ATH_DBG_BEACON, + "Unable to allocate beacon\n"); + + spin_unlock_bh(&priv->beacon_lock); +} + +void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) +{ + struct ath9k_htc_vif *avp = (void *)priv->vif->drv_priv; + struct tx_beacon_header beacon_hdr; + struct ath9k_htc_tx_ctl tx_ctl; + struct ieee80211_tx_info *info; + u8 *tx_fhdr; + + memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); + memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); + + /* FIXME: Handle BMISS */ + if (beacon_pending != 0) { + priv->bmiss_cnt++; + return; + } + + spin_lock_bh(&priv->beacon_lock); + + if (unlikely(priv->op_flags & OP_SCANNING)) { + spin_unlock_bh(&priv->beacon_lock); + return; + } + + if (unlikely(priv->beacon == NULL)) { + spin_unlock_bh(&priv->beacon_lock); + return; + } + + /* Free the old SKB first */ + dev_kfree_skb_any(priv->beacon); + + /* Get a new beacon */ + priv->beacon = ieee80211_beacon_get(priv->hw, priv->vif); + if (!priv->beacon) { + spin_unlock_bh(&priv->beacon_lock); + return; + } + + info = IEEE80211_SKB_CB(priv->beacon); + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + struct ieee80211_hdr *hdr = + (struct ieee80211_hdr *) priv->beacon->data; + priv->seq_no += 0x10; + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(priv->seq_no); + } + + tx_ctl.type = ATH9K_HTC_NORMAL; + beacon_hdr.vif_index = avp->index; + tx_fhdr = skb_push(priv->beacon, sizeof(beacon_hdr)); + memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); + + htc_send(priv->htc, priv->beacon, priv->beacon_ep, &tx_ctl); + + spin_unlock_bh(&priv->beacon_lock); +} + +void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + ath9k_htc_beacon_config_sta(priv, bss_conf); + break; + case NL80211_IFTYPE_ADHOC: + ath9k_htc_beacon_config_adhoc(priv, bss_conf); + break; + default: + ath_print(common, ATH_DBG_CONFIG, + "Unsupported beaconing mode\n"); + return; + } +} diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c new file mode 100644 index 000000000000..a653dec140b9 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -0,0 +1,713 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "htc.h" + +MODULE_AUTHOR("Atheros Communications"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("Atheros driver 802.11n HTC based wireless devices"); + +static unsigned int ath9k_debug = ATH_DBG_DEFAULT; +module_param_named(debug, ath9k_debug, uint, 0); +MODULE_PARM_DESC(debug, "Debugging mask"); + +int modparam_nohwcrypt; +module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); +MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); + +#define CHAN2G(_freq, _idx) { \ + .center_freq = (_freq), \ + .hw_value = (_idx), \ + .max_power = 20, \ +} + +static struct ieee80211_channel ath9k_2ghz_channels[] = { + CHAN2G(2412, 0), /* Channel 1 */ + CHAN2G(2417, 1), /* Channel 2 */ + CHAN2G(2422, 2), /* Channel 3 */ + CHAN2G(2427, 3), /* Channel 4 */ + CHAN2G(2432, 4), /* Channel 5 */ + CHAN2G(2437, 5), /* Channel 6 */ + CHAN2G(2442, 6), /* Channel 7 */ + CHAN2G(2447, 7), /* Channel 8 */ + CHAN2G(2452, 8), /* Channel 9 */ + CHAN2G(2457, 9), /* Channel 10 */ + CHAN2G(2462, 10), /* Channel 11 */ + CHAN2G(2467, 11), /* Channel 12 */ + CHAN2G(2472, 12), /* Channel 13 */ + CHAN2G(2484, 13), /* Channel 14 */ +}; + +/* Atheros hardware rate code addition for short premble */ +#define SHPCHECK(__hw_rate, __flags) \ + ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0) + +#define RATE(_bitrate, _hw_rate, _flags) { \ + .bitrate = (_bitrate), \ + .flags = (_flags), \ + .hw_value = (_hw_rate), \ + .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \ +} + +static struct ieee80211_rate ath9k_legacy_rates[] = { + RATE(10, 0x1b, 0), + RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp : 0x1e */ + RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp: 0x1d */ + RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), /* short: 0x1c */ + RATE(60, 0x0b, 0), + RATE(90, 0x0f, 0), + RATE(120, 0x0a, 0), + RATE(180, 0x0e, 0), + RATE(240, 0x09, 0), + RATE(360, 0x0d, 0), + RATE(480, 0x08, 0), + RATE(540, 0x0c, 0), +}; + +static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) +{ + int time_left; + + /* Firmware can take up to 50ms to get ready, to be safe use 1 second */ + time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ); + if (!time_left) { + dev_err(priv->dev, "ath9k_htc: Target is unresponsive\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) +{ + ath9k_exit_debug(priv->ah); + ath9k_hw_deinit(priv->ah); + tasklet_kill(&priv->wmi_tasklet); + tasklet_kill(&priv->rx_tasklet); + tasklet_kill(&priv->tx_tasklet); + kfree(priv->ah); + priv->ah = NULL; +} + +static void ath9k_deinit_device(struct ath9k_htc_priv *priv) +{ + struct ieee80211_hw *hw = priv->hw; + + wiphy_rfkill_stop_polling(hw->wiphy); + ath9k_deinit_leds(priv); + ieee80211_unregister_hw(hw); + ath9k_rx_cleanup(priv); + ath9k_tx_cleanup(priv); + ath9k_deinit_priv(priv); +} + +static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv, + u16 service_id, + void (*tx) (void *, + struct sk_buff *, + enum htc_endpoint_id, + bool txok), + enum htc_endpoint_id *ep_id) +{ + struct htc_service_connreq req; + + memset(&req, 0, sizeof(struct htc_service_connreq)); + + req.service_id = service_id; + req.ep_callbacks.priv = priv; + req.ep_callbacks.rx = ath9k_htc_rxep; + req.ep_callbacks.tx = tx; + + return htc_connect_service(priv->htc, &req, ep_id); +} + +static int ath9k_init_htc_services(struct ath9k_htc_priv *priv) +{ + int ret; + + /* WMI CMD*/ + ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep); + if (ret) + goto err; + + /* Beacon */ + ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, NULL, + &priv->beacon_ep); + if (ret) + goto err; + + /* CAB */ + ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep, + &priv->cab_ep); + if (ret) + goto err; + + + /* UAPSD */ + ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep, + &priv->uapsd_ep); + if (ret) + goto err; + + /* MGMT */ + ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep, + &priv->mgmt_ep); + if (ret) + goto err; + + /* DATA BE */ + ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep, + &priv->data_be_ep); + if (ret) + goto err; + + /* DATA BK */ + ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep, + &priv->data_bk_ep); + if (ret) + goto err; + + /* DATA VI */ + ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep, + &priv->data_vi_ep); + if (ret) + goto err; + + /* DATA VO */ + ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep, + &priv->data_vo_ep); + if (ret) + goto err; + + ret = htc_init(priv->htc); + if (ret) + goto err; + + return 0; + +err: + dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n"); + return ret; +} + +static int ath9k_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ath9k_htc_priv *priv = hw->priv; + + return ath_reg_notifier_apply(wiphy, request, + ath9k_hw_regulatory(priv->ah)); +} + +static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) +{ + struct ath_hw *ah = (struct ath_hw *) hw_priv; + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + __be32 val, reg = cpu_to_be32(reg_offset); + int r; + + r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID, + (u8 *) ®, sizeof(reg), + (u8 *) &val, sizeof(val), + 100); + if (unlikely(r)) { + ath_print(common, ATH_DBG_WMI, + "REGISTER READ FAILED: (0x%04x, %d)\n", + reg_offset, r); + return -EIO; + } + + return be32_to_cpu(val); +} + +static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) +{ + struct ath_hw *ah = (struct ath_hw *) hw_priv; + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + __be32 buf[2] = { + cpu_to_be32(reg_offset), + cpu_to_be32(val), + }; + int r; + + r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, + (u8 *) &buf, sizeof(buf), + (u8 *) &val, sizeof(val), + 100); + if (unlikely(r)) { + ath_print(common, ATH_DBG_WMI, + "REGISTER WRITE FAILED:(0x%04x, %d)\n", + reg_offset, r); + } +} + +static const struct ath_ops ath9k_common_ops = { + .read = ath9k_ioread32, + .write = ath9k_iowrite32, +}; + +static void ath_usb_read_cachesize(struct ath_common *common, int *csz) +{ + *csz = L1_CACHE_BYTES >> 2; +} + +static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data) +{ + struct ath_hw *ah = (struct ath_hw *) common->ah; + + (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); + + if (!ath9k_hw_wait(ah, + AR_EEPROM_STATUS_DATA, + AR_EEPROM_STATUS_DATA_BUSY | + AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, + AH_WAIT_TIMEOUT)) + return false; + + *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), + AR_EEPROM_STATUS_DATA_VAL); + + return true; +} + +static const struct ath_bus_ops ath9k_usb_bus_ops = { + .read_cachesize = ath_usb_read_cachesize, + .eeprom_read = ath_usb_eeprom_read, +}; + +static void setup_ht_cap(struct ath9k_htc_priv *priv, + struct ieee80211_sta_ht_cap *ht_info) +{ + ht_info->ht_supported = true; + ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_SM_PS | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_DSSSCCK40; + + ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; + + memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); + ht_info->mcs.rx_mask[0] = 0xff; + ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; +} + +static int ath9k_init_queues(struct ath9k_htc_priv *priv) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + int i; + + for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++) + priv->hwq_map[i] = -1; + + if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BE)) { + ath_print(common, ATH_DBG_FATAL, + "Unable to setup xmit queue for BE traffic\n"); + goto err; + } + + if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BK)) { + ath_print(common, ATH_DBG_FATAL, + "Unable to setup xmit queue for BK traffic\n"); + goto err; + } + if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_VI)) { + ath_print(common, ATH_DBG_FATAL, + "Unable to setup xmit queue for VI traffic\n"); + goto err; + } + if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_VO)) { + ath_print(common, ATH_DBG_FATAL, + "Unable to setup xmit queue for VO traffic\n"); + goto err; + } + + return 0; + +err: + return -EINVAL; +} + +static void ath9k_init_crypto(struct ath9k_htc_priv *priv) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + int i = 0; + + /* Get the hardware key cache size. */ + common->keymax = priv->ah->caps.keycache_size; + if (common->keymax > ATH_KEYMAX) { + ath_print(common, ATH_DBG_ANY, + "Warning, using only %u entries in %u key cache\n", + ATH_KEYMAX, common->keymax); + common->keymax = ATH_KEYMAX; + } + + /* + * Reset the key cache since some parts do not + * reset the contents on initial power up. + */ + for (i = 0; i < common->keymax; i++) + ath9k_hw_keyreset(priv->ah, (u16) i); + + if (ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, + ATH9K_CIPHER_TKIP, NULL)) { + /* + * Whether we should enable h/w TKIP MIC. + * XXX: if we don't support WME TKIP MIC, then we wouldn't + * report WMM capable, so it's always safe to turn on + * TKIP MIC in this case. + */ + ath9k_hw_setcapability(priv->ah, ATH9K_CAP_TKIP_MIC, 0, 1, NULL); + } + + /* + * Check whether the separate key cache entries + * are required to handle both tx+rx MIC keys. + * With split mic keys the number of stations is limited + * to 27 otherwise 59. + */ + if (ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, + ATH9K_CIPHER_TKIP, NULL) + && ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, + ATH9K_CIPHER_MIC, NULL) + && ath9k_hw_getcapability(priv->ah, ATH9K_CAP_TKIP_SPLIT, + 0, NULL)) + common->splitmic = 1; + + /* turn on mcast key search if possible */ + if (!ath9k_hw_getcapability(priv->ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) + (void)ath9k_hw_setcapability(priv->ah, ATH9K_CAP_MCAST_KEYSRCH, + 1, 1, NULL); +} + +static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) +{ + if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) { + priv->sbands[IEEE80211_BAND_2GHZ].channels = + ath9k_2ghz_channels; + priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; + priv->sbands[IEEE80211_BAND_2GHZ].n_channels = + ARRAY_SIZE(ath9k_2ghz_channels); + priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; + priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates = + ARRAY_SIZE(ath9k_legacy_rates); + } +} + +static void ath9k_init_misc(struct ath9k_htc_priv *priv) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + + common->tx_chainmask = priv->ah->caps.tx_chainmask; + common->rx_chainmask = priv->ah->caps.rx_chainmask; + + if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) + memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); + + priv->op_flags |= OP_TXAGGR; +} + +static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) +{ + struct ath_hw *ah = NULL; + struct ath_common *common; + int ret = 0, csz = 0; + + priv->op_flags |= OP_INVALID; + + ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); + if (!ah) + return -ENOMEM; + + ah->hw_version.devid = devid; + ah->hw_version.subsysid = 0; /* FIXME */ + priv->ah = ah; + + common = ath9k_hw_common(ah); + common->ops = &ath9k_common_ops; + common->bus_ops = &ath9k_usb_bus_ops; + common->ah = ah; + common->hw = priv->hw; + common->priv = priv; + common->debug_mask = ath9k_debug; + + spin_lock_init(&priv->wmi->wmi_lock); + spin_lock_init(&priv->beacon_lock); + mutex_init(&priv->mutex); + mutex_init(&priv->aggr_work.mutex); + tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, + (unsigned long)priv); + tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, + (unsigned long)priv); + tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); + INIT_DELAYED_WORK(&priv->ath9k_aggr_work, ath9k_htc_aggr_work); + INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); + + /* + * Cache line size is used to size and align various + * structures used to communicate with the hardware. + */ + ath_read_cachesize(common, &csz); + common->cachelsz = csz << 2; /* convert to bytes */ + + ret = ath9k_hw_init(ah); + if (ret) { + ath_print(common, ATH_DBG_FATAL, + "Unable to initialize hardware; " + "initialization status: %d\n", ret); + goto err_hw; + } + + ret = ath9k_init_debug(ah); + if (ret) { + ath_print(common, ATH_DBG_FATAL, + "Unable to create debugfs files\n"); + goto err_debug; + } + + ret = ath9k_init_queues(priv); + if (ret) + goto err_queues; + + ath9k_init_crypto(priv); + ath9k_init_channels_rates(priv); + ath9k_init_misc(priv); + + return 0; + +err_queues: + ath9k_exit_debug(ah); +err_debug: + ath9k_hw_deinit(ah); +err_hw: + + kfree(ah); + priv->ah = NULL; + + return ret; +} + +static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, + struct ieee80211_hw *hw) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + + hw->flags = IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_AMPDU_AGGREGATION | + IEEE80211_HW_SPECTRUM_MGMT | + IEEE80211_HW_HAS_RATE_CONTROL; + + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + + hw->queues = 4; + hw->channel_change_time = 5000; + hw->max_listen_interval = 10; + hw->vif_data_size = sizeof(struct ath9k_htc_vif); + hw->sta_data_size = sizeof(struct ath9k_htc_sta); + + /* tx_frame_hdr is larger than tx_mgmt_hdr anyway */ + hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) + + sizeof(struct htc_frame_hdr) + 4; + + if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + &priv->sbands[IEEE80211_BAND_2GHZ]; + + if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) { + if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) + setup_ht_cap(priv, + &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap); + } + + SET_IEEE80211_PERM_ADDR(hw, common->macaddr); +} + +static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid) +{ + struct ieee80211_hw *hw = priv->hw; + struct ath_common *common; + struct ath_hw *ah; + int error = 0; + struct ath_regulatory *reg; + + /* Bring up device */ + error = ath9k_init_priv(priv, devid); + if (error != 0) + goto err_init; + + ah = priv->ah; + common = ath9k_hw_common(ah); + ath9k_set_hw_capab(priv, hw); + + /* Initialize regulatory */ + error = ath_regd_init(&common->regulatory, priv->hw->wiphy, + ath9k_reg_notifier); + if (error) + goto err_regd; + + reg = &common->regulatory; + + /* Setup TX */ + error = ath9k_tx_init(priv); + if (error != 0) + goto err_tx; + + /* Setup RX */ + error = ath9k_rx_init(priv); + if (error != 0) + goto err_rx; + + /* Register with mac80211 */ + error = ieee80211_register_hw(hw); + if (error) + goto err_register; + + /* Handle world regulatory */ + if (!ath_is_world_regd(reg)) { + error = regulatory_hint(hw->wiphy, reg->alpha2); + if (error) + goto err_world; + } + + ath9k_init_leds(priv); + ath9k_start_rfkill_poll(priv); + + return 0; + +err_world: + ieee80211_unregister_hw(hw); +err_register: + ath9k_rx_cleanup(priv); +err_rx: + ath9k_tx_cleanup(priv); +err_tx: + /* Nothing */ +err_regd: + ath9k_deinit_priv(priv); +err_init: + return error; +} + +int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, + u16 devid) +{ + struct ieee80211_hw *hw; + struct ath9k_htc_priv *priv; + int ret; + + hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops); + if (!hw) + return -ENOMEM; + + priv = hw->priv; + priv->hw = hw; + priv->htc = htc_handle; + priv->dev = dev; + htc_handle->drv_priv = priv; + SET_IEEE80211_DEV(hw, priv->dev); + + ret = ath9k_htc_wait_for_target(priv); + if (ret) + goto err_free; + + priv->wmi = ath9k_init_wmi(priv); + if (!priv->wmi) { + ret = -EINVAL; + goto err_free; + } + + ret = ath9k_init_htc_services(priv); + if (ret) + goto err_init; + + ret = ath9k_init_device(priv, devid); + if (ret) + goto err_init; + + return 0; + +err_init: + ath9k_deinit_wmi(priv); +err_free: + ieee80211_free_hw(hw); + return ret; +} + +void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug) +{ + if (htc_handle->drv_priv) { + ath9k_deinit_device(htc_handle->drv_priv); + ath9k_deinit_wmi(htc_handle->drv_priv); + ieee80211_free_hw(htc_handle->drv_priv->hw); + } +} + +#ifdef CONFIG_PM +int ath9k_htc_resume(struct htc_target *htc_handle) +{ + int ret; + + ret = ath9k_htc_wait_for_target(htc_handle->drv_priv); + if (ret) + return ret; + + ret = ath9k_init_htc_services(htc_handle->drv_priv); + return ret; +} +#endif + +static int __init ath9k_htc_init(void) +{ + int error; + + error = ath9k_debug_create_root(); + if (error < 0) { + printk(KERN_ERR + "ath9k_htc: Unable to create debugfs root: %d\n", + error); + goto err_dbg; + } + + error = ath9k_hif_usb_init(); + if (error < 0) { + printk(KERN_ERR + "ath9k_htc: No USB devices found," + " driver not installed.\n"); + error = -ENODEV; + goto err_usb; + } + + return 0; + +err_usb: + ath9k_debug_remove_root(); +err_dbg: + return error; +} +module_init(ath9k_htc_init); + +static void __exit ath9k_htc_exit(void) +{ + ath9k_hif_usb_exit(); + ath9k_debug_remove_root(); + printk(KERN_INFO "ath9k_htc: Driver unloaded\n"); +} +module_exit(ath9k_htc_exit); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c new file mode 100644 index 000000000000..3184a2ac7b88 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -0,0 +1,1626 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "htc.h" + +#ifdef CONFIG_ATH9K_HTC_DEBUGFS +static struct dentry *ath9k_debugfs_root; +#endif + +/*************/ +/* Utilities */ +/*************/ + +static void ath_update_txpow(struct ath9k_htc_priv *priv) +{ + struct ath_hw *ah = priv->ah; + u32 txpow; + + if (priv->curtxpow != priv->txpowlimit) { + ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit); + /* read back in case value is clamped */ + ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); + priv->curtxpow = txpow; + } +} + +/* HACK Alert: Use 11NG for 2.4, use 11NA for 5 */ +static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, + struct ath9k_channel *ichan) +{ + enum htc_phymode mode; + + mode = HTC_MODE_AUTO; + + switch (ichan->chanmode) { + case CHANNEL_G: + case CHANNEL_G_HT20: + case CHANNEL_G_HT40PLUS: + case CHANNEL_G_HT40MINUS: + mode = HTC_MODE_11NG; + break; + case CHANNEL_A: + case CHANNEL_A_HT20: + case CHANNEL_A_HT40PLUS: + case CHANNEL_A_HT40MINUS: + mode = HTC_MODE_11NA; + break; + default: + break; + } + + return mode; +} + +static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, + struct ieee80211_hw *hw, + struct ath9k_channel *hchan) +{ + struct ath_hw *ah = priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_conf *conf = &common->hw->conf; + bool fastcc = true; + struct ieee80211_channel *channel = hw->conf.channel; + enum htc_phymode mode; + u16 htc_mode; + u8 cmd_rsp; + int ret; + + if (priv->op_flags & OP_INVALID) + return -EIO; + + if (priv->op_flags & OP_FULL_RESET) + fastcc = false; + + /* Fiddle around with fastcc later on, for now just use full reset */ + fastcc = false; + + htc_stop(priv->htc); + WMI_CMD(WMI_DISABLE_INTR_CMDID); + WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); + WMI_CMD(WMI_STOP_RECV_CMDID); + + ath_print(common, ATH_DBG_CONFIG, + "(%u MHz) -> (%u MHz), HT: %d, HT40: %d\n", + priv->ah->curchan->channel, + channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf)); + + ret = ath9k_hw_reset(ah, hchan, fastcc); + if (ret) { + ath_print(common, ATH_DBG_FATAL, + "Unable to reset channel (%u Mhz) " + "reset status %d\n", channel->center_freq, ret); + goto err; + } + + ath_update_txpow(priv); + + WMI_CMD(WMI_START_RECV_CMDID); + if (ret) + goto err; + + ath9k_host_rx_init(priv); + + mode = ath9k_htc_get_curmode(priv, hchan); + htc_mode = cpu_to_be16(mode); + WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); + if (ret) + goto err; + + WMI_CMD(WMI_ENABLE_INTR_CMDID); + if (ret) + goto err; + + htc_start(priv->htc); + + priv->op_flags &= ~OP_FULL_RESET; +err: + return ret; +} + +static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_target_vif hvif; + int ret = 0; + u8 cmd_rsp; + + if (priv->nvifs > 0) + return -ENOBUFS; + + memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); + memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); + + hvif.opmode = cpu_to_be32(HTC_M_MONITOR); + priv->ah->opmode = NL80211_IFTYPE_MONITOR; + hvif.index = priv->nvifs; + + WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); + if (ret) + return ret; + + priv->nvifs++; + return 0; +} + +static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_target_vif hvif; + int ret = 0; + u8 cmd_rsp; + + memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); + memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); + hvif.index = 0; /* Should do for now */ + WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); + priv->nvifs--; + + return ret; +} + +static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_target_sta tsta; + struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; + struct ath9k_htc_sta *ista; + int ret; + u8 cmd_rsp; + + if (priv->nstations >= ATH9K_HTC_MAX_STA) + return -ENOBUFS; + + memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); + + if (sta) { + ista = (struct ath9k_htc_sta *) sta->drv_priv; + memcpy(&tsta.macaddr, sta->addr, ETH_ALEN); + memcpy(&tsta.bssid, common->curbssid, ETH_ALEN); + tsta.associd = common->curaid; + tsta.is_vif_sta = 0; + tsta.valid = true; + ista->index = priv->nstations; + } else { + memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); + tsta.is_vif_sta = 1; + } + + tsta.sta_index = priv->nstations; + tsta.vif_index = avp->index; + tsta.maxampdu = 0xffff; + if (sta && sta->ht_cap.ht_supported) + tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); + + WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); + if (ret) { + if (sta) + ath_print(common, ATH_DBG_FATAL, + "Unable to add station entry for: %pM\n", sta->addr); + return ret; + } + + if (sta) + ath_print(common, ATH_DBG_CONFIG, + "Added a station entry for: %pM (idx: %d)\n", + sta->addr, tsta.sta_index); + + priv->nstations++; + return 0; +} + +static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_sta *ista; + int ret; + u8 cmd_rsp, sta_idx; + + if (sta) { + ista = (struct ath9k_htc_sta *) sta->drv_priv; + sta_idx = ista->index; + } else { + sta_idx = 0; + } + + WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); + if (ret) { + if (sta) + ath_print(common, ATH_DBG_FATAL, + "Unable to remove station entry for: %pM\n", + sta->addr); + return ret; + } + + if (sta) + ath_print(common, ATH_DBG_CONFIG, + "Removed a station entry for: %pM (idx: %d)\n", + sta->addr, sta_idx); + + priv->nstations--; + return 0; +} + +static int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) +{ + struct ath9k_htc_cap_target tcap; + int ret; + u8 cmd_rsp; + + memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); + + /* FIXME: Values are hardcoded */ + tcap.flags = 0x240c40; + tcap.flags_ext = 0x80601000; + tcap.ampdu_limit = 0xffff0000; + tcap.ampdu_subframes = 20; + tcap.tx_chainmask_legacy = 1; + tcap.protmode = 1; + tcap.tx_chainmask = 1; + + WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); + + return ret; +} + +static int ath9k_htc_init_rate(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; + struct ieee80211_supported_band *sband; + struct ath9k_htc_target_rate trate; + u32 caps = 0; + u8 cmd_rsp; + int i, j, ret; + + memset(&trate, 0, sizeof(trate)); + + /* Only 2GHz is supported */ + sband = priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ]; + + for (i = 0, j = 0; i < sband->n_bitrates; i++) { + if (sta->supp_rates[sband->band] & BIT(i)) { + priv->tgt_rate.rates.legacy_rates.rs_rates[j] + = (sband->bitrates[i].bitrate * 2) / 10; + j++; + } + } + priv->tgt_rate.rates.legacy_rates.rs_nrates = j; + + if (sta->ht_cap.ht_supported) { + for (i = 0, j = 0; i < 77; i++) { + if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) + priv->tgt_rate.rates.ht_rates.rs_rates[j++] = i; + if (j == ATH_HTC_RATE_MAX) + break; + } + priv->tgt_rate.rates.ht_rates.rs_nrates = j; + + caps = WLAN_RC_HT_FLAG; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) + caps |= WLAN_RC_40_FLAG; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + caps |= WLAN_RC_SGI_FLAG; + + } + + priv->tgt_rate.sta_index = ista->index; + priv->tgt_rate.isnew = 1; + trate = priv->tgt_rate; + priv->tgt_rate.capflags = caps; + trate.capflags = cpu_to_be32(caps); + + WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate); + if (ret) { + ath_print(common, ATH_DBG_FATAL, + "Unable to initialize Rate information on target\n"); + return ret; + } + + ath_print(common, ATH_DBG_CONFIG, + "Updated target STA: %pM (caps: 0x%x)\n", sta->addr, caps); + return 0; +} + +static bool check_rc_update(struct ieee80211_hw *hw, bool *cw40) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + + if (!conf_is_ht(conf)) + return false; + + if (!(priv->op_flags & OP_ASSOCIATED) || + (priv->op_flags & OP_SCANNING)) + return false; + + if (conf_is_ht40(conf)) { + if (priv->ah->curchan->chanmode & + (CHANNEL_HT40PLUS | CHANNEL_HT40MINUS)) { + return false; + } else { + *cw40 = true; + return true; + } + } else { /* ht20 */ + if (priv->ah->curchan->chanmode & CHANNEL_HT20) + return false; + else + return true; + } +} + +static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40) +{ + struct ath9k_htc_target_rate trate; + struct ath_common *common = ath9k_hw_common(priv->ah); + int ret; + u8 cmd_rsp; + + memset(&trate, 0, sizeof(trate)); + + trate = priv->tgt_rate; + + if (is_cw40) + priv->tgt_rate.capflags |= WLAN_RC_40_FLAG; + else + priv->tgt_rate.capflags &= ~WLAN_RC_40_FLAG; + + trate.capflags = cpu_to_be32(priv->tgt_rate.capflags); + + WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate); + if (ret) { + ath_print(common, ATH_DBG_FATAL, + "Unable to update Rate information on target\n"); + return; + } + + ath_print(common, ATH_DBG_CONFIG, "Rate control updated with " + "caps:0x%x on target\n", priv->tgt_rate.capflags); +} + +static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif, + u8 *sta_addr, u8 tid, bool oper) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_target_aggr aggr; + struct ieee80211_sta *sta = NULL; + struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; + int ret = 0; + u8 cmd_rsp; + + if (tid > ATH9K_HTC_MAX_TID) + return -EINVAL; + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, sta_addr); + if (sta) { + ista = (struct ath9k_htc_sta *) sta->drv_priv; + } else { + rcu_read_unlock(); + return -EINVAL; + } + + if (!ista) { + rcu_read_unlock(); + return -EINVAL; + } + + memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); + + aggr.sta_index = ista->index; + rcu_read_unlock(); + aggr.tidno = tid; + aggr.aggr_enable = oper; + + if (oper) + ista->tid_state[tid] = AGGR_START; + else + ista->tid_state[tid] = AGGR_STOP; + + WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); + if (ret) + ath_print(common, ATH_DBG_CONFIG, + "Unable to %s TX aggregation for (%pM, %d)\n", + (oper) ? "start" : "stop", sta->addr, tid); + else + ath_print(common, ATH_DBG_CONFIG, + "%s aggregation for (%pM, %d)\n", + (oper) ? "Starting" : "Stopping", sta->addr, tid); + + return ret; +} + +void ath9k_htc_aggr_work(struct work_struct *work) +{ + int ret = 0; + struct ath9k_htc_priv *priv = + container_of(work, struct ath9k_htc_priv, + ath9k_aggr_work.work); + struct ath9k_htc_aggr_work *wk = &priv->aggr_work; + + mutex_lock(&wk->mutex); + + switch (wk->action) { + case IEEE80211_AMPDU_TX_START: + ret = ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr, + wk->tid, true); + if (!ret) + ieee80211_start_tx_ba_cb(wk->vif, wk->sta_addr, + wk->tid); + break; + case IEEE80211_AMPDU_TX_STOP: + ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr, + wk->tid, false); + ieee80211_stop_tx_ba_cb(wk->vif, wk->sta_addr, wk->tid); + break; + default: + ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, + "Unknown AMPDU action\n"); + } + + mutex_unlock(&wk->mutex); +} + +/*********/ +/* DEBUG */ +/*********/ + +#ifdef CONFIG_ATH9K_HTC_DEBUGFS + +static int ath9k_debugfs_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = + (struct ath9k_htc_priv *) file->private_data; + struct ath9k_htc_target_stats cmd_rsp; + char buf[512]; + unsigned int len = 0; + int ret = 0; + + memset(&cmd_rsp, 0, sizeof(cmd_rsp)); + + WMI_CMD(WMI_TGT_STATS_CMDID); + if (ret) + return -EINVAL; + + + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Short Retries", + be32_to_cpu(cmd_rsp.tx_shortretry)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Long Retries", + be32_to_cpu(cmd_rsp.tx_longretry)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Xretries", + be32_to_cpu(cmd_rsp.tx_xretries)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Unaggr. Xretries", + be32_to_cpu(cmd_rsp.ht_txunaggr_xretry)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Xretries (HT)", + be32_to_cpu(cmd_rsp.ht_tx_xretries)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Rate", priv->debug.txrate); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_tgt_stats = { + .read = read_file_tgt_stats, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + +static ssize_t read_file_xmit(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = + (struct ath9k_htc_priv *) file->private_data; + char buf[512]; + unsigned int len = 0; + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "Buffers queued", + priv->debug.tx_stats.buf_queued); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "Buffers completed", + priv->debug.tx_stats.buf_completed); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs queued", + priv->debug.tx_stats.skb_queued); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs completed", + priv->debug.tx_stats.skb_completed); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_xmit = { + .read = read_file_xmit, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + +static ssize_t read_file_recv(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = + (struct ath9k_htc_priv *) file->private_data; + char buf[512]; + unsigned int len = 0; + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs allocated", + priv->debug.rx_stats.skb_allocated); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs completed", + priv->debug.rx_stats.skb_completed); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs Dropped", + priv->debug.rx_stats.skb_dropped); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_recv = { + .read = read_file_recv, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + +int ath9k_init_debug(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + + if (!ath9k_debugfs_root) + return -ENOENT; + + priv->debug.debugfs_phy = debugfs_create_dir(wiphy_name(priv->hw->wiphy), + ath9k_debugfs_root); + if (!priv->debug.debugfs_phy) + goto err; + + priv->debug.debugfs_tgt_stats = debugfs_create_file("tgt_stats", S_IRUSR, + priv->debug.debugfs_phy, + priv, &fops_tgt_stats); + if (!priv->debug.debugfs_tgt_stats) + goto err; + + + priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR, + priv->debug.debugfs_phy, + priv, &fops_xmit); + if (!priv->debug.debugfs_xmit) + goto err; + + priv->debug.debugfs_recv = debugfs_create_file("recv", S_IRUSR, + priv->debug.debugfs_phy, + priv, &fops_recv); + if (!priv->debug.debugfs_recv) + goto err; + + return 0; + +err: + ath9k_exit_debug(ah); + return -ENOMEM; +} + +void ath9k_exit_debug(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + + debugfs_remove(priv->debug.debugfs_recv); + debugfs_remove(priv->debug.debugfs_xmit); + debugfs_remove(priv->debug.debugfs_tgt_stats); + debugfs_remove(priv->debug.debugfs_phy); +} + +int ath9k_debug_create_root(void) +{ + ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); + if (!ath9k_debugfs_root) + return -ENOENT; + + return 0; +} + +void ath9k_debug_remove_root(void) +{ + debugfs_remove(ath9k_debugfs_root); + ath9k_debugfs_root = NULL; +} + +#endif /* CONFIG_ATH9K_HTC_DEBUGFS */ + +/*******/ +/* ANI */ +/*******/ + +static void ath_start_ani(struct ath9k_htc_priv *priv) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + unsigned long timestamp = jiffies_to_msecs(jiffies); + + common->ani.longcal_timer = timestamp; + common->ani.shortcal_timer = timestamp; + common->ani.checkani_timer = timestamp; + + ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work, + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); +} + +void ath9k_ani_work(struct work_struct *work) +{ + struct ath9k_htc_priv *priv = + container_of(work, struct ath9k_htc_priv, + ath9k_ani_work.work); + struct ath_hw *ah = priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + bool longcal = false; + bool shortcal = false; + bool aniflag = false; + unsigned int timestamp = jiffies_to_msecs(jiffies); + u32 cal_interval, short_cal_interval; + + short_cal_interval = ATH_STA_SHORT_CALINTERVAL; + + /* Long calibration runs independently of short calibration. */ + if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { + longcal = true; + ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); + common->ani.longcal_timer = timestamp; + } + + /* Short calibration applies only while caldone is false */ + if (!common->ani.caldone) { + if ((timestamp - common->ani.shortcal_timer) >= + short_cal_interval) { + shortcal = true; + ath_print(common, ATH_DBG_ANI, + "shortcal @%lu\n", jiffies); + common->ani.shortcal_timer = timestamp; + common->ani.resetcal_timer = timestamp; + } + } else { + if ((timestamp - common->ani.resetcal_timer) >= + ATH_RESTART_CALINTERVAL) { + common->ani.caldone = ath9k_hw_reset_calvalid(ah); + if (common->ani.caldone) + common->ani.resetcal_timer = timestamp; + } + } + + /* Verify whether we must check ANI */ + if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { + aniflag = true; + common->ani.checkani_timer = timestamp; + } + + /* Skip all processing if there's nothing to do. */ + if (longcal || shortcal || aniflag) { + /* Call ANI routine if necessary */ + if (aniflag) + ath9k_hw_ani_monitor(ah, ah->curchan); + + /* Perform calibration if necessary */ + if (longcal || shortcal) { + common->ani.caldone = + ath9k_hw_calibrate(ah, ah->curchan, + common->rx_chainmask, + longcal); + + if (longcal) + common->ani.noise_floor = + ath9k_hw_getchan_noise(ah, ah->curchan); + + ath_print(common, ATH_DBG_ANI, + " calibrate chan %u/%x nf: %d\n", + ah->curchan->channel, + ah->curchan->channelFlags, + common->ani.noise_floor); + } + } + + /* + * Set timer interval based on previous results. + * The interval must be the shortest necessary to satisfy ANI, + * short calibration and long calibration. + */ + cal_interval = ATH_LONG_CALINTERVAL; + if (priv->ah->config.enable_ani) + cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); + if (!common->ani.caldone) + cal_interval = min(cal_interval, (u32)short_cal_interval); + + ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work, + msecs_to_jiffies(cal_interval)); +} + +/*******/ +/* LED */ +/*******/ + +static void ath9k_led_blink_work(struct work_struct *work) +{ + struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, + ath9k_led_blink_work.work); + + if (!(priv->op_flags & OP_LED_ASSOCIATED)) + return; + + if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) || + (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) + ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); + else + ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, + (priv->op_flags & OP_LED_ON) ? 1 : 0); + + ieee80211_queue_delayed_work(priv->hw, + &priv->ath9k_led_blink_work, + (priv->op_flags & OP_LED_ON) ? + msecs_to_jiffies(priv->led_off_duration) : + msecs_to_jiffies(priv->led_on_duration)); + + priv->led_on_duration = priv->led_on_cnt ? + max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) : + ATH_LED_ON_DURATION_IDLE; + priv->led_off_duration = priv->led_off_cnt ? + max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) : + ATH_LED_OFF_DURATION_IDLE; + priv->led_on_cnt = priv->led_off_cnt = 0; + + if (priv->op_flags & OP_LED_ON) + priv->op_flags &= ~OP_LED_ON; + else + priv->op_flags |= OP_LED_ON; +} + +static void ath9k_led_brightness_work(struct work_struct *work) +{ + struct ath_led *led = container_of(work, struct ath_led, + brightness_work.work); + struct ath9k_htc_priv *priv = led->priv; + + switch (led->brightness) { + case LED_OFF: + if (led->led_type == ATH_LED_ASSOC || + led->led_type == ATH_LED_RADIO) { + ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, + (led->led_type == ATH_LED_RADIO)); + priv->op_flags &= ~OP_LED_ASSOCIATED; + if (led->led_type == ATH_LED_RADIO) + priv->op_flags &= ~OP_LED_ON; + } else { + priv->led_off_cnt++; + } + break; + case LED_FULL: + if (led->led_type == ATH_LED_ASSOC) { + priv->op_flags |= OP_LED_ASSOCIATED; + ieee80211_queue_delayed_work(priv->hw, + &priv->ath9k_led_blink_work, 0); + } else if (led->led_type == ATH_LED_RADIO) { + ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); + priv->op_flags |= OP_LED_ON; + } else { + priv->led_on_cnt++; + } + break; + default: + break; + } +} + +static void ath9k_led_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); + struct ath9k_htc_priv *priv = led->priv; + + led->brightness = brightness; + if (!(priv->op_flags & OP_LED_DEINIT)) + ieee80211_queue_delayed_work(priv->hw, + &led->brightness_work, 0); +} + +static void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv) +{ + cancel_delayed_work_sync(&priv->radio_led.brightness_work); + cancel_delayed_work_sync(&priv->assoc_led.brightness_work); + cancel_delayed_work_sync(&priv->tx_led.brightness_work); + cancel_delayed_work_sync(&priv->rx_led.brightness_work); +} + +static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led, + char *trigger) +{ + int ret; + + led->priv = priv; + led->led_cdev.name = led->name; + led->led_cdev.default_trigger = trigger; + led->led_cdev.brightness_set = ath9k_led_brightness; + + ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev); + if (ret) + ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, + "Failed to register led:%s", led->name); + else + led->registered = 1; + + INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work); + + return ret; +} + +static void ath9k_unregister_led(struct ath_led *led) +{ + if (led->registered) { + led_classdev_unregister(&led->led_cdev); + led->registered = 0; + } +} + +void ath9k_deinit_leds(struct ath9k_htc_priv *priv) +{ + priv->op_flags |= OP_LED_DEINIT; + ath9k_unregister_led(&priv->assoc_led); + priv->op_flags &= ~OP_LED_ASSOCIATED; + ath9k_unregister_led(&priv->tx_led); + ath9k_unregister_led(&priv->rx_led); + ath9k_unregister_led(&priv->radio_led); + ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); +} + +void ath9k_init_leds(struct ath9k_htc_priv *priv) +{ + char *trigger; + int ret; + + if (AR_SREV_9287(priv->ah)) + priv->ah->led_pin = ATH_LED_PIN_9287; + else if (AR_SREV_9271(priv->ah)) + priv->ah->led_pin = ATH_LED_PIN_9271; + else + priv->ah->led_pin = ATH_LED_PIN_DEF; + + /* Configure gpio 1 for output */ + ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + /* LED off, active low */ + ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); + + INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work); + + trigger = ieee80211_get_radio_led_name(priv->hw); + snprintf(priv->radio_led.name, sizeof(priv->radio_led.name), + "ath9k-%s::radio", wiphy_name(priv->hw->wiphy)); + ret = ath9k_register_led(priv, &priv->radio_led, trigger); + priv->radio_led.led_type = ATH_LED_RADIO; + if (ret) + goto fail; + + trigger = ieee80211_get_assoc_led_name(priv->hw); + snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name), + "ath9k-%s::assoc", wiphy_name(priv->hw->wiphy)); + ret = ath9k_register_led(priv, &priv->assoc_led, trigger); + priv->assoc_led.led_type = ATH_LED_ASSOC; + if (ret) + goto fail; + + trigger = ieee80211_get_tx_led_name(priv->hw); + snprintf(priv->tx_led.name, sizeof(priv->tx_led.name), + "ath9k-%s::tx", wiphy_name(priv->hw->wiphy)); + ret = ath9k_register_led(priv, &priv->tx_led, trigger); + priv->tx_led.led_type = ATH_LED_TX; + if (ret) + goto fail; + + trigger = ieee80211_get_rx_led_name(priv->hw); + snprintf(priv->rx_led.name, sizeof(priv->rx_led.name), + "ath9k-%s::rx", wiphy_name(priv->hw->wiphy)); + ret = ath9k_register_led(priv, &priv->rx_led, trigger); + priv->rx_led.led_type = ATH_LED_RX; + if (ret) + goto fail; + + priv->op_flags &= ~OP_LED_DEINIT; + + return; + +fail: + cancel_delayed_work_sync(&priv->ath9k_led_blink_work); + ath9k_deinit_leds(priv); +} + +/*******************/ +/* Rfkill */ +/*******************/ + +static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv) +{ + return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) == + priv->ah->rfkill_polarity; +} + +static void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw) +{ + struct ath9k_htc_priv *priv = hw->priv; + bool blocked = !!ath_is_rfkill_set(priv); + + wiphy_rfkill_set_hw_state(hw->wiphy, blocked); +} + +void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv) +{ + if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + wiphy_rfkill_start_polling(priv->hw->wiphy); +} + +/**********************/ +/* mac80211 Callbacks */ +/**********************/ + +static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + struct ath9k_htc_priv *priv = hw->priv; + int padpos, padsize; + + hdr = (struct ieee80211_hdr *) skb->data; + + /* Add the padding after the header if this is not already done */ + padpos = ath9k_cmn_padpos(hdr->frame_control); + padsize = padpos & 3; + if (padsize && skb->len > padpos) { + if (skb_headroom(skb) < padsize) + return -1; + skb_push(skb, padsize); + memmove(skb->data, skb->data + padsize, padpos); + } + + if (ath9k_htc_tx_start(priv, skb) != 0) { + ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, "Tx failed"); + goto fail_tx; + } + + return 0; + +fail_tx: + dev_kfree_skb_any(skb); + return 0; +} + +static int ath9k_htc_start(struct ieee80211_hw *hw) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath_hw *ah = priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_channel *curchan = hw->conf.channel; + struct ath9k_channel *init_channel; + int ret = 0; + enum htc_phymode mode; + u16 htc_mode; + u8 cmd_rsp; + + ath_print(common, ATH_DBG_CONFIG, + "Starting driver with initial channel: %d MHz\n", + curchan->center_freq); + + mutex_lock(&priv->mutex); + + /* setup initial channel */ + init_channel = ath9k_cmn_get_curchannel(hw, ah); + + /* Reset SERDES registers */ + ath9k_hw_configpcipowersave(ah, 0, 0); + + ath9k_hw_htc_resetinit(ah); + ret = ath9k_hw_reset(ah, init_channel, false); + if (ret) { + ath_print(common, ATH_DBG_FATAL, + "Unable to reset hardware; reset status %d " + "(freq %u MHz)\n", ret, curchan->center_freq); + goto mutex_unlock; + } + + ath_update_txpow(priv); + + mode = ath9k_htc_get_curmode(priv, init_channel); + htc_mode = cpu_to_be16(mode); + WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); + if (ret) + goto mutex_unlock; + + WMI_CMD(WMI_ATH_INIT_CMDID); + if (ret) + goto mutex_unlock; + + WMI_CMD(WMI_START_RECV_CMDID); + if (ret) + goto mutex_unlock; + + ath9k_host_rx_init(priv); + + priv->op_flags &= ~OP_INVALID; + htc_start(priv->htc); + +mutex_unlock: + mutex_unlock(&priv->mutex); + return ret; +} + +static void ath9k_htc_stop(struct ieee80211_hw *hw) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath_hw *ah = priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + int ret = 0; + u8 cmd_rsp; + + mutex_lock(&priv->mutex); + + if (priv->op_flags & OP_INVALID) { + ath_print(common, ATH_DBG_ANY, "Device not present\n"); + mutex_unlock(&priv->mutex); + return; + } + + htc_stop(priv->htc); + WMI_CMD(WMI_DISABLE_INTR_CMDID); + WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); + WMI_CMD(WMI_STOP_RECV_CMDID); + ath9k_hw_phy_disable(ah); + ath9k_hw_disable(ah); + ath9k_hw_configpcipowersave(ah, 1, 1); + ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); + + cancel_delayed_work_sync(&priv->ath9k_ani_work); + cancel_delayed_work_sync(&priv->ath9k_aggr_work); + cancel_delayed_work_sync(&priv->ath9k_led_blink_work); + ath9k_led_stop_brightness(priv); + skb_queue_purge(&priv->tx_queue); + + /* Remove monitor interface here */ + if (ah->opmode == NL80211_IFTYPE_MONITOR) { + if (ath9k_htc_remove_monitor_interface(priv)) + ath_print(common, ATH_DBG_FATAL, + "Unable to remove monitor interface\n"); + else + ath_print(common, ATH_DBG_CONFIG, + "Monitor interface removed\n"); + } + + priv->op_flags |= OP_INVALID; + mutex_unlock(&priv->mutex); + + ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); +} + +static int ath9k_htc_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath9k_htc_vif *avp = (void *)vif->drv_priv; + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_target_vif hvif; + int ret = 0; + u8 cmd_rsp; + + mutex_lock(&priv->mutex); + + /* Only one interface for now */ + if (priv->nvifs > 0) { + ret = -ENOBUFS; + goto out; + } + + memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); + memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + hvif.opmode = cpu_to_be32(HTC_M_STA); + break; + case NL80211_IFTYPE_ADHOC: + hvif.opmode = cpu_to_be32(HTC_M_IBSS); + break; + default: + ath_print(common, ATH_DBG_FATAL, + "Interface type %d not yet supported\n", vif->type); + ret = -EOPNOTSUPP; + goto out; + } + + ath_print(common, ATH_DBG_CONFIG, + "Attach a VIF of type: %d\n", vif->type); + + priv->ah->opmode = vif->type; + + /* Index starts from zero on the target */ + avp->index = hvif.index = priv->nvifs; + hvif.rtsthreshold = cpu_to_be16(2304); + WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); + if (ret) + goto out; + + priv->nvifs++; + + /* + * We need a node in target to tx mgmt frames + * before association. + */ + ret = ath9k_htc_add_station(priv, vif, NULL); + if (ret) + goto out; + + ret = ath9k_htc_update_cap_target(priv); + if (ret) + ath_print(common, ATH_DBG_CONFIG, "Failed to update" + " capability in target \n"); + + priv->vif = vif; +out: + mutex_unlock(&priv->mutex); + return ret; +} + +static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_vif *avp = (void *)vif->drv_priv; + struct ath9k_htc_target_vif hvif; + int ret = 0; + u8 cmd_rsp; + + ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); + + mutex_lock(&priv->mutex); + + memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); + memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); + hvif.index = avp->index; + WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); + priv->nvifs--; + + ath9k_htc_remove_station(priv, vif, NULL); + + if (vif->type == NL80211_IFTYPE_ADHOC) { + spin_lock_bh(&priv->beacon_lock); + if (priv->beacon) + dev_kfree_skb_any(priv->beacon); + priv->beacon = NULL; + spin_unlock_bh(&priv->beacon_lock); + } + + priv->vif = NULL; + + mutex_unlock(&priv->mutex); +} + +static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ieee80211_conf *conf = &hw->conf; + + mutex_lock(&priv->mutex); + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + struct ieee80211_channel *curchan = hw->conf.channel; + int pos = curchan->hw_value; + bool is_cw40 = false; + + ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", + curchan->center_freq); + + if (check_rc_update(hw, &is_cw40)) + ath9k_htc_rc_update(priv, is_cw40); + + ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]); + + if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { + ath_print(common, ATH_DBG_FATAL, + "Unable to set channel\n"); + mutex_unlock(&priv->mutex); + return -EINVAL; + } + + } + + if (changed & IEEE80211_CONF_CHANGE_MONITOR) { + if (conf->flags & IEEE80211_CONF_MONITOR) { + if (ath9k_htc_add_monitor_interface(priv)) + ath_print(common, ATH_DBG_FATAL, + "Failed to set monitor mode\n"); + else + ath_print(common, ATH_DBG_CONFIG, + "HW opmode set to Monitor mode\n"); + } + } + + mutex_unlock(&priv->mutex); + + return 0; +} + +#define SUPPORTED_FILTERS \ + (FIF_PROMISC_IN_BSS | \ + FIF_ALLMULTI | \ + FIF_CONTROL | \ + FIF_PSPOLL | \ + FIF_OTHER_BSS | \ + FIF_BCN_PRBRESP_PROMISC | \ + FIF_FCSFAIL) + +static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ + struct ath9k_htc_priv *priv = hw->priv; + u32 rfilt; + + mutex_lock(&priv->mutex); + + changed_flags &= SUPPORTED_FILTERS; + *total_flags &= SUPPORTED_FILTERS; + + priv->rxfilter = *total_flags; + rfilt = ath9k_cmn_calcrxfilter(hw, priv->ah, priv->rxfilter); + ath9k_hw_setrxfilter(priv->ah, rfilt); + + ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG, + "Set HW RX filter: 0x%x\n", rfilt); + + mutex_unlock(&priv->mutex); +} + +static void ath9k_htc_sta_notify(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) +{ + struct ath9k_htc_priv *priv = hw->priv; + int ret; + + switch (cmd) { + case STA_NOTIFY_ADD: + ret = ath9k_htc_add_station(priv, vif, sta); + if (!ret) + ath9k_htc_init_rate(priv, vif, sta); + break; + case STA_NOTIFY_REMOVE: + ath9k_htc_remove_station(priv, vif, sta); + break; + default: + break; + } +} + +static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_tx_queue_info qi; + int ret = 0, qnum; + + if (queue >= WME_NUM_AC) + return 0; + + mutex_lock(&priv->mutex); + + memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); + + qi.tqi_aifs = params->aifs; + qi.tqi_cwmin = params->cw_min; + qi.tqi_cwmax = params->cw_max; + qi.tqi_burstTime = params->txop; + + qnum = get_hw_qnum(queue, priv->hwq_map); + + ath_print(common, ATH_DBG_CONFIG, + "Configure tx [queue/hwq] [%d/%d], " + "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", + queue, qnum, params->aifs, params->cw_min, + params->cw_max, params->txop); + + ret = ath_txq_update(priv, qnum, &qi); + if (ret) + ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); + + mutex_unlock(&priv->mutex); + + return ret; +} + +static int ath9k_htc_set_key(struct ieee80211_hw *hw, + enum set_key_cmd cmd, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath_common *common = ath9k_hw_common(priv->ah); + int ret = 0; + + if (modparam_nohwcrypt) + return -ENOSPC; + + mutex_lock(&priv->mutex); + ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); + + switch (cmd) { + case SET_KEY: + ret = ath9k_cmn_key_config(common, vif, sta, key); + if (ret >= 0) { + key->hw_key_idx = ret; + /* push IV and Michael MIC generation to stack */ + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + if (key->alg == ALG_TKIP) + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + if (priv->ah->sw_mgmt_crypto && key->alg == ALG_CCMP) + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; + ret = 0; + } + break; + case DISABLE_KEY: + ath9k_cmn_key_delete(common, key); + break; + default: + ret = -EINVAL; + } + + mutex_unlock(&priv->mutex); + + return ret; +} + +static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changed) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath_hw *ah = priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + + mutex_lock(&priv->mutex); + + if (changed & BSS_CHANGED_ASSOC) { + common->curaid = bss_conf->assoc ? + bss_conf->aid : 0; + ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", + bss_conf->assoc); + + if (bss_conf->assoc) { + priv->op_flags |= OP_ASSOCIATED; + ath_start_ani(priv); + } else { + priv->op_flags &= ~OP_ASSOCIATED; + cancel_delayed_work_sync(&priv->ath9k_ani_work); + } + } + + if (changed & BSS_CHANGED_BSSID) { + /* Set BSSID */ + memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); + ath9k_hw_write_associd(ah); + + ath_print(common, ATH_DBG_CONFIG, + "BSSID: %pM aid: 0x%x\n", + common->curbssid, common->curaid); + } + + if ((changed & BSS_CHANGED_BEACON_INT) || + (changed & BSS_CHANGED_BEACON) || + ((changed & BSS_CHANGED_BEACON_ENABLED) && + bss_conf->enable_beacon)) { + priv->op_flags |= OP_ENABLE_BEACON; + ath9k_htc_beacon_config(priv, vif, bss_conf); + } + + if (changed & BSS_CHANGED_BEACON) + ath9k_htc_beacon_update(priv, vif); + + if ((changed & BSS_CHANGED_BEACON_ENABLED) && + !bss_conf->enable_beacon) { + priv->op_flags &= ~OP_ENABLE_BEACON; + ath9k_htc_beacon_config(priv, vif, bss_conf); + } + + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", + bss_conf->use_short_preamble); + if (bss_conf->use_short_preamble) + priv->op_flags |= OP_PREAMBLE_SHORT; + else + priv->op_flags &= ~OP_PREAMBLE_SHORT; + } + + if (changed & BSS_CHANGED_ERP_CTS_PROT) { + ath_print(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", + bss_conf->use_cts_prot); + if (bss_conf->use_cts_prot && + hw->conf.channel->band != IEEE80211_BAND_5GHZ) + priv->op_flags |= OP_PROTECT_ENABLE; + else + priv->op_flags &= ~OP_PROTECT_ENABLE; + } + + if (changed & BSS_CHANGED_ERP_SLOT) { + if (bss_conf->use_short_slot) + ah->slottime = 9; + else + ah->slottime = 20; + + ath9k_hw_init_global_settings(ah); + } + + mutex_unlock(&priv->mutex); +} + +static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw) +{ + struct ath9k_htc_priv *priv = hw->priv; + u64 tsf; + + mutex_lock(&priv->mutex); + tsf = ath9k_hw_gettsf64(priv->ah); + mutex_unlock(&priv->mutex); + + return tsf; +} + +static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf) +{ + struct ath9k_htc_priv *priv = hw->priv; + + mutex_lock(&priv->mutex); + ath9k_hw_settsf64(priv->ah, tsf); + mutex_unlock(&priv->mutex); +} + +static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw) +{ + struct ath9k_htc_priv *priv = hw->priv; + + mutex_lock(&priv->mutex); + ath9k_hw_reset_tsf(priv->ah); + mutex_unlock(&priv->mutex); +} + +static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, + u16 tid, u16 *ssn) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath9k_htc_aggr_work *work = &priv->aggr_work; + struct ath9k_htc_sta *ista; + + switch (action) { + case IEEE80211_AMPDU_RX_START: + break; + case IEEE80211_AMPDU_RX_STOP: + break; + case IEEE80211_AMPDU_TX_START: + case IEEE80211_AMPDU_TX_STOP: + if (!(priv->op_flags & OP_TXAGGR)) + return -ENOTSUPP; + memcpy(work->sta_addr, sta->addr, ETH_ALEN); + work->hw = hw; + work->vif = vif; + work->action = action; + work->tid = tid; + ieee80211_queue_delayed_work(hw, &priv->ath9k_aggr_work, 0); + break; + case IEEE80211_AMPDU_TX_OPERATIONAL: + ista = (struct ath9k_htc_sta *) sta->drv_priv; + ista->tid_state[tid] = AGGR_OPERATIONAL; + break; + default: + ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, + "Unknown AMPDU action\n"); + } + + return 0; +} + +static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) +{ + struct ath9k_htc_priv *priv = hw->priv; + + mutex_lock(&priv->mutex); + spin_lock_bh(&priv->beacon_lock); + priv->op_flags |= OP_SCANNING; + spin_unlock_bh(&priv->beacon_lock); + cancel_delayed_work_sync(&priv->ath9k_ani_work); + mutex_unlock(&priv->mutex); +} + +static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) +{ + struct ath9k_htc_priv *priv = hw->priv; + + mutex_lock(&priv->mutex); + spin_lock_bh(&priv->beacon_lock); + priv->op_flags &= ~OP_SCANNING; + spin_unlock_bh(&priv->beacon_lock); + priv->op_flags |= OP_FULL_RESET; + ath_start_ani(priv); + mutex_unlock(&priv->mutex); +} + +static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value) +{ + return 0; +} + +static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw, + u8 coverage_class) +{ + struct ath9k_htc_priv *priv = hw->priv; + + mutex_lock(&priv->mutex); + priv->ah->coverage_class = coverage_class; + ath9k_hw_init_global_settings(priv->ah); + mutex_unlock(&priv->mutex); +} + +struct ieee80211_ops ath9k_htc_ops = { + .tx = ath9k_htc_tx, + .start = ath9k_htc_start, + .stop = ath9k_htc_stop, + .add_interface = ath9k_htc_add_interface, + .remove_interface = ath9k_htc_remove_interface, + .config = ath9k_htc_config, + .configure_filter = ath9k_htc_configure_filter, + .sta_notify = ath9k_htc_sta_notify, + .conf_tx = ath9k_htc_conf_tx, + .bss_info_changed = ath9k_htc_bss_info_changed, + .set_key = ath9k_htc_set_key, + .get_tsf = ath9k_htc_get_tsf, + .set_tsf = ath9k_htc_set_tsf, + .reset_tsf = ath9k_htc_reset_tsf, + .ampdu_action = ath9k_htc_ampdu_action, + .sw_scan_start = ath9k_htc_sw_scan_start, + .sw_scan_complete = ath9k_htc_sw_scan_complete, + .set_rts_threshold = ath9k_htc_set_rts_threshold, + .rfkill_poll = ath9k_htc_rfkill_poll_state, + .set_coverage_class = ath9k_htc_set_coverage_class, +}; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c new file mode 100644 index 000000000000..dba22d3f87c3 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -0,0 +1,604 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "htc.h" + +/******/ +/* TX */ +/******/ + +int get_hw_qnum(u16 queue, int *hwq_map) +{ + switch (queue) { + case 0: + return hwq_map[ATH9K_WME_AC_VO]; + case 1: + return hwq_map[ATH9K_WME_AC_VI]; + case 2: + return hwq_map[ATH9K_WME_AC_BE]; + case 3: + return hwq_map[ATH9K_WME_AC_BK]; + default: + return hwq_map[ATH9K_WME_AC_BE]; + } +} + +int ath_txq_update(struct ath9k_htc_priv *priv, int qnum, + struct ath9k_tx_queue_info *qinfo) +{ + struct ath_hw *ah = priv->ah; + int error = 0; + struct ath9k_tx_queue_info qi; + + ath9k_hw_get_txq_props(ah, qnum, &qi); + + qi.tqi_aifs = qinfo->tqi_aifs; + qi.tqi_cwmin = qinfo->tqi_cwmin / 2; /* XXX */ + qi.tqi_cwmax = qinfo->tqi_cwmax; + qi.tqi_burstTime = qinfo->tqi_burstTime; + qi.tqi_readyTime = qinfo->tqi_readyTime; + + if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { + ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, + "Unable to update hardware queue %u!\n", qnum); + error = -EIO; + } else { + ath9k_hw_resettxqueue(ah, qnum); + } + + return error; +} + +int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *sta = tx_info->control.sta; + struct ath9k_htc_sta *ista; + struct ath9k_htc_vif *avp; + struct ath9k_htc_tx_ctl tx_ctl; + enum htc_endpoint_id epid; + u16 qnum, hw_qnum; + __le16 fc; + u8 *tx_fhdr; + u8 sta_idx; + + hdr = (struct ieee80211_hdr *) skb->data; + fc = hdr->frame_control; + + avp = (struct ath9k_htc_vif *) tx_info->control.vif->drv_priv; + if (sta) { + ista = (struct ath9k_htc_sta *) sta->drv_priv; + sta_idx = ista->index; + } else { + sta_idx = 0; + } + + memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); + + if (ieee80211_is_data(fc)) { + struct tx_frame_hdr tx_hdr; + u8 *qc; + + memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); + + tx_hdr.node_idx = sta_idx; + tx_hdr.vif_idx = avp->index; + + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { + tx_ctl.type = ATH9K_HTC_AMPDU; + tx_hdr.data_type = ATH9K_HTC_AMPDU; + } else { + tx_ctl.type = ATH9K_HTC_NORMAL; + tx_hdr.data_type = ATH9K_HTC_NORMAL; + } + + if (ieee80211_is_data(fc)) { + qc = ieee80211_get_qos_ctl(hdr); + tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + } + + /* Check for RTS protection */ + if (priv->hw->wiphy->rts_threshold != (u32) -1) + if (skb->len > priv->hw->wiphy->rts_threshold) + tx_hdr.flags |= ATH9K_HTC_TX_RTSCTS; + + /* CTS-to-self */ + if (!(tx_hdr.flags & ATH9K_HTC_TX_RTSCTS) && + (priv->op_flags & OP_PROTECT_ENABLE)) + tx_hdr.flags |= ATH9K_HTC_TX_CTSONLY; + + tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); + if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) + tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; + else + tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; + + tx_fhdr = skb_push(skb, sizeof(tx_hdr)); + memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); + + qnum = skb_get_queue_mapping(skb); + hw_qnum = get_hw_qnum(qnum, priv->hwq_map); + + switch (hw_qnum) { + case 0: + epid = priv->data_be_ep; + break; + case 2: + epid = priv->data_vi_ep; + break; + case 3: + epid = priv->data_vo_ep; + break; + case 1: + default: + epid = priv->data_bk_ep; + break; + } + } else { + struct tx_mgmt_hdr mgmt_hdr; + + memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); + + tx_ctl.type = ATH9K_HTC_NORMAL; + + mgmt_hdr.node_idx = sta_idx; + mgmt_hdr.vif_idx = avp->index; + mgmt_hdr.tidno = 0; + mgmt_hdr.flags = 0; + + mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); + if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) + mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; + else + mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; + + tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); + memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); + epid = priv->mgmt_ep; + } + + return htc_send(priv->htc, skb, epid, &tx_ctl); +} + +void ath9k_tx_tasklet(unsigned long data) +{ + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; + struct ieee80211_sta *sta; + struct ieee80211_hdr *hdr; + struct ieee80211_tx_info *tx_info; + struct sk_buff *skb = NULL; + __le16 fc; + + while ((skb = skb_dequeue(&priv->tx_queue)) != NULL) { + + hdr = (struct ieee80211_hdr *) skb->data; + fc = hdr->frame_control; + tx_info = IEEE80211_SKB_CB(skb); + sta = tx_info->control.sta; + + rcu_read_lock(); + + if (sta && conf_is_ht(&priv->hw->conf) && + (priv->op_flags & OP_TXAGGR) + && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { + if (ieee80211_is_data_qos(fc)) { + u8 *qc, tid; + struct ath9k_htc_sta *ista; + + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & 0xf; + ista = (struct ath9k_htc_sta *)sta->drv_priv; + + if ((tid < ATH9K_HTC_MAX_TID) && + ista->tid_state[tid] == AGGR_STOP) { + ieee80211_start_tx_ba_session(sta, tid); + ista->tid_state[tid] = AGGR_PROGRESS; + } + } + } + + rcu_read_unlock(); + + memset(&tx_info->status, 0, sizeof(tx_info->status)); + ieee80211_tx_status(priv->hw, skb); + } +} + +void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, + enum htc_endpoint_id ep_id, bool txok) +{ + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; + struct ieee80211_tx_info *tx_info; + + if (!skb) + return; + + if (ep_id == priv->mgmt_ep) + skb_pull(skb, sizeof(struct tx_mgmt_hdr)); + else + /* TODO: Check for cab/uapsd/data */ + skb_pull(skb, sizeof(struct tx_frame_hdr)); + + tx_info = IEEE80211_SKB_CB(skb); + + if (txok) + tx_info->flags |= IEEE80211_TX_STAT_ACK; + + skb_queue_tail(&priv->tx_queue, skb); + tasklet_schedule(&priv->tx_tasklet); +} + +int ath9k_tx_init(struct ath9k_htc_priv *priv) +{ + skb_queue_head_init(&priv->tx_queue); + return 0; +} + +void ath9k_tx_cleanup(struct ath9k_htc_priv *priv) +{ + +} + +bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, + enum ath9k_tx_queue_subtype subtype) +{ + struct ath_hw *ah = priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_tx_queue_info qi; + int qnum; + + memset(&qi, 0, sizeof(qi)); + + qi.tqi_subtype = subtype; + qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; + qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; + qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; + qi.tqi_physCompBuf = 0; + qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | TXQ_FLAG_TXDESCINT_ENABLE; + + qnum = ath9k_hw_setuptxqueue(priv->ah, ATH9K_TX_QUEUE_DATA, &qi); + if (qnum == -1) + return false; + + if (qnum >= ARRAY_SIZE(priv->hwq_map)) { + ath_print(common, ATH_DBG_FATAL, + "qnum %u out of range, max %u!\n", + qnum, (unsigned int)ARRAY_SIZE(priv->hwq_map)); + ath9k_hw_releasetxqueue(ah, qnum); + return false; + } + + priv->hwq_map[subtype] = qnum; + return true; +} + +/******/ +/* RX */ +/******/ + +void ath9k_host_rx_init(struct ath9k_htc_priv *priv) +{ + ath9k_hw_rxena(priv->ah); + ath9k_cmn_opmode_init(priv->hw, priv->ah, priv->rxfilter); + ath9k_hw_startpcureceive(priv->ah); + priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER; +} + +static void ath9k_process_rate(struct ieee80211_hw *hw, + struct ieee80211_rx_status *rxs, + u8 rx_rate, u8 rs_flags) +{ + struct ieee80211_supported_band *sband; + enum ieee80211_band band; + unsigned int i = 0; + + if (rx_rate & 0x80) { + /* HT rate */ + rxs->flag |= RX_FLAG_HT; + if (rs_flags & ATH9K_RX_2040) + rxs->flag |= RX_FLAG_40MHZ; + if (rs_flags & ATH9K_RX_GI) + rxs->flag |= RX_FLAG_SHORT_GI; + rxs->rate_idx = rx_rate & 0x7f; + return; + } + + band = hw->conf.channel->band; + sband = hw->wiphy->bands[band]; + + for (i = 0; i < sband->n_bitrates; i++) { + if (sband->bitrates[i].hw_value == rx_rate) { + rxs->rate_idx = i; + return; + } + if (sband->bitrates[i].hw_value_short == rx_rate) { + rxs->rate_idx = i; + rxs->flag |= RX_FLAG_SHORTPRE; + return; + } + } + +} + +static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, + struct ath9k_htc_rxbuf *rxbuf, + struct ieee80211_rx_status *rx_status) + +{ + struct ieee80211_hdr *hdr; + struct ieee80211_hw *hw = priv->hw; + struct sk_buff *skb = rxbuf->skb; + struct ath_common *common = ath9k_hw_common(priv->ah); + int hdrlen, padpos, padsize; + int last_rssi = ATH_RSSI_DUMMY_MARKER; + __le16 fc; + + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; + hdrlen = ieee80211_get_hdrlen_from_skb(skb); + + padpos = ath9k_cmn_padpos(fc); + + padsize = padpos & 3; + if (padsize && skb->len >= padpos+padsize) { + memmove(skb->data + padsize, skb->data, padpos); + skb_pull(skb, padsize); + } + + memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); + + if (rxbuf->rxstatus.rs_status != 0) { + if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_CRC) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_PHY) + goto rx_next; + + if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT) { + /* FIXME */ + } else if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_MIC) { + if (ieee80211_is_ctl(fc)) + /* + * Sometimes, we get invalid + * MIC failures on valid control frames. + * Remove these mic errors. + */ + rxbuf->rxstatus.rs_status &= ~ATH9K_RXERR_MIC; + else + rx_status->flag |= RX_FLAG_MMIC_ERROR; + } + + /* + * Reject error frames with the exception of + * decryption and MIC failures. For monitor mode, + * we also ignore the CRC error. + */ + if (priv->ah->opmode == NL80211_IFTYPE_MONITOR) { + if (rxbuf->rxstatus.rs_status & + ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | + ATH9K_RXERR_CRC)) + goto rx_next; + } else { + if (rxbuf->rxstatus.rs_status & + ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { + goto rx_next; + } + } + } + + if (!(rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT)) { + u8 keyix; + keyix = rxbuf->rxstatus.rs_keyix; + if (keyix != ATH9K_RXKEYIX_INVALID) { + rx_status->flag |= RX_FLAG_DECRYPTED; + } else if (ieee80211_has_protected(fc) && + skb->len >= hdrlen + 4) { + keyix = skb->data[hdrlen + 3] >> 6; + if (test_bit(keyix, common->keymap)) + rx_status->flag |= RX_FLAG_DECRYPTED; + } + } + + ath9k_process_rate(hw, rx_status, rxbuf->rxstatus.rs_rate, + rxbuf->rxstatus.rs_flags); + + if (priv->op_flags & OP_ASSOCIATED) { + if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD && + !rxbuf->rxstatus.rs_moreaggr) + ATH_RSSI_LPF(priv->rx.last_rssi, + rxbuf->rxstatus.rs_rssi); + + last_rssi = priv->rx.last_rssi; + + if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) + rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi, + ATH_RSSI_EP_MULTIPLIER); + + if (rxbuf->rxstatus.rs_rssi < 0) + rxbuf->rxstatus.rs_rssi = 0; + + if (ieee80211_is_beacon(fc)) + priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi; + } + + rx_status->mactime = rxbuf->rxstatus.rs_tstamp; + rx_status->band = hw->conf.channel->band; + rx_status->freq = hw->conf.channel->center_freq; + rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR; + rx_status->antenna = rxbuf->rxstatus.rs_antenna; + rx_status->flag |= RX_FLAG_TSFT; + + return true; + +rx_next: + return false; +} + +/* + * FIXME: Handle FLUSH later on. + */ +void ath9k_rx_tasklet(unsigned long data) +{ + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; + struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; + struct ieee80211_rx_status rx_status; + struct sk_buff *skb; + unsigned long flags; + + + do { + spin_lock_irqsave(&priv->rx.rxbuflock, flags); + list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) { + if (tmp_buf->in_process) { + rxbuf = tmp_buf; + break; + } + } + + if (rxbuf == NULL) { + spin_unlock_irqrestore(&priv->rx.rxbuflock, flags); + break; + } + + if (!rxbuf->skb) + goto requeue; + + if (!ath9k_rx_prepare(priv, rxbuf, &rx_status)) { + dev_kfree_skb_any(rxbuf->skb); + goto requeue; + } + + memcpy(IEEE80211_SKB_RXCB(rxbuf->skb), &rx_status, + sizeof(struct ieee80211_rx_status)); + skb = rxbuf->skb; + spin_unlock_irqrestore(&priv->rx.rxbuflock, flags); + + ieee80211_rx(priv->hw, skb); + + spin_lock_irqsave(&priv->rx.rxbuflock, flags); +requeue: + rxbuf->in_process = false; + rxbuf->skb = NULL; + list_move_tail(&rxbuf->list, &priv->rx.rxbuf); + rxbuf = NULL; + spin_unlock_irqrestore(&priv->rx.rxbuflock, flags); + } while (1); + +} + +void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, + enum htc_endpoint_id ep_id) +{ + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)drv_priv; + struct ath_hw *ah = priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; + struct ath_htc_rx_status *rxstatus; + u32 len = 0; + + spin_lock(&priv->rx.rxbuflock); + list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) { + if (!tmp_buf->in_process) { + rxbuf = tmp_buf; + break; + } + } + spin_unlock(&priv->rx.rxbuflock); + + if (rxbuf == NULL) { + ath_print(common, ATH_DBG_ANY, + "No free RX buffer\n"); + goto err; + } + + len = skb->len; + if (len <= HTC_RX_FRAME_HEADER_SIZE) { + ath_print(common, ATH_DBG_FATAL, + "Corrupted RX frame, dropping\n"); + goto err; + } + + rxstatus = (struct ath_htc_rx_status *)skb->data; + + rxstatus->rs_tstamp = be64_to_cpu(rxstatus->rs_tstamp); + rxstatus->rs_datalen = be16_to_cpu(rxstatus->rs_datalen); + rxstatus->evm0 = be32_to_cpu(rxstatus->evm0); + rxstatus->evm1 = be32_to_cpu(rxstatus->evm1); + rxstatus->evm2 = be32_to_cpu(rxstatus->evm2); + + if (rxstatus->rs_datalen - (len - HTC_RX_FRAME_HEADER_SIZE) != 0) { + ath_print(common, ATH_DBG_FATAL, + "Corrupted RX data len, dropping " + "(epid: %d, dlen: %d, skblen: %d)\n", + ep_id, rxstatus->rs_datalen, len); + goto err; + } + + spin_lock(&priv->rx.rxbuflock); + memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); + skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); + skb->len = rxstatus->rs_datalen; + rxbuf->skb = skb; + rxbuf->in_process = true; + spin_unlock(&priv->rx.rxbuflock); + + tasklet_schedule(&priv->rx_tasklet); + return; +err: + dev_kfree_skb_any(skb); + return; +} + +/* FIXME: Locking for cleanup/init */ + +void ath9k_rx_cleanup(struct ath9k_htc_priv *priv) +{ + struct ath9k_htc_rxbuf *rxbuf, *tbuf; + + list_for_each_entry_safe(rxbuf, tbuf, &priv->rx.rxbuf, list) { + list_del(&rxbuf->list); + if (rxbuf->skb) + dev_kfree_skb_any(rxbuf->skb); + kfree(rxbuf); + } +} + +int ath9k_rx_init(struct ath9k_htc_priv *priv) +{ + struct ath_hw *ah = priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_rxbuf *rxbuf; + int i = 0; + + INIT_LIST_HEAD(&priv->rx.rxbuf); + spin_lock_init(&priv->rx.rxbuflock); + + for (i = 0; i < ATH9K_HTC_RXBUF; i++) { + rxbuf = kzalloc(sizeof(struct ath9k_htc_rxbuf), GFP_KERNEL); + if (rxbuf == NULL) { + ath_print(common, ATH_DBG_FATAL, + "Unable to allocate RX buffers\n"); + goto err; + } + list_add_tail(&rxbuf->list, &priv->rx.rxbuf); + } + + return 0; + +err: + ath9k_rx_cleanup(priv); + return -ENOMEM; +} diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c new file mode 100644 index 000000000000..9a48999d0979 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -0,0 +1,463 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "htc.h" + +static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, + u16 len, u8 flags, u8 epid, + struct ath9k_htc_tx_ctl *tx_ctl) +{ + struct htc_frame_hdr *hdr; + struct htc_endpoint *endpoint = &target->endpoint[epid]; + int status; + + hdr = (struct htc_frame_hdr *) + skb_push(skb, sizeof(struct htc_frame_hdr)); + hdr->endpoint_id = epid; + hdr->flags = flags; + hdr->payload_len = cpu_to_be16(len); + + status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb, + tx_ctl); + return status; +} + +static struct htc_endpoint *get_next_avail_ep(struct htc_endpoint *endpoint) +{ + enum htc_endpoint_id avail_epid; + + for (avail_epid = ENDPOINT_MAX; avail_epid > ENDPOINT0; avail_epid--) + if (endpoint[avail_epid].service_id == 0) + return &endpoint[avail_epid]; + return NULL; +} + +static u8 service_to_ulpipe(u16 service_id) +{ + switch (service_id) { + case WMI_CONTROL_SVC: + return 4; + case WMI_BEACON_SVC: + case WMI_CAB_SVC: + case WMI_UAPSD_SVC: + case WMI_MGMT_SVC: + case WMI_DATA_VO_SVC: + case WMI_DATA_VI_SVC: + case WMI_DATA_BE_SVC: + case WMI_DATA_BK_SVC: + return 1; + default: + return 0; + } +} + +static u8 service_to_dlpipe(u16 service_id) +{ + switch (service_id) { + case WMI_CONTROL_SVC: + return 3; + case WMI_BEACON_SVC: + case WMI_CAB_SVC: + case WMI_UAPSD_SVC: + case WMI_MGMT_SVC: + case WMI_DATA_VO_SVC: + case WMI_DATA_VI_SVC: + case WMI_DATA_BE_SVC: + case WMI_DATA_BK_SVC: + return 2; + default: + return 0; + } +} + +static void htc_process_target_rdy(struct htc_target *target, + void *buf) +{ + struct htc_endpoint *endpoint; + struct htc_ready_msg *htc_ready_msg = (struct htc_ready_msg *) buf; + + target->credits = be16_to_cpu(htc_ready_msg->credits); + target->credit_size = be16_to_cpu(htc_ready_msg->credit_size); + + endpoint = &target->endpoint[ENDPOINT0]; + endpoint->service_id = HTC_CTRL_RSVD_SVC; + endpoint->max_msglen = HTC_MAX_CONTROL_MESSAGE_LENGTH; + complete(&target->target_wait); +} + +static void htc_process_conn_rsp(struct htc_target *target, + struct htc_frame_hdr *htc_hdr) +{ + struct htc_conn_svc_rspmsg *svc_rspmsg; + struct htc_endpoint *endpoint, *tmp_endpoint = NULL; + u16 service_id; + u16 max_msglen; + enum htc_endpoint_id epid, tepid; + + svc_rspmsg = (struct htc_conn_svc_rspmsg *) + ((void *) htc_hdr + sizeof(struct htc_frame_hdr)); + + if (svc_rspmsg->status == HTC_SERVICE_SUCCESS) { + epid = svc_rspmsg->endpoint_id; + service_id = be16_to_cpu(svc_rspmsg->service_id); + max_msglen = be16_to_cpu(svc_rspmsg->max_msg_len); + endpoint = &target->endpoint[epid]; + + for (tepid = ENDPOINT_MAX; tepid > ENDPOINT0; tepid--) { + tmp_endpoint = &target->endpoint[tepid]; + if (tmp_endpoint->service_id == service_id) { + tmp_endpoint->service_id = 0; + break; + } + } + + if (!tmp_endpoint) + return; + + endpoint->service_id = service_id; + endpoint->max_txqdepth = tmp_endpoint->max_txqdepth; + endpoint->ep_callbacks = tmp_endpoint->ep_callbacks; + endpoint->ul_pipeid = tmp_endpoint->ul_pipeid; + endpoint->dl_pipeid = tmp_endpoint->dl_pipeid; + endpoint->max_msglen = max_msglen; + target->conn_rsp_epid = epid; + complete(&target->cmd_wait); + } else { + target->conn_rsp_epid = ENDPOINT_UNUSED; + } +} + +static int htc_config_pipe_credits(struct htc_target *target) +{ + struct sk_buff *skb; + struct htc_config_pipe_msg *cp_msg; + int ret, time_left; + + skb = dev_alloc_skb(50 + sizeof(struct htc_frame_hdr)); + if (!skb) { + dev_err(target->dev, "failed to allocate send buffer\n"); + return -ENOMEM; + } + skb_reserve(skb, sizeof(struct htc_frame_hdr)); + + cp_msg = (struct htc_config_pipe_msg *) + skb_put(skb, sizeof(struct htc_config_pipe_msg)); + + cp_msg->message_id = cpu_to_be16(HTC_MSG_CONFIG_PIPE_ID); + cp_msg->pipe_id = USB_WLAN_TX_PIPE; + cp_msg->credits = 28; + + target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS; + + ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); + if (ret) + goto err; + + time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); + if (!time_left) { + dev_err(target->dev, "HTC credit config timeout\n"); + return -ETIMEDOUT; + } + + return 0; +err: + dev_kfree_skb(skb); + return -EINVAL; +} + +static int htc_setup_complete(struct htc_target *target) +{ + struct sk_buff *skb; + struct htc_comp_msg *comp_msg; + int ret = 0, time_left; + + skb = dev_alloc_skb(50 + sizeof(struct htc_frame_hdr)); + if (!skb) { + dev_err(target->dev, "failed to allocate send buffer\n"); + return -ENOMEM; + } + skb_reserve(skb, sizeof(struct htc_frame_hdr)); + + comp_msg = (struct htc_comp_msg *) + skb_put(skb, sizeof(struct htc_comp_msg)); + comp_msg->msg_id = cpu_to_be16(HTC_MSG_SETUP_COMPLETE_ID); + + target->htc_flags |= HTC_OP_START_WAIT; + + ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); + if (ret) + goto err; + + time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); + if (!time_left) { + dev_err(target->dev, "HTC start timeout\n"); + return -ETIMEDOUT; + } + + return 0; + +err: + dev_kfree_skb(skb); + return -EINVAL; +} + +/* HTC APIs */ + +int htc_init(struct htc_target *target) +{ + int ret; + + ret = htc_config_pipe_credits(target); + if (ret) + return ret; + + return htc_setup_complete(target); +} + +int htc_connect_service(struct htc_target *target, + struct htc_service_connreq *service_connreq, + enum htc_endpoint_id *conn_rsp_epid) +{ + struct sk_buff *skb; + struct htc_endpoint *endpoint; + struct htc_conn_svc_msg *conn_msg; + int ret, time_left; + + /* Find an available endpoint */ + endpoint = get_next_avail_ep(target->endpoint); + if (!endpoint) { + dev_err(target->dev, "Endpoint is not available for" + "service %d\n", service_connreq->service_id); + return -EINVAL; + } + + endpoint->service_id = service_connreq->service_id; + endpoint->max_txqdepth = service_connreq->max_send_qdepth; + endpoint->ul_pipeid = service_to_ulpipe(service_connreq->service_id); + endpoint->dl_pipeid = service_to_dlpipe(service_connreq->service_id); + endpoint->ep_callbacks = service_connreq->ep_callbacks; + + skb = dev_alloc_skb(sizeof(struct htc_conn_svc_msg) + + sizeof(struct htc_frame_hdr)); + if (!skb) { + dev_err(target->dev, "Failed to allocate buf to send" + "service connect req\n"); + return -ENOMEM; + } + + skb_reserve(skb, sizeof(struct htc_frame_hdr)); + + conn_msg = (struct htc_conn_svc_msg *) + skb_put(skb, sizeof(struct htc_conn_svc_msg)); + conn_msg->service_id = cpu_to_be16(service_connreq->service_id); + conn_msg->msg_id = cpu_to_be16(HTC_MSG_CONNECT_SERVICE_ID); + conn_msg->con_flags = cpu_to_be16(service_connreq->con_flags); + conn_msg->dl_pipeid = endpoint->dl_pipeid; + conn_msg->ul_pipeid = endpoint->ul_pipeid; + + ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); + if (ret) + goto err; + + time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); + if (!time_left) { + dev_err(target->dev, "Service connection timeout for: %d\n", + service_connreq->service_id); + return -ETIMEDOUT; + } + + *conn_rsp_epid = target->conn_rsp_epid; + return 0; +err: + dev_kfree_skb(skb); + return ret; +} + +int htc_send(struct htc_target *target, struct sk_buff *skb, + enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl) +{ + return htc_issue_send(target, skb, skb->len, 0, epid, tx_ctl); +} + +void htc_stop(struct htc_target *target) +{ + enum htc_endpoint_id epid; + struct htc_endpoint *endpoint; + + for (epid = ENDPOINT0; epid <= ENDPOINT_MAX; epid++) { + endpoint = &target->endpoint[epid]; + if (endpoint->service_id != 0) + target->hif->stop(target->hif_dev, endpoint->ul_pipeid); + } +} + +void htc_start(struct htc_target *target) +{ + enum htc_endpoint_id epid; + struct htc_endpoint *endpoint; + + for (epid = ENDPOINT0; epid <= ENDPOINT_MAX; epid++) { + endpoint = &target->endpoint[epid]; + if (endpoint->service_id != 0) + target->hif->start(target->hif_dev, + endpoint->ul_pipeid); + } +} + +void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, + struct sk_buff *skb, bool txok) +{ + struct htc_endpoint *endpoint; + struct htc_frame_hdr *htc_hdr; + + if (htc_handle->htc_flags & HTC_OP_CONFIG_PIPE_CREDITS) { + complete(&htc_handle->cmd_wait); + htc_handle->htc_flags &= ~HTC_OP_CONFIG_PIPE_CREDITS; + } + + if (htc_handle->htc_flags & HTC_OP_START_WAIT) { + complete(&htc_handle->cmd_wait); + htc_handle->htc_flags &= ~HTC_OP_START_WAIT; + } + + if (skb) { + htc_hdr = (struct htc_frame_hdr *) skb->data; + endpoint = &htc_handle->endpoint[htc_hdr->endpoint_id]; + skb_pull(skb, sizeof(struct htc_frame_hdr)); + + if (endpoint->ep_callbacks.tx) { + endpoint->ep_callbacks.tx(htc_handle->drv_priv, skb, + htc_hdr->endpoint_id, txok); + } + } +} + +/* + * HTC Messages are handled directly here and the obtained SKB + * is freed. + * + * Sevice messages (Data, WMI) passed to the corresponding + * endpoint RX handlers, which have to free the SKB. + */ +void ath9k_htc_rx_msg(struct htc_target *htc_handle, + struct sk_buff *skb, u32 len, u8 pipe_id) +{ + struct htc_frame_hdr *htc_hdr; + enum htc_endpoint_id epid; + struct htc_endpoint *endpoint; + u16 *msg_id; + + if (!htc_handle || !skb) + return; + + htc_hdr = (struct htc_frame_hdr *) skb->data; + epid = htc_hdr->endpoint_id; + + if (epid >= ENDPOINT_MAX) { + dev_kfree_skb_any(skb); + return; + } + + if (epid == ENDPOINT0) { + + /* Handle trailer */ + if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) { + if (be32_to_cpu(*(u32 *) skb->data) == 0x00C60000) + /* Move past the Watchdog pattern */ + htc_hdr = (struct htc_frame_hdr *) skb->data + 4; + } + + /* Get the message ID */ + msg_id = (u16 *) ((void *) htc_hdr + + sizeof(struct htc_frame_hdr)); + + /* Now process HTC messages */ + switch (be16_to_cpu(*msg_id)) { + case HTC_MSG_READY_ID: + htc_process_target_rdy(htc_handle, htc_hdr); + break; + case HTC_MSG_CONNECT_SERVICE_RESPONSE_ID: + htc_process_conn_rsp(htc_handle, htc_hdr); + break; + default: + break; + } + + dev_kfree_skb_any(skb); + + } else { + if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) + skb_trim(skb, len - htc_hdr->control[0]); + + skb_pull(skb, sizeof(struct htc_frame_hdr)); + + endpoint = &htc_handle->endpoint[epid]; + if (endpoint->ep_callbacks.rx) + endpoint->ep_callbacks.rx(endpoint->ep_callbacks.priv, + skb, epid); + } +} + +struct htc_target *ath9k_htc_hw_alloc(void *hif_handle) +{ + struct htc_target *target; + + target = kzalloc(sizeof(struct htc_target), GFP_KERNEL); + if (!target) + printk(KERN_ERR "Unable to allocate memory for" + "target device\n"); + + return target; +} + +void ath9k_htc_hw_free(struct htc_target *htc) +{ + kfree(htc); +} + +int ath9k_htc_hw_init(struct ath9k_htc_hif *hif, struct htc_target *target, + void *hif_handle, struct device *dev, u16 devid, + enum ath9k_hif_transports transport) +{ + struct htc_endpoint *endpoint; + int err = 0; + + init_completion(&target->target_wait); + init_completion(&target->cmd_wait); + + target->hif = hif; + target->hif_dev = hif_handle; + target->dev = dev; + + /* Assign control endpoint pipe IDs */ + endpoint = &target->endpoint[ENDPOINT0]; + endpoint->ul_pipeid = hif->control_ul_pipe; + endpoint->dl_pipeid = hif->control_dl_pipe; + + err = ath9k_htc_probe_device(target, dev, devid); + if (err) { + printk(KERN_ERR "Failed to initialize the device\n"); + return -ENODEV; + } + + return 0; +} + +void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug) +{ + if (target) + ath9k_htc_disconnect_device(target, hot_unplug); +} diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h new file mode 100644 index 000000000000..cd7048ffd239 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HTC_HST_H +#define HTC_HST_H + +struct ath9k_htc_priv; +struct htc_target; +struct ath9k_htc_tx_ctl; + +enum ath9k_hif_transports { + ATH9K_HIF_USB, +}; + +struct ath9k_htc_hif { + struct list_head list; + const enum ath9k_hif_transports transport; + const char *name; + + u8 control_dl_pipe; + u8 control_ul_pipe; + + void (*start) (void *hif_handle, u8 pipe); + void (*stop) (void *hif_handle, u8 pipe); + int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf, + struct ath9k_htc_tx_ctl *tx_ctl); +}; + +enum htc_endpoint_id { + ENDPOINT_UNUSED = -1, + ENDPOINT0 = 0, + ENDPOINT1 = 1, + ENDPOINT2 = 2, + ENDPOINT3 = 3, + ENDPOINT4 = 4, + ENDPOINT5 = 5, + ENDPOINT6 = 6, + ENDPOINT7 = 7, + ENDPOINT8 = 8, + ENDPOINT_MAX = 22 +}; + +/* Htc frame hdr flags */ +#define HTC_FLAGS_RECV_TRAILER (1 << 1) + +struct htc_frame_hdr { + u8 endpoint_id; + u8 flags; + u16 payload_len; + u8 control[4]; +} __packed; + +struct htc_ready_msg { + u16 message_id; + u16 credits; + u16 credit_size; + u8 max_endpoints; + u8 pad; +} __packed; + +struct htc_config_pipe_msg { + u16 message_id; + u8 pipe_id; + u8 credits; +} __packed; + +struct htc_packet { + void *pktcontext; + u8 *buf; + u8 *buf_payload; + u32 buflen; + u32 payload_len; + + int endpoint; + int status; + + void *context; + u32 reserved; +}; + +struct htc_ep_callbacks { + void *priv; + void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok); + void (*rx) (void *, struct sk_buff *, enum htc_endpoint_id); +}; + +#define HTC_TX_QUEUE_SIZE 256 + +struct htc_txq { + struct sk_buff *buf[HTC_TX_QUEUE_SIZE]; + u32 txqdepth; + u16 txbuf_cnt; + u16 txq_head; + u16 txq_tail; +}; + +struct htc_endpoint { + u16 service_id; + + struct htc_ep_callbacks ep_callbacks; + struct htc_txq htc_txq; + u32 max_txqdepth; + int max_msglen; + + u8 ul_pipeid; + u8 dl_pipeid; +}; + +#define HTC_MAX_CONTROL_MESSAGE_LENGTH 255 +#define HTC_CONTROL_BUFFER_SIZE \ + (HTC_MAX_CONTROL_MESSAGE_LENGTH + sizeof(struct htc_frame_hdr)) + +#define NUM_CONTROL_BUFFERS 8 +#define HST_ENDPOINT_MAX 8 + +struct htc_control_buf { + struct htc_packet htc_pkt; + u8 buf[HTC_CONTROL_BUFFER_SIZE]; +}; + +#define HTC_OP_START_WAIT BIT(0) +#define HTC_OP_CONFIG_PIPE_CREDITS BIT(1) + +struct htc_target { + void *hif_dev; + struct ath9k_htc_priv *drv_priv; + struct device *dev; + struct ath9k_htc_hif *hif; + struct htc_endpoint endpoint[HST_ENDPOINT_MAX]; + struct completion target_wait; + struct completion cmd_wait; + struct list_head list; + enum htc_endpoint_id conn_rsp_epid; + u16 credits; + u16 credit_size; + u8 htc_flags; +}; + +enum htc_msg_id { + HTC_MSG_READY_ID = 1, + HTC_MSG_CONNECT_SERVICE_ID, + HTC_MSG_CONNECT_SERVICE_RESPONSE_ID, + HTC_MSG_SETUP_COMPLETE_ID, + HTC_MSG_CONFIG_PIPE_ID, + HTC_MSG_CONFIG_PIPE_RESPONSE_ID, +}; + +struct htc_service_connreq { + u16 service_id; + u16 con_flags; + u32 max_send_qdepth; + struct htc_ep_callbacks ep_callbacks; +}; + +/* Current service IDs */ + +enum htc_service_group_ids{ + RSVD_SERVICE_GROUP = 0, + WMI_SERVICE_GROUP = 1, + + HTC_SERVICE_GROUP_LAST = 255 +}; + +#define MAKE_SERVICE_ID(group, index) \ + (int)(((int)group << 8) | (int)(index)) + +/* NOTE: service ID of 0x0000 is reserved and should never be used */ +#define HTC_CTRL_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP, 1) +#define HTC_LOOPBACK_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP, 2) + +#define WMI_CONTROL_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 0) +#define WMI_BEACON_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 1) +#define WMI_CAB_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 2) +#define WMI_UAPSD_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 3) +#define WMI_MGMT_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 4) +#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 5) +#define WMI_DATA_VI_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 6) +#define WMI_DATA_BE_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 7) +#define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 8) + +struct htc_conn_svc_msg { + u16 msg_id; + u16 service_id; + u16 con_flags; + u8 dl_pipeid; + u8 ul_pipeid; + u8 svc_meta_len; + u8 pad; +} __packed; + +/* connect response status codes */ +#define HTC_SERVICE_SUCCESS 0 +#define HTC_SERVICE_NOT_FOUND 1 +#define HTC_SERVICE_FAILED 2 +#define HTC_SERVICE_NO_RESOURCES 3 +#define HTC_SERVICE_NO_MORE_EP 4 + +struct htc_conn_svc_rspmsg { + u16 msg_id; + u16 service_id; + u8 status; + u8 endpoint_id; + u16 max_msg_len; + u8 svc_meta_len; + u8 pad; +} __packed; + +struct htc_comp_msg { + u16 msg_id; +} __packed; + +int htc_init(struct htc_target *target); +int htc_connect_service(struct htc_target *target, + struct htc_service_connreq *service_connreq, + enum htc_endpoint_id *conn_rsp_eid); +int htc_send(struct htc_target *target, struct sk_buff *skb, + enum htc_endpoint_id eid, struct ath9k_htc_tx_ctl *tx_ctl); +void htc_stop(struct htc_target *target); +void htc_start(struct htc_target *target); + +void ath9k_htc_rx_msg(struct htc_target *htc_handle, + struct sk_buff *skb, u32 len, u8 pipe_id); +void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, + struct sk_buff *skb, bool txok); + +struct htc_target *ath9k_htc_hw_alloc(void *hif_handle); +void ath9k_htc_hw_free(struct htc_target *htc); +int ath9k_htc_hw_init(struct ath9k_htc_hif *hif, struct htc_target *target, + void *hif_handle, struct device *dev, u16 devid, + enum ath9k_hif_transports transport); +void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug); + +#endif /* HTC_HST_H */ diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 29851e6376a9..a5e543bd2271 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -150,6 +150,32 @@ struct ath_rx_status { u32 evm2; }; +struct ath_htc_rx_status { + u64 rs_tstamp; + u16 rs_datalen; + u8 rs_status; + u8 rs_phyerr; + int8_t rs_rssi; + int8_t rs_rssi_ctl0; + int8_t rs_rssi_ctl1; + int8_t rs_rssi_ctl2; + int8_t rs_rssi_ext0; + int8_t rs_rssi_ext1; + int8_t rs_rssi_ext2; + u8 rs_keyix; + u8 rs_rate; + u8 rs_antenna; + u8 rs_more; + u8 rs_isaggr; + u8 rs_moreaggr; + u8 rs_num_delims; + u8 rs_flags; + u8 rs_dummy; + u32 evm0; + u32 evm1; + u32 evm2; +}; + #define ATH9K_RXERR_CRC 0x01 #define ATH9K_RXERR_PHY 0x02 #define ATH9K_RXERR_FIFO 0x04 diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c new file mode 100644 index 000000000000..818dea0164ec --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "htc.h" + +static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) +{ + switch (wmi_cmd) { + case WMI_ECHO_CMDID: + return "WMI_ECHO_CMDID"; + case WMI_ACCESS_MEMORY_CMDID: + return "WMI_ACCESS_MEMORY_CMDID"; + case WMI_DISABLE_INTR_CMDID: + return "WMI_DISABLE_INTR_CMDID"; + case WMI_ENABLE_INTR_CMDID: + return "WMI_ENABLE_INTR_CMDID"; + case WMI_RX_LINK_CMDID: + return "WMI_RX_LINK_CMDID"; + case WMI_ATH_INIT_CMDID: + return "WMI_ATH_INIT_CMDID"; + case WMI_ABORT_TXQ_CMDID: + return "WMI_ABORT_TXQ_CMDID"; + case WMI_STOP_TX_DMA_CMDID: + return "WMI_STOP_TX_DMA_CMDID"; + case WMI_STOP_DMA_RECV_CMDID: + return "WMI_STOP_DMA_RECV_CMDID"; + case WMI_ABORT_TX_DMA_CMDID: + return "WMI_ABORT_TX_DMA_CMDID"; + case WMI_DRAIN_TXQ_CMDID: + return "WMI_DRAIN_TXQ_CMDID"; + case WMI_DRAIN_TXQ_ALL_CMDID: + return "WMI_DRAIN_TXQ_ALL_CMDID"; + case WMI_START_RECV_CMDID: + return "WMI_START_RECV_CMDID"; + case WMI_STOP_RECV_CMDID: + return "WMI_STOP_RECV_CMDID"; + case WMI_FLUSH_RECV_CMDID: + return "WMI_FLUSH_RECV_CMDID"; + case WMI_SET_MODE_CMDID: + return "WMI_SET_MODE_CMDID"; + case WMI_RESET_CMDID: + return "WMI_RESET_CMDID"; + case WMI_NODE_CREATE_CMDID: + return "WMI_NODE_CREATE_CMDID"; + case WMI_NODE_REMOVE_CMDID: + return "WMI_NODE_REMOVE_CMDID"; + case WMI_VAP_REMOVE_CMDID: + return "WMI_VAP_REMOVE_CMDID"; + case WMI_VAP_CREATE_CMDID: + return "WMI_VAP_CREATE_CMDID"; + case WMI_BEACON_UPDATE_CMDID: + return "WMI_BEACON_UPDATE_CMDID"; + case WMI_REG_READ_CMDID: + return "WMI_REG_READ_CMDID"; + case WMI_REG_WRITE_CMDID: + return "WMI_REG_WRITE_CMDID"; + case WMI_RC_STATE_CHANGE_CMDID: + return "WMI_RC_STATE_CHANGE_CMDID"; + case WMI_RC_RATE_UPDATE_CMDID: + return "WMI_RC_RATE_UPDATE_CMDID"; + case WMI_DEBUG_INFO_CMDID: + return "WMI_DEBUG_INFO_CMDID"; + case WMI_HOST_ATTACH: + return "WMI_HOST_ATTACH"; + case WMI_TARGET_IC_UPDATE_CMDID: + return "WMI_TARGET_IC_UPDATE_CMDID"; + case WMI_TGT_STATS_CMDID: + return "WMI_TGT_STATS_CMDID"; + case WMI_TX_AGGR_ENABLE_CMDID: + return "WMI_TX_AGGR_ENABLE_CMDID"; + case WMI_TGT_DETACH_CMDID: + return "WMI_TGT_DETACH_CMDID"; + case WMI_TGT_TXQ_ENABLE_CMDID: + return "WMI_TGT_TXQ_ENABLE_CMDID"; + } + + return "Bogus"; +} + +struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv) +{ + struct wmi *wmi; + + wmi = kzalloc(sizeof(struct wmi), GFP_KERNEL); + if (!wmi) + return NULL; + + wmi->drv_priv = priv; + wmi->stopped = false; + mutex_init(&wmi->op_mutex); + init_completion(&wmi->cmd_wait); + + return wmi; +} + +void ath9k_deinit_wmi(struct ath9k_htc_priv *priv) +{ + struct wmi *wmi = priv->wmi; + + mutex_lock(&wmi->op_mutex); + wmi->stopped = true; + mutex_unlock(&wmi->op_mutex); + + kfree(priv->wmi); +} + +void ath9k_wmi_tasklet(unsigned long data) +{ + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; + struct ath_common *common = ath9k_hw_common(priv->ah); + struct wmi_cmd_hdr *hdr; + struct wmi_swba *swba_hdr; + enum wmi_event_id event; + struct sk_buff *skb; + void *wmi_event; + unsigned long flags; +#ifdef CONFIG_ATH9K_HTC_DEBUGFS + u32 txrate; +#endif + + spin_lock_irqsave(&priv->wmi->wmi_lock, flags); + skb = priv->wmi->wmi_skb; + spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); + + hdr = (struct wmi_cmd_hdr *) skb->data; + event = be16_to_cpu(hdr->command_id); + wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); + + ath_print(common, ATH_DBG_WMI, + "WMI Event: 0x%x\n", event); + + switch (event) { + case WMI_TGT_RDY_EVENTID: + break; + case WMI_SWBA_EVENTID: + swba_hdr = (struct wmi_swba *) wmi_event; + ath9k_htc_swba(priv, swba_hdr->beacon_pending); + break; + case WMI_FATAL_EVENTID: + break; + case WMI_TXTO_EVENTID: + break; + case WMI_BMISS_EVENTID: + break; + case WMI_WLAN_TXCOMP_EVENTID: + break; + case WMI_DELBA_EVENTID: + break; + case WMI_TXRATE_EVENTID: +#ifdef CONFIG_ATH9K_HTC_DEBUGFS + txrate = ((struct wmi_event_txrate *)wmi_event)->txrate; + priv->debug.txrate = be32_to_cpu(txrate); +#endif + break; + default: + break; + } + + dev_kfree_skb_any(skb); +} + +static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) +{ + skb_pull(skb, sizeof(struct wmi_cmd_hdr)); + + if (wmi->cmd_rsp_buf != NULL && wmi->cmd_rsp_len != 0) + memcpy(wmi->cmd_rsp_buf, skb->data, wmi->cmd_rsp_len); + + complete(&wmi->cmd_wait); +} + +static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, + enum htc_endpoint_id epid) +{ + struct wmi *wmi = (struct wmi *) priv; + struct wmi_cmd_hdr *hdr; + u16 cmd_id; + + if (unlikely(wmi->stopped)) + goto free_skb; + + hdr = (struct wmi_cmd_hdr *) skb->data; + cmd_id = be16_to_cpu(hdr->command_id); + + if (cmd_id & 0x1000) { + spin_lock(&wmi->wmi_lock); + wmi->wmi_skb = skb; + spin_unlock(&wmi->wmi_lock); + tasklet_schedule(&wmi->drv_priv->wmi_tasklet); + return; + } + + /* WMI command response */ + ath9k_wmi_rsp_callback(wmi, skb); + +free_skb: + dev_kfree_skb_any(skb); +} + +static void ath9k_wmi_ctrl_tx(void *priv, struct sk_buff *skb, + enum htc_endpoint_id epid, bool txok) +{ + dev_kfree_skb_any(skb); +} + +int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi, + enum htc_endpoint_id *wmi_ctrl_epid) +{ + struct htc_service_connreq connect; + int ret; + + wmi->htc = htc; + + memset(&connect, 0, sizeof(connect)); + + connect.ep_callbacks.priv = wmi; + connect.ep_callbacks.tx = ath9k_wmi_ctrl_tx; + connect.ep_callbacks.rx = ath9k_wmi_ctrl_rx; + connect.service_id = WMI_CONTROL_SVC; + + ret = htc_connect_service(htc, &connect, &wmi->ctrl_epid); + if (ret) + return ret; + + *wmi_ctrl_epid = wmi->ctrl_epid; + + return 0; +} + +static int ath9k_wmi_cmd_issue(struct wmi *wmi, + struct sk_buff *skb, + enum wmi_cmd_id cmd, u16 len) +{ + struct wmi_cmd_hdr *hdr; + + hdr = (struct wmi_cmd_hdr *) skb_push(skb, sizeof(struct wmi_cmd_hdr)); + hdr->command_id = cpu_to_be16(cmd); + hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id); + + return htc_send(wmi->htc, skb, wmi->ctrl_epid, NULL); +} + +int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, + u8 *cmd_buf, u32 cmd_len, + u8 *rsp_buf, u32 rsp_len, + u32 timeout) +{ + struct ath_hw *ah = wmi->drv_priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + u16 headroom = sizeof(struct htc_frame_hdr) + + sizeof(struct wmi_cmd_hdr); + struct sk_buff *skb; + u8 *data; + int time_left, ret = 0; + + if (!wmi) + return -EINVAL; + + skb = dev_alloc_skb(headroom + cmd_len); + if (!skb) + return -ENOMEM; + + skb_reserve(skb, headroom); + + if (cmd_len != 0 && cmd_buf != NULL) { + data = (u8 *) skb_put(skb, cmd_len); + memcpy(data, cmd_buf, cmd_len); + } + + mutex_lock(&wmi->op_mutex); + + /* check if wmi stopped flag is set */ + if (unlikely(wmi->stopped)) { + ret = -EPROTO; + goto out; + } + + /* record the rsp buffer and length */ + wmi->cmd_rsp_buf = rsp_buf; + wmi->cmd_rsp_len = rsp_len; + + ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len); + if (ret) + goto out; + + time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout); + if (!time_left) { + ath_print(common, ATH_DBG_WMI, + "Timeout waiting for WMI command: %s\n", + wmi_cmd_to_name(cmd_id)); + mutex_unlock(&wmi->op_mutex); + return -ETIMEDOUT; + } + + mutex_unlock(&wmi->op_mutex); + + return 0; + +out: + ath_print(common, ATH_DBG_WMI, + "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id)); + mutex_unlock(&wmi->op_mutex); + dev_kfree_skb_any(skb); + + return ret; +} diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h new file mode 100644 index 000000000000..39ef926f27c2 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef WMI_H +#define WMI_H + + +struct wmi_event_txrate { + u32 txrate; + struct { + u8 rssi_thresh; + u8 per; + } rc_stats; +} __packed; + +struct wmi_cmd_hdr { + u16 command_id; + u16 seq_no; +} __packed; + +struct wmi_swba { + u8 beacon_pending; +} __packed; + +enum wmi_cmd_id { + WMI_ECHO_CMDID = 0x0001, + WMI_ACCESS_MEMORY_CMDID, + + /* Commands to Target */ + WMI_DISABLE_INTR_CMDID, + WMI_ENABLE_INTR_CMDID, + WMI_RX_LINK_CMDID, + WMI_ATH_INIT_CMDID, + WMI_ABORT_TXQ_CMDID, + WMI_STOP_TX_DMA_CMDID, + WMI_STOP_DMA_RECV_CMDID, + WMI_ABORT_TX_DMA_CMDID, + WMI_DRAIN_TXQ_CMDID, + WMI_DRAIN_TXQ_ALL_CMDID, + WMI_START_RECV_CMDID, + WMI_STOP_RECV_CMDID, + WMI_FLUSH_RECV_CMDID, + WMI_SET_MODE_CMDID, + WMI_RESET_CMDID, + WMI_NODE_CREATE_CMDID, + WMI_NODE_REMOVE_CMDID, + WMI_VAP_REMOVE_CMDID, + WMI_VAP_CREATE_CMDID, + WMI_BEACON_UPDATE_CMDID, + WMI_REG_READ_CMDID, + WMI_REG_WRITE_CMDID, + WMI_RC_STATE_CHANGE_CMDID, + WMI_RC_RATE_UPDATE_CMDID, + WMI_DEBUG_INFO_CMDID, + WMI_HOST_ATTACH, + WMI_TARGET_IC_UPDATE_CMDID, + WMI_TGT_STATS_CMDID, + WMI_TX_AGGR_ENABLE_CMDID, + WMI_TGT_DETACH_CMDID, + WMI_TGT_TXQ_ENABLE_CMDID, +}; + +enum wmi_event_id { + WMI_TGT_RDY_EVENTID = 0x1001, + WMI_SWBA_EVENTID, + WMI_FATAL_EVENTID, + WMI_TXTO_EVENTID, + WMI_BMISS_EVENTID, + WMI_WLAN_TXCOMP_EVENTID, + WMI_DELBA_EVENTID, + WMI_TXRATE_EVENTID, +}; + +struct wmi { + struct ath9k_htc_priv *drv_priv; + struct htc_target *htc; + enum htc_endpoint_id ctrl_epid; + struct mutex op_mutex; + struct completion cmd_wait; + u16 tx_seq_id; + u8 *cmd_rsp_buf; + u32 cmd_rsp_len; + bool stopped; + + struct sk_buff *wmi_skb; + spinlock_t wmi_lock; +}; + +struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv); +void ath9k_deinit_wmi(struct ath9k_htc_priv *priv); +int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi, + enum htc_endpoint_id *wmi_ctrl_epid); +int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, + u8 *cmd_buf, u32 cmd_len, + u8 *rsp_buf, u32 rsp_len, + u32 timeout); +void ath9k_wmi_tasklet(unsigned long data); + +#define WMI_CMD(_wmi_cmd) \ + do { \ + ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, NULL, 0, \ + (u8 *) &cmd_rsp, \ + sizeof(cmd_rsp), HZ); \ + } while (0) + +#define WMI_CMD_BUF(_wmi_cmd, _buf) \ + do { \ + ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, \ + (u8 *) _buf, sizeof(*_buf), \ + &cmd_rsp, sizeof(cmd_rsp), HZ); \ + } while (0) + +#endif /* WMI_H */ diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h index 8263633c003c..873bf526e11f 100644 --- a/drivers/net/wireless/ath/debug.h +++ b/drivers/net/wireless/ath/debug.h @@ -59,6 +59,7 @@ enum ATH_DEBUG { ATH_DBG_PS = 0x00000800, ATH_DBG_HWTIMER = 0x00001000, ATH_DBG_BTCOEX = 0x00002000, + ATH_DBG_WMI = 0x00004000, ATH_DBG_ANY = 0xffffffff }; -- cgit v1.2.3 From b43316dbf9c6b01f3ac6dc23bcb94ae66eb3a721 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Mar 2010 12:26:26 +0200 Subject: wl1271: Fix configuration of the TX opportunity value The per-queue TX opportunity value is configured by the mac80211 in units of 32us. The firmware however wants it in us, so add the conversion. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 0a4ff7b02f59..0de337f9e50f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1745,9 +1745,10 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, if (ret < 0) goto out; + /* the txop is confed in units of 32us by the mac80211, we need us */ ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), params->cw_min, params->cw_max, - params->aifs, params->txop); + params->aifs, params->txop << 5); if (ret < 0) goto out_sleep; -- cgit v1.2.3 From becd551cac0d6868819083c59fc32d1072ba1804 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Thu, 18 Mar 2010 12:26:27 +0200 Subject: wl1271: Cleaned up wlan power on/off functions Added method for wlan power control to io_ops struct and moved wl1271_power_on and wl1271_power_off functions to wl1271_io.h. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 1 + drivers/net/wireless/wl12xx/wl1271_debugfs.c | 12 +++++------- drivers/net/wireless/wl12xx/wl1271_io.h | 12 ++++++++++++ drivers/net/wireless/wl12xx/wl1271_main.c | 12 ------------ drivers/net/wireless/wl12xx/wl1271_sdio.c | 11 +++++------ drivers/net/wireless/wl12xx/wl1271_spi.c | 7 +++++++ 6 files changed, 30 insertions(+), 25 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 0deb4fdf916b..7397999deb19 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -344,6 +344,7 @@ struct wl1271_if_operations { bool fixed); void (*reset)(struct wl1271 *wl); void (*init)(struct wl1271 *wl); + void (*power)(struct wl1271 *wl, bool enable); struct device* (*dev)(struct wl1271 *wl); void (*enable_irq)(struct wl1271 *wl); void (*disable_irq)(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c index 8d7588ca68fd..3c0f5b1ac272 100644 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c @@ -28,6 +28,7 @@ #include "wl1271.h" #include "wl1271_acx.h" #include "wl1271_ps.h" +#include "wl1271_io.h" /* ms */ #define WL1271_DEBUGFS_STATS_LIFETIME 1000 @@ -276,13 +277,10 @@ static ssize_t gpio_power_write(struct file *file, goto out; } - if (value) { - wl->set_power(true); - set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); - } else { - wl->set_power(false); - clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); - } + if (value) + wl1271_power_on(wl); + else + wl1271_power_off(wl); out: mutex_unlock(&wl->mutex); diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index 95d2168f8af4..3ff88d971308 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h @@ -138,6 +138,18 @@ static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); } +static inline void wl1271_power_off(struct wl1271 *wl) +{ + wl->if_ops->power(wl, false); + clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); +} + +static inline void wl1271_power_on(struct wl1271 *wl) +{ + wl->if_ops->power(wl, true); + set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); +} + /* Top Register IO */ void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 0de337f9e50f..b3abb455bd70 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -359,18 +359,6 @@ static int wl1271_plt_init(struct wl1271 *wl) return ret; } -static void wl1271_power_off(struct wl1271 *wl) -{ - wl->set_power(false); - clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); -} - -static void wl1271_power_on(struct wl1271 *wl) -{ - wl->set_power(true); - set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); -} - static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status) { diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index 1f204db30c27..d43e0d41d439 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c @@ -156,20 +156,21 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, sdio_release_host(func); } +static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable) +{ +} + static struct wl1271_if_operations sdio_ops = { .read = wl1271_sdio_raw_read, .write = wl1271_sdio_raw_write, .reset = wl1271_sdio_reset, .init = wl1271_sdio_init, + .power = wl1271_sdio_set_power, .dev = wl1271_sdio_wl_to_dev, .enable_irq = wl1271_sdio_enable_interrupts, .disable_irq = wl1271_sdio_disable_interrupts }; -static void wl1271_sdio_set_power(bool enable) -{ -} - static int __devinit wl1271_probe(struct sdio_func *func, const struct sdio_device_id *id) { @@ -190,8 +191,6 @@ static int __devinit wl1271_probe(struct sdio_func *func, wl->if_priv = func; wl->if_ops = &sdio_ops; - wl->set_power = wl1271_sdio_set_power; - /* Grab access to FN0 for ELP reg. */ func->card->quirks |= MMC_QUIRK_LENIENT_FN0; diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index ed285fec2a08..0eea73392ea3 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c @@ -347,11 +347,18 @@ static struct platform_device wl1271_device = { }, }; +static void wl1271_spi_set_power(struct wl1271 *wl, bool enable) +{ + if (wl->set_power) + wl->set_power(enable); +} + static struct wl1271_if_operations spi_ops = { .read = wl1271_spi_raw_read, .write = wl1271_spi_raw_write, .reset = wl1271_spi_reset, .init = wl1271_spi_init, + .power = wl1271_spi_set_power, .dev = wl1271_spi_wl_to_dev, .enable_irq = wl1271_spi_enable_interrupts, .disable_irq = wl1271_spi_disable_interrupts -- cgit v1.2.3 From 93f56be146a7be4d3243fc64d9b6313d96eaa62b Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Thu, 18 Mar 2010 12:26:28 +0200 Subject: wl1271: Changed SDIO MMC host claiming Changed driver to keep MMC host claimed while wlan interface is up. This keeps MMC stack from powering the SDIO device down. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_sdio.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index d43e0d41d439..d9183b64e723 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c @@ -107,7 +107,6 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, int ret; struct sdio_func *func = wl_to_func(wl); - sdio_claim_host(func); if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); wl1271_debug(DEBUG_SPI, "sdio read 52 addr 0x%x, byte 0x%02x", @@ -126,7 +125,6 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, if (ret) wl1271_error("sdio read failed (%d)", ret); - sdio_release_host(func); } static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, @@ -135,7 +133,6 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, int ret; struct sdio_func *func = wl_to_func(wl); - sdio_claim_host(func); if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); wl1271_debug(DEBUG_SPI, "sdio write 52 addr 0x%x, byte 0x%02x", @@ -153,11 +150,19 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, if (ret) wl1271_error("sdio write failed (%d)", ret); - sdio_release_host(func); } static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable) { + struct sdio_func *func = wl_to_func(wl); + + if (enable) { + sdio_claim_host(func); + sdio_enable_func(func); + } else { + sdio_disable_func(func); + sdio_release_host(func); + } } static struct wl1271_if_operations sdio_ops = { @@ -219,22 +224,12 @@ static int __devinit wl1271_probe(struct sdio_func *func, if (ret) goto out_irq; - sdio_claim_host(func); sdio_set_drvdata(func, wl); - ret = sdio_enable_func(func); - if (ret) - goto out_release; - - sdio_release_host(func); - wl1271_notice("initialized"); return 0; - out_release: - sdio_release_host(func); - out_irq: free_irq(wl->irq, wl); @@ -251,10 +246,6 @@ static void __devexit wl1271_remove(struct sdio_func *func) ieee80211_unregister_hw(wl->hw); - sdio_claim_host(func); - sdio_disable_func(func); - sdio_release_host(func); - free_irq(wl->irq, wl); kfree(wl->target_mem_map); -- cgit v1.2.3 From 885c9907440947a4f50d4c7a93b1a45266b00b84 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Mar 2010 12:26:29 +0200 Subject: wl1271: Fix SG configuration message structures The bluetooth coexistence (SG) configuration messages have changed and were completely wrong. For instance, intending to enable the SG, it was instead disabled. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.c | 17 +---- drivers/net/wireless/wl12xx/wl1271_acx.h | 120 ++++++++++++++++--------------- 2 files changed, 66 insertions(+), 71 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 60e20876e6d8..405ae1bf464f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -547,7 +547,7 @@ int wl1271_acx_sg_enable(struct wl1271 *wl) goto out; } - pta->enable = SG_ENABLE; + pta->enable = ACX_SG_DISABLE; ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta)); if (ret < 0) { @@ -575,19 +575,8 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) } /* BT-WLAN coext parameters */ - param->per_threshold = cpu_to_le32(c->per_threshold); - param->max_scan_compensation_time = - cpu_to_le32(c->max_scan_compensation_time); - param->nfs_sample_interval = cpu_to_le16(c->nfs_sample_interval); - param->load_ratio = c->load_ratio; - param->auto_ps_mode = c->auto_ps_mode; - param->probe_req_compensation = c->probe_req_compensation; - param->scan_window_compensation = c->scan_window_compensation; - param->antenna_config = c->antenna_config; - param->beacon_miss_threshold = c->beacon_miss_threshold; - param->rate_adaptation_threshold = - cpu_to_le32(c->rate_adaptation_threshold); - param->rate_adaptation_snr = c->rate_adaptation_snr; + param->params[ACX_SG_BT_PER_THRESHOLD] = c->per_threshold; + param->param_idx = ACX_SG_BT_PER_THRESHOLD; ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); if (ret < 0) { diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index aeccc98581eb..88a05cbd3457 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -393,80 +393,86 @@ struct acx_conn_monit_params { } __attribute__ ((packed)); enum { - SG_ENABLE = 0, - SG_DISABLE, - SG_SENSE_NO_ACTIVITY, - SG_SENSE_ACTIVE + ACX_SG_DISABLE = 0, + ACX_SG_PROTECTIVE, + ACX_SG_OPPORTUNISTIC }; struct acx_bt_wlan_coex { struct acx_header header; - /* - * 0 -> PTA enabled - * 1 -> PTA disabled - * 2 -> sense no active mode, i.e. - * an interrupt is sent upon - * BT activity. - * 3 -> PTA is switched on in response - * to the interrupt sending. - */ u8 enable; u8 pad[3]; } __attribute__ ((packed)); -struct acx_dco_itrim_params { +enum { + ACX_SG_BT_PER_THRESHOLD = 0, + ACX_SG_HV3_MAX_OVERRIDE, + ACX_SG_BT_NFS_SAMPLE_INTERVAL, + ACX_SG_BT_LOAD_RATIO, + ACX_SG_AUTO_PS_MODE, + ACX_SG_AUTO_SCAN_PROBE_REQ, + ACX_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3, + ACX_SG_ANTENNA_CONFIGURATION, + ACX_SG_BEACON_MISS_PERCENT, + ACX_SG_RATE_ADAPT_THRESH, + ACX_SG_RATE_ADAPT_SNR, + ACX_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR, + ACX_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR, + ACX_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR, + ACX_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR, + ACX_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR, + ACX_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR, + ACX_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR, + ACX_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR, + ACX_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR, + ACX_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR, + ACX_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR, + ACX_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR, + ACX_SG_RXT, + ACX_SG_TXT, + ACX_SG_ADAPTIVE_RXT_TXT, + ACX_SG_PS_POLL_TIMEOUT, + ACX_SG_UPSD_TIMEOUT, + ACX_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR, + ACX_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR, + ACX_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR, + ACX_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR, + ACX_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR, + ACX_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR, + ACX_SG_WLAN_ACTIVE_BT_ACL_MIN_BR, + ACX_SG_WLAN_ACTIVE_BT_ACL_MAX_BR, + ACX_SG_WLAN_ACTIVE_MAX_BT_ACL_BR, + ACX_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3, + ACX_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP, + ACX_SG_PASSIVE_SCAN_A2DP_BT_TIME, + ACX_SG_PASSIVE_SCAN_A2DP_WLAN_TIME, + ACX_SG_HV3_MAX_SERVED, + ACX_SG_DHCP_TIME, + ACX_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP, + ACX_SG_TEMP_PARAM_1, + ACX_SG_TEMP_PARAM_2, + ACX_SG_TEMP_PARAM_3, + ACX_SG_TEMP_PARAM_4, + ACX_SG_TEMP_PARAM_5, + ACX_SG_PARAMS_MAX, + ACX_SG_PARAMS_ALL = 0xff +}; + +struct acx_bt_wlan_coex_param { struct acx_header header; - u8 enable; + __le32 params[ACX_SG_PARAMS_MAX]; + u8 param_idx; u8 padding[3]; - __le32 timeout; } __attribute__ ((packed)); -#define PTA_ANTENNA_TYPE_DEF (0) -#define PTA_BT_HP_MAXTIME_DEF (2000) -#define PTA_WLAN_HP_MAX_TIME_DEF (5000) -#define PTA_SENSE_DISABLE_TIMER_DEF (1350) -#define PTA_PROTECTIVE_RX_TIME_DEF (1500) -#define PTA_PROTECTIVE_TX_TIME_DEF (1500) -#define PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF (3000) -#define PTA_SIGNALING_TYPE_DEF (1) -#define PTA_AFH_LEVERAGE_ON_DEF (0) -#define PTA_NUMBER_QUIET_CYCLE_DEF (0) -#define PTA_MAX_NUM_CTS_DEF (3) -#define PTA_NUMBER_OF_WLAN_PACKETS_DEF (2) -#define PTA_NUMBER_OF_BT_PACKETS_DEF (2) -#define PTA_PROTECTIVE_RX_TIME_FAST_DEF (1500) -#define PTA_PROTECTIVE_TX_TIME_FAST_DEF (3000) -#define PTA_CYCLE_TIME_FAST_DEF (8700) -#define PTA_RX_FOR_AVALANCHE_DEF (5) -#define PTA_ELP_HP_DEF (0) -#define PTA_ANTI_STARVE_PERIOD_DEF (500) -#define PTA_ANTI_STARVE_NUM_CYCLE_DEF (4) -#define PTA_ALLOW_PA_SD_DEF (1) -#define PTA_TIME_BEFORE_BEACON_DEF (6300) -#define PTA_HPDM_MAX_TIME_DEF (1600) -#define PTA_TIME_OUT_NEXT_WLAN_DEF (2550) -#define PTA_AUTO_MODE_NO_CTS_DEF (0) -#define PTA_BT_HP_RESPECTED_DEF (3) -#define PTA_WLAN_RX_MIN_RATE_DEF (24) -#define PTA_ACK_MODE_DEF (1) - -struct acx_bt_wlan_coex_param { +struct acx_dco_itrim_params { struct acx_header header; - __le32 per_threshold; - __le32 max_scan_compensation_time; - __le16 nfs_sample_interval; - u8 load_ratio; - u8 auto_ps_mode; - u8 probe_req_compensation; - u8 scan_window_compensation; - u8 antenna_config; - u8 beacon_miss_threshold; - __le32 rate_adaptation_threshold; - s8 rate_adaptation_snr; + u8 enable; u8 padding[3]; + __le32 timeout; } __attribute__ ((packed)); struct acx_energy_detection { -- cgit v1.2.3 From 1b00f546fc4271d94c1bccb1955ce64d9ace1000 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Mar 2010 12:26:30 +0200 Subject: wl1271: Add proper WLAN-BT co-ex configuration, and enable co-ex. Add configuration values for the varous WLAN-BT co-ex configuration parameters, and finally enable WLAN-BT co-ex. Based on preliminary measurements, it appears the co-ex feature is not increasing WLAN power consumption, if BT is not activated. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.c | 9 +- drivers/net/wireless/wl12xx/wl1271_acx.h | 62 +----- drivers/net/wireless/wl12xx/wl1271_conf.h | 330 ++++++++++++++++++++++++------ drivers/net/wireless/wl12xx/wl1271_init.c | 4 +- drivers/net/wireless/wl12xx/wl1271_main.c | 62 +++++- 5 files changed, 328 insertions(+), 139 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 405ae1bf464f..e7c22d3c75ac 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -547,7 +547,7 @@ int wl1271_acx_sg_enable(struct wl1271 *wl) goto out; } - pta->enable = ACX_SG_DISABLE; + pta->enable = wl->conf.sg.state; ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta)); if (ret < 0) { @@ -564,7 +564,7 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) { struct acx_bt_wlan_coex_param *param; struct conf_sg_settings *c = &wl->conf.sg; - int ret; + int i, ret; wl1271_debug(DEBUG_ACX, "acx sg cfg"); @@ -575,8 +575,9 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) } /* BT-WLAN coext parameters */ - param->params[ACX_SG_BT_PER_THRESHOLD] = c->per_threshold; - param->param_idx = ACX_SG_BT_PER_THRESHOLD; + for (i = 0; i < CONF_SG_PARAMS_MAX; i++) + param->params[i] = c->params[i]; + param->param_idx = CONF_SG_PARAMS_ALL; ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); if (ret < 0) { diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 88a05cbd3457..dee3c06a717c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -392,12 +392,6 @@ struct acx_conn_monit_params { __le32 bss_lose_timeout; /* number of TU's from synch fail */ } __attribute__ ((packed)); -enum { - ACX_SG_DISABLE = 0, - ACX_SG_PROTECTIVE, - ACX_SG_OPPORTUNISTIC -}; - struct acx_bt_wlan_coex { struct acx_header header; @@ -405,64 +399,10 @@ struct acx_bt_wlan_coex { u8 pad[3]; } __attribute__ ((packed)); -enum { - ACX_SG_BT_PER_THRESHOLD = 0, - ACX_SG_HV3_MAX_OVERRIDE, - ACX_SG_BT_NFS_SAMPLE_INTERVAL, - ACX_SG_BT_LOAD_RATIO, - ACX_SG_AUTO_PS_MODE, - ACX_SG_AUTO_SCAN_PROBE_REQ, - ACX_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3, - ACX_SG_ANTENNA_CONFIGURATION, - ACX_SG_BEACON_MISS_PERCENT, - ACX_SG_RATE_ADAPT_THRESH, - ACX_SG_RATE_ADAPT_SNR, - ACX_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR, - ACX_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR, - ACX_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR, - ACX_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR, - ACX_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR, - ACX_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR, - ACX_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR, - ACX_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR, - ACX_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR, - ACX_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR, - ACX_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR, - ACX_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR, - ACX_SG_RXT, - ACX_SG_TXT, - ACX_SG_ADAPTIVE_RXT_TXT, - ACX_SG_PS_POLL_TIMEOUT, - ACX_SG_UPSD_TIMEOUT, - ACX_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR, - ACX_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR, - ACX_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR, - ACX_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR, - ACX_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR, - ACX_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR, - ACX_SG_WLAN_ACTIVE_BT_ACL_MIN_BR, - ACX_SG_WLAN_ACTIVE_BT_ACL_MAX_BR, - ACX_SG_WLAN_ACTIVE_MAX_BT_ACL_BR, - ACX_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3, - ACX_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP, - ACX_SG_PASSIVE_SCAN_A2DP_BT_TIME, - ACX_SG_PASSIVE_SCAN_A2DP_WLAN_TIME, - ACX_SG_HV3_MAX_SERVED, - ACX_SG_DHCP_TIME, - ACX_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP, - ACX_SG_TEMP_PARAM_1, - ACX_SG_TEMP_PARAM_2, - ACX_SG_TEMP_PARAM_3, - ACX_SG_TEMP_PARAM_4, - ACX_SG_TEMP_PARAM_5, - ACX_SG_PARAMS_MAX, - ACX_SG_PARAMS_ALL = 0xff -}; - struct acx_bt_wlan_coex_param { struct acx_header header; - __le32 params[ACX_SG_PARAMS_MAX]; + __le32 params[CONF_SG_PARAMS_MAX]; u8 param_idx; u8 padding[3]; } __attribute__ ((packed)); diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 6f9e75cc5640..7fcfe06b1412 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -65,110 +65,318 @@ enum { CONF_HW_RATE_INDEX_MAX = CONF_HW_RATE_INDEX_54MBPS, }; -struct conf_sg_settings { +enum { + CONF_SG_DISABLE = 0, + CONF_SG_PROTECTIVE, + CONF_SG_OPPORTUNISTIC +}; + +enum { /* - * Defines the PER threshold in PPM of the BT voice of which reaching - * this value will trigger raising the priority of the BT voice by - * the BT IP until next NFS sample interval time as defined in - * nfs_sample_interval. + * PER threshold in PPM of the BT voice * - * Unit: PER value in PPM (parts per million) - * #Error_packets / #Total_packets + * Range: 0 - 10000000 + */ + CONF_SG_BT_PER_THRESHOLD = 0, - * Range: u32 + /* + * Number of consequent RX_ACTIVE activities to override BT voice + * frames to ensure WLAN connection + * + * Range: 0 - 100 + */ + CONF_SG_HV3_MAX_OVERRIDE, + + /* + * Defines the PER threshold of the BT voice + * + * Range: 0 - 65000 + */ + CONF_SG_BT_NFS_SAMPLE_INTERVAL, + + /* + * Defines the load ratio of BT + * + * Range: 0 - 100 (%) + */ + CONF_SG_BT_LOAD_RATIO, + + /* + * Defines whether the SG will force WLAN host to enter/exit PSM + * + * Range: 1 - SG can force, 0 - host handles PSM + */ + CONF_SG_AUTO_PS_MODE, + + /* + * Compensation percentage of probe requests when scan initiated + * during BT voice/ACL link. + * + * Range: 0 - 255 (%) + */ + CONF_SG_AUTO_SCAN_PROBE_REQ, + + /* + * Compensation percentage of probe requests when active scan initiated + * during BT voice + * + * Range: 0 - 255 (%) + */ + CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3, + + /* + * Defines antenna configuration (single/dual antenna) + * + * Range: 0 - single antenna, 1 - dual antenna + */ + CONF_SG_ANTENNA_CONFIGURATION, + + /* + * The threshold (percent) of max consequtive beacon misses before + * increasing priority of beacon reception. + * + * Range: 0 - 100 (%) + */ + CONF_SG_BEACON_MISS_PERCENT, + + /* + * The rate threshold below which receiving a data frame from the AP + * will increase the priority of the data frame above BT traffic. + * + * Range: 0,2, 5(=5.5), 6, 9, 11, 12, 18, 24, 36, 48, 54 + */ + CONF_SG_RATE_ADAPT_THRESH, + + /* + * Not used currently. + * + * Range: 0 + */ + CONF_SG_RATE_ADAPT_SNR, + + /* + * Configure the min and max time BT gains the antenna + * in WLAN PSM / BT master basic rate + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR, + CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR, + + /* + * The time after it expires no new WLAN trigger frame is trasmitted + * in WLAN PSM / BT master basic rate + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR, + + /* + * Configure the min and max time BT gains the antenna + * in WLAN PSM / BT slave basic rate + * + * Range: 0 - 255 (ms) */ - u32 per_threshold; + CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR, + CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR, /* - * This value is an absolute time in micro-seconds to limit the - * maximum scan duration compensation while in SG + * The time after it expires no new WLAN trigger frame is trasmitted + * in WLAN PSM / BT slave basic rate + * + * Range: 0 - 255 (ms) */ - u32 max_scan_compensation_time; + CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR, - /* Defines the PER threshold of the BT voice of which reaching this - * value will trigger raising the priority of the BT voice until next - * NFS sample interval time as defined in sample_interval. + /* + * Configure the min and max time BT gains the antenna + * in WLAN PSM / BT master EDR * - * Unit: msec - * Range: 1-65000 + * Range: 0 - 255 (ms) */ - u16 nfs_sample_interval; + CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR, + CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR, /* - * Defines the load ratio for the BT. - * The WLAN ratio is: 100 - load_ratio + * The time after it expires no new WLAN trigger frame is trasmitted + * in WLAN PSM / BT master EDR * - * Unit: Percent - * Range: 0-100 + * Range: 0 - 255 (ms) */ - u8 load_ratio; + CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR, /* - * true - Co-ex is allowed to enter/exit P.S automatically and - * transparently to the host + * Configure the min and max time BT gains the antenna + * in WLAN PSM / BT slave EDR * - * false - Co-ex is disallowed to enter/exit P.S and will trigger an - * event to the host to notify for the need to enter/exit P.S - * due to BT change state + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR, + CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR, + + /* + * The time after it expires no new WLAN trigger frame is trasmitted + * in WLAN PSM / BT slave EDR * + * Range: 0 - 255 (ms) */ - u8 auto_ps_mode; + CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR, /* - * This parameter defines the compensation percentage of num of probe - * requests in case scan is initiated during BT voice/BT ACL - * guaranteed link. + * RX guard time before the beginning of a new BT voice frame during + * which no new WLAN trigger frame is transmitted. * - * Unit: Percent - * Range: 0-255 (0 - No compensation) + * Range: 0 - 100000 (us) */ - u8 probe_req_compensation; + CONF_SG_RXT, /* - * This parameter defines the compensation percentage of scan window - * size in case scan is initiated during BT voice/BT ACL Guaranteed - * link. + * TX guard time before the beginning of a new BT voice frame during + * which no new WLAN frame is transmitted. * - * Unit: Percent - * Range: 0-255 (0 - No compensation) + * Range: 0 - 100000 (us) */ - u8 scan_window_compensation; + + CONF_SG_TXT, /* - * Defines the antenna configuration. + * Enable adaptive RXT/TXT algorithm. If disabled, the host values + * will be utilized. * - * Range: 0 - Single Antenna; 1 - Dual Antenna + * Range: 0 - disable, 1 - enable */ - u8 antenna_config; + CONF_SG_ADAPTIVE_RXT_TXT, /* - * The percent out of the Max consecutive beacon miss roaming trigger - * which is the threshold for raising the priority of beacon - * reception. + * The used WLAN legacy service period during active BT ACL link * - * Range: 1-100 - * N = MaxConsecutiveBeaconMiss - * P = coexMaxConsecutiveBeaconMissPrecent - * Threshold = MIN( N-1, round(N * P / 100)) + * Range: 0 - 255 (ms) */ - u8 beacon_miss_threshold; + CONF_SG_PS_POLL_TIMEOUT, /* - * The RX rate threshold below which rate adaptation is assumed to be - * occurring at the AP which will raise priority for ACTIVE_RX and RX - * SP. + * The used WLAN UPSD service period during active BT ACL link * - * Range: HW_BIT_RATE_* + * Range: 0 - 255 (ms) */ - u32 rate_adaptation_threshold; + CONF_SG_UPSD_TIMEOUT, /* - * The SNR above which the RX rate threshold indicating AP rate - * adaptation is valid + * Configure the min and max time BT gains the antenna + * in WLAN Active / BT master EDR * - * Range: -128 - 127 + * Range: 0 - 255 (ms) */ - s8 rate_adaptation_snr; + CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR, + CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR, + + /* + * The maximum time WLAN can gain the antenna for + * in WLAN Active / BT master EDR + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR, + + /* + * Configure the min and max time BT gains the antenna + * in WLAN Active / BT slave EDR + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR, + CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR, + + /* + * The maximum time WLAN can gain the antenna for + * in WLAN Active / BT slave EDR + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR, + + /* + * Configure the min and max time BT gains the antenna + * in WLAN Active / BT basic rate + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR, + CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR, + + /* + * The maximum time WLAN can gain the antenna for + * in WLAN Active / BT basic rate + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR, + + /* + * Compensation percentage of WLAN passive scan window if initiated + * during BT voice + * + * Range: 0 - 1000 (%) + */ + CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3, + + /* + * Compensation percentage of WLAN passive scan window if initiated + * during BT A2DP + * + * Range: 0 - 1000 (%) + */ + CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP, + + /* + * Fixed time ensured for BT traffic to gain the antenna during WLAN + * passive scan. + * + * Range: 0 - 1000 ms + */ + CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME, + + /* + * Fixed time ensured for WLAN traffic to gain the antenna during WLAN + * passive scan. + * + * Range: 0 - 1000 ms + */ + CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME, + + /* + * Number of consequent BT voice frames not interrupted by WLAN + * + * Range: 0 - 100 + */ + CONF_SG_HV3_MAX_SERVED, + + /* + * Protection time of the DHCP procedure. + * + * Range: 0 - 100000 (ms) + */ + CONF_SG_DHCP_TIME, + + /* + * Compensation percentage of WLAN active scan window if initiated + * during BT A2DP + * + * Range: 0 - 1000 (%) + */ + CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP, + CONF_SG_TEMP_PARAM_1, + CONF_SG_TEMP_PARAM_2, + CONF_SG_TEMP_PARAM_3, + CONF_SG_TEMP_PARAM_4, + CONF_SG_TEMP_PARAM_5, + CONF_SG_PARAMS_MAX, + CONF_SG_PARAMS_ALL = 0xff +}; + +struct conf_sg_settings { + __le32 params[CONF_SG_PARAMS_MAX]; + u8 state; }; enum conf_rx_queue_type { diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 86c30a86a456..d68445c9d333 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -160,11 +160,11 @@ int wl1271_init_pta(struct wl1271 *wl) { int ret; - ret = wl1271_acx_sg_enable(wl); + ret = wl1271_acx_sg_cfg(wl); if (ret < 0) return ret; - ret = wl1271_acx_sg_cfg(wl); + ret = wl1271_acx_sg_enable(wl); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b3abb455bd70..6501d6e2d3b2 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -48,17 +48,57 @@ static struct conf_drv_settings default_conf = { .sg = { - .per_threshold = 7500, - .max_scan_compensation_time = 120000, - .nfs_sample_interval = 400, - .load_ratio = 50, - .auto_ps_mode = 0, - .probe_req_compensation = 170, - .scan_window_compensation = 50, - .antenna_config = 0, - .beacon_miss_threshold = 60, - .rate_adaptation_threshold = CONF_HW_BIT_RATE_12MBPS, - .rate_adaptation_snr = 0 + .params = { + [CONF_SG_BT_PER_THRESHOLD] = 7500, + [CONF_SG_HV3_MAX_OVERRIDE] = 0, + [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, + [CONF_SG_BT_LOAD_RATIO] = 50, + [CONF_SG_AUTO_PS_MODE] = 0, + [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, + [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, + [CONF_SG_ANTENNA_CONFIGURATION] = 0, + [CONF_SG_BEACON_MISS_PERCENT] = 60, + [CONF_SG_RATE_ADAPT_THRESH] = 12, + [CONF_SG_RATE_ADAPT_SNR] = 0, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 30, + [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 8, + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20, + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 50, + /* Note: with UPSD, this should be 4 */ + [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 8, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25, + [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 20, + /* Note: with UPDS, this should be 15 */ + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8, + /* Note: with UPDS, this should be 50 */ + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 40, + /* Note: with UPDS, this should be 10 */ + [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 20, + [CONF_SG_RXT] = 1200, + [CONF_SG_TXT] = 1000, + [CONF_SG_ADAPTIVE_RXT_TXT] = 1, + [CONF_SG_PS_POLL_TIMEOUT] = 10, + [CONF_SG_UPSD_TIMEOUT] = 10, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15, + [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15, + [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8, + [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20, + [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50, + [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10, + [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, + [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800, + [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75, + [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15, + [CONF_SG_HV3_MAX_SERVED] = 6, + [CONF_SG_DHCP_TIME] = 5000, + [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, + }, + .state = CONF_SG_PROTECTIVE, }, .rx = { .rx_msdu_life_time = 512000, -- cgit v1.2.3 From a1dd8187d8d8f565976c9e55374dee520cdc2fa3 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Mar 2010 12:26:31 +0200 Subject: wl1271: Move platform device registration from _spi to _main In order to get the platform device for both SPI and SDIO, move the platform device registration to wl1271_main.c from wl1271_spi.c. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 37 +++++++++++++++++++++++++++++-- drivers/net/wireless/wl12xx/wl1271_spi.c | 31 ++------------------------ 2 files changed, 37 insertions(+), 31 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 6501d6e2d3b2..ad9c49111678 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "wl1271.h" #include "wl12xx_80211.h" @@ -280,6 +281,21 @@ static struct conf_drv_settings default_conf = { } }; +static void wl1271_device_release(struct device *dev) +{ + +} + +static struct platform_device wl1271_device = { + .name = "wl1271", + .id = -1, + + /* device model insists to have a release function */ + .dev = { + .release = wl1271_device_release, + }, +}; + static LIST_HEAD(wl_list); static void wl1271_conf_init(struct wl1271 *wl) @@ -2025,12 +2041,13 @@ struct ieee80211_hw *wl1271_alloc_hw(void) { struct ieee80211_hw *hw; struct wl1271 *wl; - int i; + int i, ret; hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); if (!hw) { wl1271_error("could not alloc ieee80211_hw"); - return ERR_PTR(-ENOMEM); + ret = -ENOMEM; + goto err; } wl = hw->priv; @@ -2070,12 +2087,28 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl1271_debugfs_init(wl); + /* Register platform device */ + ret = platform_device_register(&wl1271_device); + if (ret) { + wl1271_error("couldn't register platform device"); + goto err_hw; + } + dev_set_drvdata(&wl1271_device.dev, wl); + + return hw; + +err_hw: + ieee80211_unregister_hw(wl->hw); + +err: + return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(wl1271_alloc_hw); int wl1271_free_hw(struct wl1271 *wl) { + platform_device_unregister(&wl1271_device); ieee80211_unregister_hw(wl->hw); wl1271_debugfs_exit(wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 0eea73392ea3..4c129c76c29d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -332,21 +331,6 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) return IRQ_HANDLED; } -static void wl1271_device_release(struct device *dev) -{ - -} - -static struct platform_device wl1271_device = { - .name = "wl1271", - .id = -1, - - /* device model insists to have a release function */ - .dev = { - .release = wl1271_device_release, - }, -}; - static void wl1271_spi_set_power(struct wl1271 *wl, bool enable) { if (wl->set_power) @@ -422,28 +406,18 @@ static int __devinit wl1271_probe(struct spi_device *spi) disable_irq(wl->irq); - ret = platform_device_register(&wl1271_device); - if (ret) { - wl1271_error("couldn't register platform device"); - goto out_irq; - } - dev_set_drvdata(&wl1271_device.dev, wl); - ret = wl1271_init_ieee80211(wl); if (ret) - goto out_platform; + goto out_irq; ret = wl1271_register_hw(wl); if (ret) - goto out_platform; + goto out_irq; wl1271_notice("initialized"); return 0; - out_platform: - platform_device_unregister(&wl1271_device); - out_irq: free_irq(wl->irq, wl); @@ -457,7 +431,6 @@ static int __devexit wl1271_remove(struct spi_device *spi) { struct wl1271 *wl = dev_get_drvdata(&spi->dev); - platform_device_unregister(&wl1271_device); free_irq(wl->irq, wl); wl1271_free_hw(wl); -- cgit v1.2.3 From 7fc3a8647d2eaa8bc2f7ac7e9baff55199da7be6 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Mar 2010 12:26:32 +0200 Subject: wl1271: Add sysfs file to control BT co-ex state Add a sysfs file to control the state of the BT co-ex (enable or disable it.) By default, the BT co-ex is enabled. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 2 + drivers/net/wireless/wl12xx/wl1271_acx.c | 7 ++- drivers/net/wireless/wl12xx/wl1271_acx.h | 2 +- drivers/net/wireless/wl12xx/wl1271_init.c | 2 +- drivers/net/wireless/wl12xx/wl1271_main.c | 72 +++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 7397999deb19..23a0c7e22939 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -484,6 +484,8 @@ struct wl1271 { /* Current chipset configuration */ struct conf_drv_settings conf; + bool sg_enabled; + struct list_head list; }; diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index e7c22d3c75ac..7e337cea9905 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -534,7 +534,7 @@ out: } -int wl1271_acx_sg_enable(struct wl1271 *wl) +int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable) { struct acx_bt_wlan_coex *pta; int ret; @@ -547,7 +547,10 @@ int wl1271_acx_sg_enable(struct wl1271 *wl) goto out; } - pta->enable = wl->conf.sg.state; + if (enable) + pta->enable = wl->conf.sg.state; + else + pta->enable = CONF_SG_DISABLE; ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta)); if (ret < 0) { diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index dee3c06a717c..8e5870fa9609 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -1005,7 +1005,7 @@ int wl1271_acx_dco_itrim_params(struct wl1271 *wl); int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); int wl1271_acx_beacon_filter_table(struct wl1271 *wl); int wl1271_acx_conn_monit_params(struct wl1271 *wl); -int wl1271_acx_sg_enable(struct wl1271 *wl); +int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); int wl1271_acx_sg_cfg(struct wl1271 *wl); int wl1271_acx_cca_threshold(struct wl1271 *wl); int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index d68445c9d333..d9335fc2a575 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -164,7 +164,7 @@ int wl1271_init_pta(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_acx_sg_enable(wl); + ret = wl1271_acx_sg_enable(wl, wl->sg_enabled); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index ad9c49111678..abf9f22ee968 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1982,6 +1982,68 @@ static const struct ieee80211_ops wl1271_ops = { CFG80211_TESTMODE_CMD(wl1271_tm_cmd) }; +static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct wl1271 *wl = dev_get_drvdata(dev); + ssize_t len; + + /* FIXME: what's the maximum length of buf? page size?*/ + len = 500; + + mutex_lock(&wl->mutex); + len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n", + wl->sg_enabled); + mutex_unlock(&wl->mutex); + + return len; + +} + +static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct wl1271 *wl = dev_get_drvdata(dev); + unsigned long res; + int ret; + + ret = strict_strtoul(buf, 10, &res); + + if (ret < 0) { + wl1271_warning("incorrect value written to bt_coex_mode"); + return count; + } + + mutex_lock(&wl->mutex); + + res = !!res; + + if (res == wl->sg_enabled) + goto out; + + wl->sg_enabled = res; + + if (wl->state == WL1271_STATE_OFF) + goto out; + + ret = wl1271_ps_elp_wakeup(wl, false); + if (ret < 0) + goto out; + + wl1271_acx_sg_enable(wl, wl->sg_enabled); + wl1271_ps_elp_sleep(wl); + + out: + mutex_unlock(&wl->mutex); + return count; +} + +static DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR, + wl1271_sysfs_show_bt_coex_state, + wl1271_sysfs_store_bt_coex_state); + int wl1271_register_hw(struct wl1271 *wl) { int ret; @@ -2073,6 +2135,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->band = IEEE80211_BAND_2GHZ; wl->vif = NULL; wl->flags = 0; + wl->sg_enabled = true; for (i = 0; i < ACX_TX_DESCRIPTORS; i++) wl->tx_frames[i] = NULL; @@ -2095,9 +2158,18 @@ struct ieee80211_hw *wl1271_alloc_hw(void) } dev_set_drvdata(&wl1271_device.dev, wl); + /* Create sysfs file to control bt coex state */ + ret = device_create_file(&wl1271_device.dev, &dev_attr_bt_coex_state); + if (ret < 0) { + wl1271_error("failed to create sysfs file bt_coex_state"); + goto err_platform; + } return hw; +err_platform: + platform_device_unregister(&wl1271_device); + err_hw: ieee80211_unregister_hw(wl->hw); -- cgit v1.2.3 From 12bd89499f22ec01bbff21fd04a347ee82726bf6 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 18 Mar 2010 12:26:33 +0200 Subject: wl1271: enable WMM Everything is ready now and we can enable WMM in wl1271. Signed-off-by: Kalle Valo Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 2 ++ drivers/net/wireless/wl12xx/wl1271_tx.h | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index abf9f22ee968..d21bfe29531d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -2091,6 +2091,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl) if (wl1271_11a_enabled()) wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; + wl->hw->queues = 4; + SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); return 0; diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 8b9f6b4f5652..5e6c27a57415 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h @@ -125,9 +125,6 @@ struct wl1271_tx_hw_res_if { static inline int wl1271_tx_get_queue(int queue) { - /* FIXME: use best effort until WMM is enabled */ - return CONF_TX_AC_BE; - switch (queue) { case 0: return CONF_TX_AC_VO; -- cgit v1.2.3 From 899e6e65c39990a76c17940625dbe6001f618734 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 18 Mar 2010 12:26:34 +0200 Subject: wl1271: get pspoll and nullfunc templates from mac80211 mac80211 now can create pspoll and nullfunc templates, better to use those. Signed-off-by: Kalle Valo Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 44 +++++++++++++++----------------- 1 file changed, 20 insertions(+), 24 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index d59b3830a6a5..3a615fac54e8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -776,41 +776,37 @@ static int wl1271_build_extended_rates(u8 *rates, u8 band) int wl1271_cmd_build_null_data(struct wl1271 *wl) { - struct wl12xx_null_data_template template; + struct sk_buff *skb; + int ret = 0; - if (!is_zero_ether_addr(wl->bssid)) { - memcpy(template.header.da, wl->bssid, ETH_ALEN); - memcpy(template.header.bssid, wl->bssid, ETH_ALEN); - } else { - memset(template.header.da, 0xff, ETH_ALEN); - memset(template.header.bssid, 0xff, ETH_ALEN); - } + skb = ieee80211_nullfunc_get(wl->hw, wl->vif); + if (!skb) + goto out; - memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); - template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC | - IEEE80211_FCTL_TODS); + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, skb->data, + skb->len); - return wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, &template, - sizeof(template)); +out: + dev_kfree_skb(skb); + return ret; } int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) { - struct wl12xx_ps_poll_template template; - - memcpy(template.bssid, wl->bssid, ETH_ALEN); - memcpy(template.ta, wl->mac_addr, ETH_ALEN); - - /* aid in PS-Poll has its two MSBs each set to 1 */ - template.aid = cpu_to_le16(1 << 15 | 1 << 14 | aid); + struct sk_buff *skb; + int ret = 0; - template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); + skb = ieee80211_pspoll_get(wl->hw, wl->vif); + if (!skb) + goto out; - return wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, &template, - sizeof(template)); + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, + skb->len); +out: + dev_kfree_skb(skb); + return ret; } int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len, -- cgit v1.2.3 From 818e3063a9546fcd826155dd47582a6e2f4d1c37 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 18 Mar 2010 12:26:35 +0200 Subject: wl1271: get probe request template from mac80211 If we get probe request from mac80211, we can remove two functions. Signed-off-by: Kalle Valo Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 137 ++++++----------------------- drivers/net/wireless/wl12xx/wl1271_cmd.h | 11 +-- drivers/net/wireless/wl12xx/wl1271_event.c | 2 + drivers/net/wireless/wl12xx/wl1271_main.c | 6 +- 4 files changed, 40 insertions(+), 116 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 3a615fac54e8..8364270b2d5c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -546,9 +546,9 @@ out: return ret; } -int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, - u8 active_scan, u8 high_prio, u8 band, - u8 probe_requests) +int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len, u8 active_scan, + u8 high_prio, u8 band, u8 probe_requests) { struct wl1271_cmd_trigger_scan_to *trigger = NULL; @@ -619,12 +619,13 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, params->params.num_channels = j; - if (len && ssid) { - params->params.ssid_len = len; - memcpy(params->params.ssid, ssid, len); + if (ssid_len && ssid) { + params->params.ssid_len = ssid_len; + memcpy(params->params.ssid, ssid, ssid_len); } - ret = wl1271_cmd_build_probe_req(wl, ssid, len, ieee_band); + ret = wl1271_cmd_build_probe_req(wl, ssid, ssid_len, + ie, ie_len, ieee_band); if (ret < 0) { wl1271_error("PROBE request template failed"); goto out; @@ -655,9 +656,9 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, wl->scan.active = active_scan; wl->scan.high_prio = high_prio; wl->scan.probe_requests = probe_requests; - if (len && ssid) { - wl->scan.ssid_len = len; - memcpy(wl->scan.ssid, ssid, len); + if (ssid_len && ssid) { + wl->scan.ssid_len = ssid_len; + memcpy(wl->scan.ssid, ssid, ssid_len); } else wl->scan.ssid_len = 0; } @@ -714,66 +715,6 @@ out: return ret; } -static int wl1271_build_basic_rates(u8 *rates, u8 band) -{ - u8 index = 0; - - if (band == IEEE80211_BAND_2GHZ) { - rates[index++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; - rates[index++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; - rates[index++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; - rates[index++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; - } else if (band == IEEE80211_BAND_5GHZ) { - rates[index++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; - rates[index++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; - rates[index++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; - } else { - wl1271_error("build_basic_rates invalid band: %d", band); - } - - return index; -} - -static int wl1271_build_extended_rates(u8 *rates, u8 band) -{ - u8 index = 0; - - if (band == IEEE80211_BAND_2GHZ) { - rates[index++] = IEEE80211_OFDM_RATE_6MB; - rates[index++] = IEEE80211_OFDM_RATE_9MB; - rates[index++] = IEEE80211_OFDM_RATE_12MB; - rates[index++] = IEEE80211_OFDM_RATE_18MB; - rates[index++] = IEEE80211_OFDM_RATE_24MB; - rates[index++] = IEEE80211_OFDM_RATE_36MB; - rates[index++] = IEEE80211_OFDM_RATE_48MB; - rates[index++] = IEEE80211_OFDM_RATE_54MB; - } else if (band == IEEE80211_BAND_5GHZ) { - rates[index++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; - rates[index++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; - rates[index++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; - rates[index++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; - rates[index++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; - rates[index++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; - } else { - wl1271_error("build_basic_rates invalid band: %d", band); - } - - return index; -} - int wl1271_cmd_build_null_data(struct wl1271 *wl) { struct sk_buff *skb; @@ -809,53 +750,31 @@ out: return ret; } -int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len, - u8 band) +int wl1271_cmd_build_probe_req(struct wl1271 *wl, + const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len, u8 band) { - struct wl12xx_probe_req_template template; - struct wl12xx_ie_rates *rates; - char *ptr; - u16 size; + struct sk_buff *skb; int ret; - ptr = (char *)&template; - size = sizeof(struct ieee80211_header); - - memset(template.header.da, 0xff, ETH_ALEN); - memset(template.header.bssid, 0xff, ETH_ALEN); - memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); - template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - - /* IEs */ - /* SSID */ - template.ssid.header.id = WLAN_EID_SSID; - template.ssid.header.len = ssid_len; - if (ssid_len && ssid) - memcpy(template.ssid.ssid, ssid, ssid_len); - size += sizeof(struct wl12xx_ie_header) + ssid_len; - ptr += size; - - /* Basic Rates */ - rates = (struct wl12xx_ie_rates *)ptr; - rates->header.id = WLAN_EID_SUPP_RATES; - rates->header.len = wl1271_build_basic_rates(rates->rates, band); - size += sizeof(struct wl12xx_ie_header) + rates->header.len; - ptr += sizeof(struct wl12xx_ie_header) + rates->header.len; - - /* Extended rates */ - rates = (struct wl12xx_ie_rates *)ptr; - rates->header.id = WLAN_EID_EXT_SUPP_RATES; - rates->header.len = wl1271_build_extended_rates(rates->rates, band); - size += sizeof(struct wl12xx_ie_header) + rates->header.len; - - wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size); + skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, + ie, ie_len); + if (!skb) { + ret = -ENOMEM; + goto out; + } + + wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); if (band == IEEE80211_BAND_2GHZ) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, - &template, size); + skb->data, skb->len); else ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, - &template, size); + skb->data, skb->len); + +out: + dev_kfree_skb(skb); return ret; } diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 4297205b8d6d..e936d3ace7b8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -41,15 +41,16 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, size_t len); -int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, - u8 active_scan, u8 high_prio, u8 band, - u8 probe_requests); +int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len, u8 active_scan, + u8 high_prio, u8 band, u8 probe_requests); int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, void *buf, size_t buf_len); int wl1271_cmd_build_null_data(struct wl1271 *wl); int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); -int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len, - u8 band); +int wl1271_cmd_build_probe_req(struct wl1271 *wl, + const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len, u8 band); int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, const u8 *addr, diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 5533519a1418..4d35af96c597 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -44,7 +44,9 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, * scanning as it checks that. */ clear_bit(WL1271_FLAG_SCANNING, &wl->flags); + /* FIXME: ie missing! */ wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, + NULL, 0, wl->scan.active, wl->scan.high_prio, WL1271_SCAN_BAND_5_GHZ, diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index d21bfe29531d..fbc42ceb39d8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1566,10 +1566,12 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, goto out; if (wl1271_11a_enabled()) - ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0, + ret = wl1271_cmd_scan(hw->priv, ssid, len, + req->ie, req->ie_len, 1, 0, WL1271_SCAN_BAND_DUAL, 3); else - ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0, + ret = wl1271_cmd_scan(hw->priv, ssid, len, + req->ie, req->ie_len, 1, 0, WL1271_SCAN_BAND_2_4_GHZ, 3); wl1271_ps_elp_sleep(wl); -- cgit v1.2.3 From 023e082609ba3225dbd5c33933a90156d2201d7f Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 18 Mar 2010 12:26:36 +0200 Subject: wl1271: create qos nullfunc template Needed for U-APSD. Signed-off-by: Kalle Valo Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 22 ++++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1271_cmd.h | 1 + 2 files changed, 23 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 8364270b2d5c..0cbb0e1e3d40 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "wl1271.h" #include "wl1271_reg.h" @@ -778,6 +779,27 @@ out: return ret; } +int wl1271_build_qos_null_data(struct wl1271 *wl) +{ + struct ieee80211_qos_hdr template; + + memset(&template, 0, sizeof(template)); + + memcpy(template.addr1, wl->bssid, ETH_ALEN); + memcpy(template.addr2, wl->mac_addr, ETH_ALEN); + memcpy(template.addr3, wl->bssid, ETH_ALEN); + + template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | + IEEE80211_STYPE_QOS_NULLFUNC | + IEEE80211_FCTL_TODS); + + /* FIXME: not sure what priority to use here */ + template.qos_ctrl = cpu_to_le16(0); + + return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, + sizeof(template)); +} + int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) { struct wl1271_cmd_set_keys *cmd; diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index e936d3ace7b8..6324bbf36843 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -51,6 +51,7 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); int wl1271_cmd_build_probe_req(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, u8 band); +int wl1271_build_qos_null_data(struct wl1271 *wl); int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, const u8 *addr, -- cgit v1.2.3 From 522ac25048676b2141d0560841654323339c0cbb Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 18 Mar 2010 12:26:37 +0200 Subject: wl1271: fix ps scheme in wl1271_op_conf_tx() Commit "wl1271: implement WMM" accidentally used CONF_PS_SCHEME_LEGACY_PSPOLL, but instead CONF_PS_SCHEME_LEGACY should be used as earlier. Signed-off-by: Kalle Valo Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index fbc42ceb39d8..2a2e5841a0e0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1801,7 +1801,7 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), CONF_CHANNEL_TYPE_EDCF, wl1271_tx_get_queue(queue), - CONF_PS_SCHEME_LEGACY_PSPOLL, + CONF_PS_SCHEME_LEGACY, CONF_ACK_POLICY_LEGACY, 0, 0); if (ret < 0) goto out_sleep; -- cgit v1.2.3 From 4695dc917d9ec7a38cb4f91fceb2b78aaec1f945 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 18 Mar 2010 12:26:38 +0200 Subject: wl1271: enable U-APSD wl1271 supports U-APSD similarly as wl1251, so let's enable it. Signed-off-by: Kalle Valo Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 2a2e5841a0e0..037a4f4036fd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1781,6 +1781,7 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { struct wl1271 *wl = hw->priv; + u8 ps_scheme; int ret; mutex_lock(&wl->mutex); @@ -1798,11 +1799,15 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, if (ret < 0) goto out_sleep; + if (params->uapsd) + ps_scheme = CONF_PS_SCHEME_UPSD_TRIGGER; + else + ps_scheme = CONF_PS_SCHEME_LEGACY; + ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), CONF_CHANNEL_TYPE_EDCF, wl1271_tx_get_queue(queue), - CONF_PS_SCHEME_LEGACY, - CONF_ACK_POLICY_LEGACY, 0, 0); + ps_scheme, CONF_ACK_POLICY_LEGACY, 0, 0); if (ret < 0) goto out_sleep; @@ -2083,6 +2088,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) IEEE80211_HW_NOISE_DBM | IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_SUPPORTS_UAPSD | IEEE80211_HW_HAS_RATE_CONTROL; wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | -- cgit v1.2.3 From 1b72aecd950c4c3cec2d66dbe5436c9e25a487b7 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Mar 2010 12:26:39 +0200 Subject: wl1271: Fix MAC address handling This patch fixes MAC address handling. To achieve this, firmware booting had to be delayed from the previous op_start to op_add_interface, which is the point when the driver gets to know the configured MAC address. As the wl1271 only supports one virtual interface, this even seems quite logical. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_boot.c | 8 ++ drivers/net/wireless/wl12xx/wl1271_main.c | 149 ++++++++++++------------------ 2 files changed, 68 insertions(+), 89 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index f88d52e87e82..41c6affbee29 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -228,6 +228,14 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) nvs_len = sizeof(wl->nvs->nvs); nvs_ptr = (u8 *)wl->nvs->nvs; + /* update current MAC address to NVS */ + nvs_ptr[11] = wl->mac_addr[0]; + nvs_ptr[10] = wl->mac_addr[1]; + nvs_ptr[6] = wl->mac_addr[2]; + nvs_ptr[5] = wl->mac_addr[3]; + nvs_ptr[4] = wl->mac_addr[4]; + nvs_ptr[3] = wl->mac_addr[5]; + /* * Layout before the actual NVS tables: * 1 byte : burst length. diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 037a4f4036fd..d8cb51410b2f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -570,40 +570,6 @@ out: return ret; } -static int wl1271_update_mac_addr(struct wl1271 *wl) -{ - int ret = 0; - u8 *nvs_ptr = (u8 *)wl->nvs->nvs; - - /* get mac address from the NVS */ - wl->mac_addr[0] = nvs_ptr[11]; - wl->mac_addr[1] = nvs_ptr[10]; - wl->mac_addr[2] = nvs_ptr[6]; - wl->mac_addr[3] = nvs_ptr[5]; - wl->mac_addr[4] = nvs_ptr[4]; - wl->mac_addr[5] = nvs_ptr[3]; - - /* FIXME: if it is a zero-address, we should bail out. Now, instead, - we randomize an address */ - if (is_zero_ether_addr(wl->mac_addr)) { - static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; - memcpy(wl->mac_addr, nokia_oui, 3); - get_random_bytes(wl->mac_addr + 3, 3); - - /* update this address to the NVS */ - nvs_ptr[11] = wl->mac_addr[0]; - nvs_ptr[10] = wl->mac_addr[1]; - nvs_ptr[6] = wl->mac_addr[2]; - nvs_ptr[5] = wl->mac_addr[3]; - nvs_ptr[4] = wl->mac_addr[4]; - nvs_ptr[3] = wl->mac_addr[5]; - } - - SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); - - return ret; -} - static int wl1271_fetch_nvs(struct wl1271 *wl) { const struct firmware *fw; @@ -633,8 +599,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); - ret = wl1271_update_mac_addr(wl); - out: release_firmware(fw); @@ -951,14 +915,59 @@ static struct notifier_block wl1271_dev_notifier = { static int wl1271_op_start(struct ieee80211_hw *hw) +{ + wl1271_debug(DEBUG_MAC80211, "mac80211 start"); + + /* + * We have to delay the booting of the hardware because + * we need to know the local MAC address before downloading and + * initializing the firmware. The MAC address cannot be changed + * after boot, and without the proper MAC address, the firmware + * will not function properly. + * + * The MAC address is first known when the corresponding interface + * is added. That is where we will initialize the hardware. + */ + + return 0; +} + +static void wl1271_op_stop(struct ieee80211_hw *hw) +{ + wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); +} + +static int wl1271_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; int retries = WL1271_BOOT_RETRIES; int ret = 0; - wl1271_debug(DEBUG_MAC80211, "mac80211 start"); + wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", + vif->type, vif->addr); mutex_lock(&wl->mutex); + if (wl->vif) { + ret = -EBUSY; + goto out; + } + + wl->vif = vif; + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + wl->bss_type = BSS_TYPE_STA_BSS; + break; + case NL80211_IFTYPE_ADHOC: + wl->bss_type = BSS_TYPE_IBSS; + break; + default: + ret = -EOPNOTSUPP; + goto out; + } + + memcpy(wl->mac_addr, vif->addr, ETH_ALEN); if (wl->state != WL1271_STATE_OFF) { wl1271_error("cannot start because not in off state: %d", @@ -1014,20 +1023,20 @@ out: return ret; } -static void wl1271_op_stop(struct ieee80211_hw *hw) +static void wl1271_op_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; int i; - wl1271_info("down"); + mutex_lock(&wl->mutex); + wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); - wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); + wl1271_info("down"); unregister_inetaddr_notifier(&wl1271_dev_notifier); list_del(&wl->list); - mutex_lock(&wl->mutex); - WARN_ON(wl->state != WL1271_STATE_ON); if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) { @@ -1070,6 +1079,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->sta_rate_set = 0; wl->flags = 0; + wl->vif = NULL; for (i = 0; i < NUM_TX_QUEUES; i++) wl->tx_blocks_freed[i] = 0; @@ -1078,53 +1088,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) mutex_unlock(&wl->mutex); } -static int wl1271_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct wl1271 *wl = hw->priv; - int ret = 0; - - wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", - vif->type, vif->addr); - - mutex_lock(&wl->mutex); - if (wl->vif) { - ret = -EBUSY; - goto out; - } - - wl->vif = vif; - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - wl->bss_type = BSS_TYPE_STA_BSS; - break; - case NL80211_IFTYPE_ADHOC: - wl->bss_type = BSS_TYPE_IBSS; - break; - default: - ret = -EOPNOTSUPP; - goto out; - } - - /* FIXME: what if conf->mac_addr changes? */ - -out: - mutex_unlock(&wl->mutex); - return ret; -} - -static void wl1271_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct wl1271 *wl = hw->priv; - - mutex_lock(&wl->mutex); - wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); - wl->vif = NULL; - mutex_unlock(&wl->mutex); -} - #if 0 static int wl1271_op_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -2114,6 +2077,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) struct ieee80211_hw *hw; struct wl1271 *wl; int i, ret; + static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); if (!hw) { @@ -2155,6 +2119,13 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->state = WL1271_STATE_OFF; mutex_init(&wl->mutex); + /* + * FIXME: we should use a zero MAC address here, but for now we + * generate a random Nokia address. + */ + memcpy(wl->mac_addr, nokia_oui, 3); + get_random_bytes(wl->mac_addr + 3, 3); + /* Apply default driver configuration. */ wl1271_conf_init(wl); -- cgit v1.2.3 From c76a0d6c9357d3e6ac32793b89a0a303966e1c4c Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Mar 2010 12:26:40 +0200 Subject: wl1271: Remove deprecated interface config function It's no longer needed. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 68 ------------------------------- 1 file changed, 68 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index d8cb51410b2f..688009ba94fa 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1088,73 +1088,6 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, mutex_unlock(&wl->mutex); } -#if 0 -static int wl1271_op_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct wl1271 *wl = hw->priv; - struct sk_buff *beacon; - int ret; - - wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %pM", - conf->bssid); - wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid, - conf->ssid_len); - - mutex_lock(&wl->mutex); - - ret = wl1271_ps_elp_wakeup(wl, false); - if (ret < 0) - goto out; - - if (memcmp(wl->bssid, conf->bssid, ETH_ALEN)) { - wl1271_debug(DEBUG_MAC80211, "bssid changed"); - - memcpy(wl->bssid, conf->bssid, ETH_ALEN); - - ret = wl1271_cmd_join(wl, wl->bss_type); - if (ret < 0) - goto out_sleep; - - ret = wl1271_cmd_build_null_data(wl); - if (ret < 0) - goto out_sleep; - } - - wl->ssid_len = conf->ssid_len; - if (wl->ssid_len) - memcpy(wl->ssid, conf->ssid, wl->ssid_len); - - if (conf->changed & IEEE80211_IFCC_BEACON) { - beacon = ieee80211_beacon_get(hw, vif); - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, - beacon->data, beacon->len); - - if (ret < 0) { - dev_kfree_skb(beacon); - goto out_sleep; - } - - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, - beacon->data, beacon->len); - - dev_kfree_skb(beacon); - - if (ret < 0) - goto out_sleep; - } - -out_sleep: - wl1271_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); - - return ret; -} -#endif - static int wl1271_join_channel(struct wl1271 *wl, int channel) { int ret = 0; @@ -1940,7 +1873,6 @@ static const struct ieee80211_ops wl1271_ops = { .add_interface = wl1271_op_add_interface, .remove_interface = wl1271_op_remove_interface, .config = wl1271_op_config, -/* .config_interface = wl1271_op_config_interface, */ .prepare_multicast = wl1271_op_prepare_multicast, .configure_filter = wl1271_op_configure_filter, .tx = wl1271_op_tx, -- cgit v1.2.3 From a3b8ea7554862e80a14b83233b37ddd2506d1d70 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Thu, 18 Mar 2010 12:26:41 +0200 Subject: wl1271: Added DEBUG_SDIO flag Added separate flag for SDIO debugging. Previously it has used DEBUG_SPI flag. This patch also includes couple indentation fixes. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 1 + drivers/net/wireless/wl12xx/wl1271_sdio.c | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 23a0c7e22939..4e608067253e 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -53,6 +53,7 @@ enum { DEBUG_MAC80211 = BIT(11), DEBUG_CMD = BIT(12), DEBUG_ACX = BIT(13), + DEBUG_SDIO = BIT(14), DEBUG_ALL = ~0, }; diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index d9183b64e723..0478919138d4 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c @@ -102,14 +102,14 @@ static void wl1271_sdio_init(struct wl1271 *wl) } static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed) + size_t len, bool fixed) { int ret; struct sdio_func *func = wl_to_func(wl); if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); - wl1271_debug(DEBUG_SPI, "sdio read 52 addr 0x%x, byte 0x%02x", + wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", addr, ((u8 *)buf)[0]); } else { if (fixed) @@ -117,9 +117,9 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, else ret = sdio_memcpy_fromio(func, buf, addr, len); - wl1271_debug(DEBUG_SPI, "sdio read 53 addr 0x%x, %d bytes", + wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %d bytes", addr, len); - wl1271_dump_ascii(DEBUG_SPI, "data: ", buf, len); + wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); } if (ret) @@ -128,19 +128,19 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, } static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed) + size_t len, bool fixed) { int ret; struct sdio_func *func = wl_to_func(wl); if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); - wl1271_debug(DEBUG_SPI, "sdio write 52 addr 0x%x, byte 0x%02x", + wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", addr, ((u8 *)buf)[0]); } else { - wl1271_debug(DEBUG_SPI, "sdio write 53 addr 0x%x, %d bytes", + wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %d bytes", addr, len); - wl1271_dump_ascii(DEBUG_SPI, "data: ", buf, len); + wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); if (fixed) ret = sdio_writesb(func, addr, buf, len); @@ -156,6 +156,10 @@ static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable) { struct sdio_func *func = wl_to_func(wl); + /* Let the SDIO stack handle wlan_enable control, so we + * keep host claimed while wlan is in use to keep wl1271 + * alive. + */ if (enable) { sdio_claim_host(func); sdio_enable_func(func); -- cgit v1.2.3 From 801a673ed1b36fc0e7dd92d8bb0090a4dc26a7d0 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Thu, 18 Mar 2010 12:26:42 +0200 Subject: wl1271: Removed duplicate code from module remove function. Removed duplicate code from wl1271_sdio module remove function. For freeing stuff in the remove function wl1271_free_hw function is now used. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_sdio.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index 0478919138d4..99b5b3f7a92c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c @@ -248,20 +248,9 @@ static void __devexit wl1271_remove(struct sdio_func *func) { struct wl1271 *wl = sdio_get_drvdata(func); - ieee80211_unregister_hw(wl->hw); - free_irq(wl->irq, wl); - kfree(wl->target_mem_map); - vfree(wl->fw); - wl->fw = NULL; - kfree(wl->nvs); - wl->nvs = NULL; - - kfree(wl->fw_status); - kfree(wl->tx_res_if); - - ieee80211_free_hw(wl->hw); + wl1271_free_hw(wl); } static struct sdio_driver wl1271_sdio_driver = { -- cgit v1.2.3 From 14b228a0d4234e4a2d4e683052da78760e8abf0f Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Mar 2010 12:26:43 +0200 Subject: wl1271: Update filters properly This patch adds support for the filters configured by the mac80211 stack. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 2 ++ drivers/net/wireless/wl12xx/wl1271_cmd.c | 9 ----- drivers/net/wireless/wl12xx/wl1271_main.c | 58 ++++++++++++++++++++++++++----- 3 files changed, 51 insertions(+), 18 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 4e608067253e..a0262b7723c3 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -54,6 +54,7 @@ enum { DEBUG_CMD = BIT(12), DEBUG_ACX = BIT(13), DEBUG_SDIO = BIT(14), + DEBUG_FILTERS = BIT(15), DEBUG_ALL = ~0, }; @@ -458,6 +459,7 @@ struct wl1271 { /* Default key (for WEP) */ u32 default_key; + unsigned int filters; unsigned int rx_config; unsigned int rx_filter; diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 0cbb0e1e3d40..035ddc06034c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -281,15 +281,6 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) join->rx_filter_options = cpu_to_le32(wl->rx_filter); join->bss_type = bss_type; - /* - * FIXME: disable temporarily all filters because after commit - * 9cef8737 "mac80211: fix managed mode BSSID handling" broke - * association. The filter logic needs to be implemented properly - * and once that is done, this hack can be removed. - */ - join->rx_config_options = cpu_to_le32(0); - join->rx_filter_options = cpu_to_le32(WL1271_DEFAULT_RX_FILTER); - if (wl->band == IEEE80211_BAND_2GHZ) join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_1MBPS | CONF_HW_BIT_RATE_2MBPS | diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 688009ba94fa..befc2e9b1842 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1080,6 +1080,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, wl->sta_rate_set = 0; wl->flags = 0; wl->vif = NULL; + wl->filters = 0; for (i = 0; i < NUM_TX_QUEUES; i++) wl->tx_blocks_freed[i] = 0; @@ -1088,6 +1089,40 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, mutex_unlock(&wl->mutex); } +static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) +{ + wl->rx_config = WL1271_DEFAULT_RX_CONFIG; + wl->rx_filter = WL1271_DEFAULT_RX_FILTER; + + /* combine requested filters with current filter config */ + filters = wl->filters | filters; + + wl1271_debug(DEBUG_FILTERS, "RX filters set: "); + + if (filters & FIF_PROMISC_IN_BSS) { + wl1271_debug(DEBUG_FILTERS, " - FIF_PROMISC_IN_BSS"); + wl->rx_config &= ~CFG_UNI_FILTER_EN; + wl->rx_config |= CFG_BSSID_FILTER_EN; + } + if (filters & FIF_BCN_PRBRESP_PROMISC) { + wl1271_debug(DEBUG_FILTERS, " - FIF_BCN_PRBRESP_PROMISC"); + wl->rx_config &= ~CFG_BSSID_FILTER_EN; + wl->rx_config &= ~CFG_SSID_FILTER_EN; + } + if (filters & FIF_OTHER_BSS) { + wl1271_debug(DEBUG_FILTERS, " - FIF_OTHER_BSS"); + wl->rx_config &= ~CFG_BSSID_FILTER_EN; + } + if (filters & FIF_CONTROL) { + wl1271_debug(DEBUG_FILTERS, " - FIF_CONTROL"); + wl->rx_filter |= CFG_RX_CTL_EN; + } + if (filters & FIF_FCSFAIL) { + wl1271_debug(DEBUG_FILTERS, " - FIF_FCSFAIL"); + wl->rx_filter |= CFG_RX_FCS_ERROR; + } +} + static int wl1271_join_channel(struct wl1271 *wl, int channel) { int ret = 0; @@ -1095,12 +1130,12 @@ static int wl1271_join_channel(struct wl1271 *wl, int channel) static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, 0xad, 0xbe, 0xef }; - /* disable mac filter, so we hear everything */ - wl->rx_config &= ~CFG_BSSID_FILTER_EN; - wl->channel = channel; memcpy(wl->bssid, dummy_bssid, ETH_ALEN); + /* pass through frames from all BSS */ + wl1271_configure_filters(wl, FIF_OTHER_BSS); + /* the dummy join is performed always with STATION BSS type to allow also ad-hoc mode to listen to the surroundings without sending any beacons yet. */ @@ -1126,7 +1161,9 @@ static int wl1271_unjoin_channel(struct wl1271 *wl) clear_bit(WL1271_FLAG_JOINED, &wl->flags); wl->channel = 0; memset(wl->bssid, 0, ETH_ALEN); - wl->rx_config = WL1271_DEFAULT_RX_CONFIG; + + /* stop filterting packets based on bssid */ + wl1271_configure_filters(wl, FIF_OTHER_BSS); out: return ret; @@ -1299,14 +1336,14 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, if (ret < 0) goto out_sleep; - kfree(fp); - - /* FIXME: We still need to set our filters properly */ - /* determine, whether supported filter values have changed */ if (changed == 0) goto out_sleep; + /* configure filters */ + wl->filters = *total; + wl1271_configure_filters(wl, 0); + /* apply configured filters */ ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); if (ret < 0) @@ -1317,6 +1354,7 @@ out_sleep: out: mutex_unlock(&wl->mutex); + kfree(fp); } static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, @@ -1580,7 +1618,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, * and enable the BSSID filter */ memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { - wl->rx_config |= CFG_BSSID_FILTER_EN; memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); ret = wl1271_cmd_build_null_data(wl); if (ret < 0) { @@ -1589,6 +1626,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, goto out_sleep; } + /* filter out all packets not from this BSSID */ + wl1271_configure_filters(wl, 0); + /* Need to update the BSSID (for filtering etc) */ do_join = true; } -- cgit v1.2.3 From a0cb7be4f4fa765dcfa82675811cd7e7713b5610 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Mar 2010 12:26:44 +0200 Subject: wl1271: Don't generate null func template for ad-hoc The null func template is not needed for ad-hoc, and it's generation is not supported for ad-hoc (mac80211 will WARN about it.) Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 26 +++++++++++++++++++------- drivers/net/wireless/wl12xx/wl1271_main.c | 6 ++---- 2 files changed, 21 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 035ddc06034c..d005729e0312 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -709,18 +709,30 @@ out: int wl1271_cmd_build_null_data(struct wl1271 *wl) { - struct sk_buff *skb; - int ret = 0; + struct sk_buff *skb = NULL; + int size; + void *ptr; + int ret = -ENOMEM; - skb = ieee80211_nullfunc_get(wl->hw, wl->vif); - if (!skb) - goto out; - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, skb->data, - skb->len); + if (wl->bss_type == BSS_TYPE_IBSS) { + size = sizeof(struct wl12xx_null_data_template); + ptr = NULL; + } else { + skb = ieee80211_nullfunc_get(wl->hw, wl->vif); + if (!skb) + goto out; + size = skb->len; + ptr = skb->data; + } + + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size); out: dev_kfree_skb(skb); + if (ret) + wl1271_warning("cmd buld null data failed %d", ret); + return ret; } diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index befc2e9b1842..6f6d366491a3 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1619,12 +1619,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, */ memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); + ret = wl1271_cmd_build_null_data(wl); - if (ret < 0) { - wl1271_warning("cmd buld null data failed %d", - ret); + if (ret < 0) goto out_sleep; - } /* filter out all packets not from this BSSID */ wl1271_configure_filters(wl, 0); -- cgit v1.2.3 From 2ea9fb3d79aac371e5bb0c4b0f5be7195e8fcd33 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Mar 2010 12:26:45 +0200 Subject: wl1271: Remove circular interlocking related to the inetaddr notifier chain Removing the wl1271 from the inet addr notifier chain sometimes causes the registered handler to be called - causing locking problems if the removing function is called from within the mutex. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 6f6d366491a3..0bebc456ec0d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1029,12 +1029,13 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, struct wl1271 *wl = hw->priv; int i; + unregister_inetaddr_notifier(&wl1271_dev_notifier); + mutex_lock(&wl->mutex); wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); wl1271_info("down"); - unregister_inetaddr_notifier(&wl1271_dev_notifier); list_del(&wl->list); WARN_ON(wl->state != WL1271_STATE_ON); -- cgit v1.2.3 From 3b56dd6a090e905eece023f690298013da4b6b67 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Thu, 18 Mar 2010 12:26:46 +0200 Subject: wl1271: Changed platform_device to be dynamically allocated Changed platform_device to be allocated dynamically from the wl1271_alloc_hw function. Also cleaned up error handling in the wl1271_alloc_hw function and module probe functions. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 1 + drivers/net/wireless/wl12xx/wl1271_io.h | 1 + drivers/net/wireless/wl12xx/wl1271_main.c | 42 ++++++++++++++++++++++++------- drivers/net/wireless/wl12xx/wl1271_sdio.c | 3 ++- drivers/net/wireless/wl12xx/wl1271_spi.c | 3 ++- 5 files changed, 39 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index a0262b7723c3..8f11506f8310 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -353,6 +353,7 @@ struct wl1271_if_operations { }; struct wl1271 { + struct platform_device *plat_dev; struct ieee80211_hw *hw; bool mac80211_registered; diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index 3ff88d971308..d8837ef0bb40 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h @@ -161,6 +161,7 @@ int wl1271_set_partition(struct wl1271 *wl, /* Functions from wl1271_main.c */ int wl1271_register_hw(struct wl1271 *wl); +void wl1271_unregister_hw(struct wl1271 *wl); int wl1271_init_ieee80211(struct wl1271 *wl); struct ieee80211_hw *wl1271_alloc_hw(void); int wl1271_free_hw(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 0bebc456ec0d..3daba6c0c77f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -2008,6 +2008,14 @@ int wl1271_register_hw(struct wl1271 *wl) } EXPORT_SYMBOL_GPL(wl1271_register_hw); +void wl1271_unregister_hw(struct wl1271 *wl) +{ + ieee80211_unregister_hw(wl->hw); + wl->mac80211_registered = false; + +} +EXPORT_SYMBOL_GPL(wl1271_unregister_hw); + int wl1271_init_ieee80211(struct wl1271 *wl) { /* The tx descriptor buffer and the TKIP space. */ @@ -2046,6 +2054,7 @@ EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); struct ieee80211_hw *wl1271_alloc_hw(void) { struct ieee80211_hw *hw; + struct platform_device *plat_dev = NULL; struct wl1271 *wl; int i, ret; static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; @@ -2054,15 +2063,25 @@ struct ieee80211_hw *wl1271_alloc_hw(void) if (!hw) { wl1271_error("could not alloc ieee80211_hw"); ret = -ENOMEM; - goto err; + goto err_hw_alloc; + } + + plat_dev = kmalloc(sizeof(wl1271_device), GFP_KERNEL); + if (!plat_dev) { + wl1271_error("could not allocate platform_device"); + ret = -ENOMEM; + goto err_plat_alloc; } + memcpy(plat_dev, &wl1271_device, sizeof(wl1271_device)); + wl = hw->priv; memset(wl, 0, sizeof(*wl)); INIT_LIST_HEAD(&wl->list); wl->hw = hw; + wl->plat_dev = plat_dev; skb_queue_head_init(&wl->tx_queue); @@ -2103,15 +2122,15 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl1271_debugfs_init(wl); /* Register platform device */ - ret = platform_device_register(&wl1271_device); + ret = platform_device_register(wl->plat_dev); if (ret) { wl1271_error("couldn't register platform device"); goto err_hw; } - dev_set_drvdata(&wl1271_device.dev, wl); + dev_set_drvdata(&wl->plat_dev->dev, wl); /* Create sysfs file to control bt coex state */ - ret = device_create_file(&wl1271_device.dev, &dev_attr_bt_coex_state); + ret = device_create_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); if (ret < 0) { wl1271_error("failed to create sysfs file bt_coex_state"); goto err_platform; @@ -2120,20 +2139,25 @@ struct ieee80211_hw *wl1271_alloc_hw(void) return hw; err_platform: - platform_device_unregister(&wl1271_device); + platform_device_unregister(wl->plat_dev); err_hw: - ieee80211_unregister_hw(wl->hw); + wl1271_debugfs_exit(wl); + kfree(plat_dev); + +err_plat_alloc: + ieee80211_free_hw(hw); + +err_hw_alloc: -err: return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(wl1271_alloc_hw); int wl1271_free_hw(struct wl1271 *wl) { - platform_device_unregister(&wl1271_device); - ieee80211_unregister_hw(wl->hw); + platform_device_unregister(wl->plat_dev); + kfree(wl->plat_dev); wl1271_debugfs_exit(wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index 99b5b3f7a92c..3c03de74dbfc 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c @@ -239,7 +239,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, out_free: - ieee80211_free_hw(hw); + wl1271_free_hw(wl); return ret; } @@ -250,6 +250,7 @@ static void __devexit wl1271_remove(struct sdio_func *func) free_irq(wl->irq, wl); + wl1271_unregister_hw(wl); wl1271_free_hw(wl); } diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 4c129c76c29d..f44b05a32b0d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c @@ -422,7 +422,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) free_irq(wl->irq, wl); out_free: - ieee80211_free_hw(hw); + wl1271_free_hw(wl); return ret; } @@ -433,6 +433,7 @@ static int __devexit wl1271_remove(struct spi_device *spi) free_irq(wl->irq, wl); + wl1271_unregister_hw(wl); wl1271_free_hw(wl); return 0; -- cgit v1.2.3 From 270020e85ec88a832d663fff4489523169641c2b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 18 Mar 2010 18:29:37 -0700 Subject: drivers/net/wireless: Use IW_HANDLER macro Convert direct uses of [ (foo - SIOCIWFIRST) , fn) Signed-off-by: Joe Perches Signed-off-by: John W. Linville --- drivers/net/wireless/ray_cs.c | 40 +++++++++++++++---------------- drivers/net/wireless/wl3501_cs.c | 52 ++++++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 46 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 84c530aa52f9..a42ee01e7b14 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -1531,28 +1531,28 @@ static iw_stats *ray_get_wireless_stats(struct net_device *dev) */ static const iw_handler ray_handler[] = { - [SIOCSIWCOMMIT - SIOCIWFIRST] = (iw_handler) ray_commit, - [SIOCGIWNAME - SIOCIWFIRST] = (iw_handler) ray_get_name, - [SIOCSIWFREQ - SIOCIWFIRST] = (iw_handler) ray_set_freq, - [SIOCGIWFREQ - SIOCIWFIRST] = (iw_handler) ray_get_freq, - [SIOCSIWMODE - SIOCIWFIRST] = (iw_handler) ray_set_mode, - [SIOCGIWMODE - SIOCIWFIRST] = (iw_handler) ray_get_mode, - [SIOCGIWRANGE - SIOCIWFIRST] = (iw_handler) ray_get_range, + IW_HANDLER(SIOCSIWCOMMIT, (iw_handler)ray_commit), + IW_HANDLER(SIOCGIWNAME, (iw_handler)ray_get_name), + IW_HANDLER(SIOCSIWFREQ, (iw_handler)ray_set_freq), + IW_HANDLER(SIOCGIWFREQ, (iw_handler)ray_get_freq), + IW_HANDLER(SIOCSIWMODE, (iw_handler)ray_set_mode), + IW_HANDLER(SIOCGIWMODE, (iw_handler)ray_get_mode), + IW_HANDLER(SIOCGIWRANGE, (iw_handler)ray_get_range), #ifdef WIRELESS_SPY - [SIOCSIWSPY - SIOCIWFIRST] = (iw_handler) iw_handler_set_spy, - [SIOCGIWSPY - SIOCIWFIRST] = (iw_handler) iw_handler_get_spy, - [SIOCSIWTHRSPY - SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy, - [SIOCGIWTHRSPY - SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy, + IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), + IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), + IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), + IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), #endif /* WIRELESS_SPY */ - [SIOCGIWAP - SIOCIWFIRST] = (iw_handler) ray_get_wap, - [SIOCSIWESSID - SIOCIWFIRST] = (iw_handler) ray_set_essid, - [SIOCGIWESSID - SIOCIWFIRST] = (iw_handler) ray_get_essid, - [SIOCSIWRATE - SIOCIWFIRST] = (iw_handler) ray_set_rate, - [SIOCGIWRATE - SIOCIWFIRST] = (iw_handler) ray_get_rate, - [SIOCSIWRTS - SIOCIWFIRST] = (iw_handler) ray_set_rts, - [SIOCGIWRTS - SIOCIWFIRST] = (iw_handler) ray_get_rts, - [SIOCSIWFRAG - SIOCIWFIRST] = (iw_handler) ray_set_frag, - [SIOCGIWFRAG - SIOCIWFIRST] = (iw_handler) ray_get_frag, + IW_HANDLER(SIOCGIWAP, (iw_handler)ray_get_wap), + IW_HANDLER(SIOCSIWESSID, (iw_handler)ray_set_essid), + IW_HANDLER(SIOCGIWESSID, (iw_handler)ray_get_essid), + IW_HANDLER(SIOCSIWRATE, (iw_handler)ray_set_rate), + IW_HANDLER(SIOCGIWRATE, (iw_handler)ray_get_rate), + IW_HANDLER(SIOCSIWRTS, (iw_handler)ray_set_rts), + IW_HANDLER(SIOCGIWRTS, (iw_handler)ray_get_rts), + IW_HANDLER(SIOCSIWFRAG, (iw_handler)ray_set_frag), + IW_HANDLER(SIOCGIWFRAG, (iw_handler)ray_get_frag), }; #define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */ diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 7b9621de239f..65dd502eab0d 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1834,32 +1834,32 @@ out: } static const iw_handler wl3501_handler[] = { - [SIOCGIWNAME - SIOCIWFIRST] = wl3501_get_name, - [SIOCSIWFREQ - SIOCIWFIRST] = wl3501_set_freq, - [SIOCGIWFREQ - SIOCIWFIRST] = wl3501_get_freq, - [SIOCSIWMODE - SIOCIWFIRST] = wl3501_set_mode, - [SIOCGIWMODE - SIOCIWFIRST] = wl3501_get_mode, - [SIOCGIWSENS - SIOCIWFIRST] = wl3501_get_sens, - [SIOCGIWRANGE - SIOCIWFIRST] = wl3501_get_range, - [SIOCSIWSPY - SIOCIWFIRST] = iw_handler_set_spy, - [SIOCGIWSPY - SIOCIWFIRST] = iw_handler_get_spy, - [SIOCSIWTHRSPY - SIOCIWFIRST] = iw_handler_set_thrspy, - [SIOCGIWTHRSPY - SIOCIWFIRST] = iw_handler_get_thrspy, - [SIOCSIWAP - SIOCIWFIRST] = wl3501_set_wap, - [SIOCGIWAP - SIOCIWFIRST] = wl3501_get_wap, - [SIOCSIWSCAN - SIOCIWFIRST] = wl3501_set_scan, - [SIOCGIWSCAN - SIOCIWFIRST] = wl3501_get_scan, - [SIOCSIWESSID - SIOCIWFIRST] = wl3501_set_essid, - [SIOCGIWESSID - SIOCIWFIRST] = wl3501_get_essid, - [SIOCSIWNICKN - SIOCIWFIRST] = wl3501_set_nick, - [SIOCGIWNICKN - SIOCIWFIRST] = wl3501_get_nick, - [SIOCGIWRATE - SIOCIWFIRST] = wl3501_get_rate, - [SIOCGIWRTS - SIOCIWFIRST] = wl3501_get_rts_threshold, - [SIOCGIWFRAG - SIOCIWFIRST] = wl3501_get_frag_threshold, - [SIOCGIWTXPOW - SIOCIWFIRST] = wl3501_get_txpow, - [SIOCGIWRETRY - SIOCIWFIRST] = wl3501_get_retry, - [SIOCGIWENCODE - SIOCIWFIRST] = wl3501_get_encode, - [SIOCGIWPOWER - SIOCIWFIRST] = wl3501_get_power, + IW_HANDLER(SIOCGIWNAME, wl3501_get_name), + IW_HANDLER(SIOCSIWFREQ, wl3501_set_freq), + IW_HANDLER(SIOCGIWFREQ, wl3501_get_freq), + IW_HANDLER(SIOCSIWMODE, wl3501_set_mode), + IW_HANDLER(SIOCGIWMODE, wl3501_get_mode), + IW_HANDLER(SIOCGIWSENS, wl3501_get_sens), + IW_HANDLER(SIOCGIWRANGE, wl3501_get_range), + IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), + IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), + IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), + IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), + IW_HANDLER(SIOCSIWAP, wl3501_set_wap), + IW_HANDLER(SIOCGIWAP, wl3501_get_wap), + IW_HANDLER(SIOCSIWSCAN, wl3501_set_scan), + IW_HANDLER(SIOCGIWSCAN, wl3501_get_scan), + IW_HANDLER(SIOCSIWESSID, wl3501_set_essid), + IW_HANDLER(SIOCGIWESSID, wl3501_get_essid), + IW_HANDLER(SIOCSIWNICKN, wl3501_set_nick), + IW_HANDLER(SIOCGIWNICKN, wl3501_get_nick), + IW_HANDLER(SIOCGIWRATE, wl3501_get_rate), + IW_HANDLER(SIOCGIWRTS, wl3501_get_rts_threshold), + IW_HANDLER(SIOCGIWFRAG, wl3501_get_frag_threshold), + IW_HANDLER(SIOCGIWTXPOW, wl3501_get_txpow), + IW_HANDLER(SIOCGIWRETRY, wl3501_get_retry), + IW_HANDLER(SIOCGIWENCODE, wl3501_get_encode), + IW_HANDLER(SIOCGIWPOWER, wl3501_get_power), }; static const struct iw_handler_def wl3501_handler_def = { -- cgit v1.2.3 From 56b632e8cc7a13cece861d890deb2843116f9372 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 18 Mar 2010 18:29:38 -0700 Subject: drivers/net: Remove local #define IW_IOCTL, use IW_HANDLER Use #define IW_HANDLER from wireless.h instead Signed-off-by: Joe Perches Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2200.c | 83 +++++++++++++++++----------------- 1 file changed, 41 insertions(+), 42 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index d6edc2440128..fcdbe8b00551 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -9980,49 +9980,48 @@ static int ipw_wx_sw_reset(struct net_device *dev, } /* Rebase the WE IOCTLs to zero for the handler array */ -#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] static iw_handler ipw_wx_handlers[] = { - IW_IOCTL(SIOCGIWNAME) = (iw_handler) cfg80211_wext_giwname, - IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq, - IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq, - IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode, - IW_IOCTL(SIOCGIWMODE) = ipw_wx_get_mode, - IW_IOCTL(SIOCSIWSENS) = ipw_wx_set_sens, - IW_IOCTL(SIOCGIWSENS) = ipw_wx_get_sens, - IW_IOCTL(SIOCGIWRANGE) = ipw_wx_get_range, - IW_IOCTL(SIOCSIWAP) = ipw_wx_set_wap, - IW_IOCTL(SIOCGIWAP) = ipw_wx_get_wap, - IW_IOCTL(SIOCSIWSCAN) = ipw_wx_set_scan, - IW_IOCTL(SIOCGIWSCAN) = ipw_wx_get_scan, - IW_IOCTL(SIOCSIWESSID) = ipw_wx_set_essid, - IW_IOCTL(SIOCGIWESSID) = ipw_wx_get_essid, - IW_IOCTL(SIOCSIWNICKN) = ipw_wx_set_nick, - IW_IOCTL(SIOCGIWNICKN) = ipw_wx_get_nick, - IW_IOCTL(SIOCSIWRATE) = ipw_wx_set_rate, - IW_IOCTL(SIOCGIWRATE) = ipw_wx_get_rate, - IW_IOCTL(SIOCSIWRTS) = ipw_wx_set_rts, - IW_IOCTL(SIOCGIWRTS) = ipw_wx_get_rts, - IW_IOCTL(SIOCSIWFRAG) = ipw_wx_set_frag, - IW_IOCTL(SIOCGIWFRAG) = ipw_wx_get_frag, - IW_IOCTL(SIOCSIWTXPOW) = ipw_wx_set_txpow, - IW_IOCTL(SIOCGIWTXPOW) = ipw_wx_get_txpow, - IW_IOCTL(SIOCSIWRETRY) = ipw_wx_set_retry, - IW_IOCTL(SIOCGIWRETRY) = ipw_wx_get_retry, - IW_IOCTL(SIOCSIWENCODE) = ipw_wx_set_encode, - IW_IOCTL(SIOCGIWENCODE) = ipw_wx_get_encode, - IW_IOCTL(SIOCSIWPOWER) = ipw_wx_set_power, - IW_IOCTL(SIOCGIWPOWER) = ipw_wx_get_power, - IW_IOCTL(SIOCSIWSPY) = iw_handler_set_spy, - IW_IOCTL(SIOCGIWSPY) = iw_handler_get_spy, - IW_IOCTL(SIOCSIWTHRSPY) = iw_handler_set_thrspy, - IW_IOCTL(SIOCGIWTHRSPY) = iw_handler_get_thrspy, - IW_IOCTL(SIOCSIWGENIE) = ipw_wx_set_genie, - IW_IOCTL(SIOCGIWGENIE) = ipw_wx_get_genie, - IW_IOCTL(SIOCSIWMLME) = ipw_wx_set_mlme, - IW_IOCTL(SIOCSIWAUTH) = ipw_wx_set_auth, - IW_IOCTL(SIOCGIWAUTH) = ipw_wx_get_auth, - IW_IOCTL(SIOCSIWENCODEEXT) = ipw_wx_set_encodeext, - IW_IOCTL(SIOCGIWENCODEEXT) = ipw_wx_get_encodeext, + IW_HANDLER(SIOCGIWNAME, (iw_handler)cfg80211_wext_giwname), + IW_HANDLER(SIOCSIWFREQ, ipw_wx_set_freq), + IW_HANDLER(SIOCGIWFREQ, ipw_wx_get_freq), + IW_HANDLER(SIOCSIWMODE, ipw_wx_set_mode), + IW_HANDLER(SIOCGIWMODE, ipw_wx_get_mode), + IW_HANDLER(SIOCSIWSENS, ipw_wx_set_sens), + IW_HANDLER(SIOCGIWSENS, ipw_wx_get_sens), + IW_HANDLER(SIOCGIWRANGE, ipw_wx_get_range), + IW_HANDLER(SIOCSIWAP, ipw_wx_set_wap), + IW_HANDLER(SIOCGIWAP, ipw_wx_get_wap), + IW_HANDLER(SIOCSIWSCAN, ipw_wx_set_scan), + IW_HANDLER(SIOCGIWSCAN, ipw_wx_get_scan), + IW_HANDLER(SIOCSIWESSID, ipw_wx_set_essid), + IW_HANDLER(SIOCGIWESSID, ipw_wx_get_essid), + IW_HANDLER(SIOCSIWNICKN, ipw_wx_set_nick), + IW_HANDLER(SIOCGIWNICKN, ipw_wx_get_nick), + IW_HANDLER(SIOCSIWRATE, ipw_wx_set_rate), + IW_HANDLER(SIOCGIWRATE, ipw_wx_get_rate), + IW_HANDLER(SIOCSIWRTS, ipw_wx_set_rts), + IW_HANDLER(SIOCGIWRTS, ipw_wx_get_rts), + IW_HANDLER(SIOCSIWFRAG, ipw_wx_set_frag), + IW_HANDLER(SIOCGIWFRAG, ipw_wx_get_frag), + IW_HANDLER(SIOCSIWTXPOW, ipw_wx_set_txpow), + IW_HANDLER(SIOCGIWTXPOW, ipw_wx_get_txpow), + IW_HANDLER(SIOCSIWRETRY, ipw_wx_set_retry), + IW_HANDLER(SIOCGIWRETRY, ipw_wx_get_retry), + IW_HANDLER(SIOCSIWENCODE, ipw_wx_set_encode), + IW_HANDLER(SIOCGIWENCODE, ipw_wx_get_encode), + IW_HANDLER(SIOCSIWPOWER, ipw_wx_set_power), + IW_HANDLER(SIOCGIWPOWER, ipw_wx_get_power), + IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), + IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), + IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), + IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), + IW_HANDLER(SIOCSIWGENIE, ipw_wx_set_genie), + IW_HANDLER(SIOCGIWGENIE, ipw_wx_get_genie), + IW_HANDLER(SIOCSIWMLME, ipw_wx_set_mlme), + IW_HANDLER(SIOCSIWAUTH, ipw_wx_set_auth), + IW_HANDLER(SIOCGIWAUTH, ipw_wx_get_auth), + IW_HANDLER(SIOCSIWENCODEEXT, ipw_wx_set_encodeext), + IW_HANDLER(SIOCGIWENCODEEXT, ipw_wx_get_encodeext), }; enum { -- cgit v1.2.3 From adc009e2e76b222006beb7f9df6d0aee051509d2 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 18 Mar 2010 18:29:39 -0700 Subject: orinoco/wext.c: Remove local #define STD_IW_HANDLER Use IW_HANDLER from wireless.h instead Signed-off-by: Joe Perches Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/wext.c | 94 ++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 48 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index 31ca241f7753..29f9bc03190a 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c @@ -1505,46 +1505,44 @@ static const struct iw_priv_args orinoco_privtab[] = { * Structures to export the Wireless Handlers */ -#define STD_IW_HANDLER(id, func) \ - [IW_IOCTL_IDX(id)] = (iw_handler) func static const iw_handler orinoco_handler[] = { - STD_IW_HANDLER(SIOCSIWCOMMIT, orinoco_ioctl_commit), - STD_IW_HANDLER(SIOCGIWNAME, cfg80211_wext_giwname), - STD_IW_HANDLER(SIOCSIWFREQ, orinoco_ioctl_setfreq), - STD_IW_HANDLER(SIOCGIWFREQ, orinoco_ioctl_getfreq), - STD_IW_HANDLER(SIOCSIWMODE, cfg80211_wext_siwmode), - STD_IW_HANDLER(SIOCGIWMODE, cfg80211_wext_giwmode), - STD_IW_HANDLER(SIOCSIWSENS, orinoco_ioctl_setsens), - STD_IW_HANDLER(SIOCGIWSENS, orinoco_ioctl_getsens), - STD_IW_HANDLER(SIOCGIWRANGE, cfg80211_wext_giwrange), - STD_IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), - STD_IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), - STD_IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), - STD_IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), - STD_IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap), - STD_IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap), - STD_IW_HANDLER(SIOCSIWSCAN, cfg80211_wext_siwscan), - STD_IW_HANDLER(SIOCGIWSCAN, cfg80211_wext_giwscan), - STD_IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid), - STD_IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid), - STD_IW_HANDLER(SIOCSIWRATE, orinoco_ioctl_setrate), - STD_IW_HANDLER(SIOCGIWRATE, orinoco_ioctl_getrate), - STD_IW_HANDLER(SIOCSIWRTS, orinoco_ioctl_setrts), - STD_IW_HANDLER(SIOCGIWRTS, orinoco_ioctl_getrts), - STD_IW_HANDLER(SIOCSIWFRAG, orinoco_ioctl_setfrag), - STD_IW_HANDLER(SIOCGIWFRAG, orinoco_ioctl_getfrag), - STD_IW_HANDLER(SIOCGIWRETRY, orinoco_ioctl_getretry), - STD_IW_HANDLER(SIOCSIWENCODE, orinoco_ioctl_setiwencode), - STD_IW_HANDLER(SIOCGIWENCODE, orinoco_ioctl_getiwencode), - STD_IW_HANDLER(SIOCSIWPOWER, orinoco_ioctl_setpower), - STD_IW_HANDLER(SIOCGIWPOWER, orinoco_ioctl_getpower), - STD_IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie), - STD_IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie), - STD_IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme), - STD_IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth), - STD_IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth), - STD_IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext), - STD_IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext), + IW_HANDLER(SIOCSIWCOMMIT, (iw_handler)orinoco_ioctl_commit), + IW_HANDLER(SIOCGIWNAME, (iw_handler)cfg80211_wext_giwname), + IW_HANDLER(SIOCSIWFREQ, (iw_handler)orinoco_ioctl_setfreq), + IW_HANDLER(SIOCGIWFREQ, (iw_handler)orinoco_ioctl_getfreq), + IW_HANDLER(SIOCSIWMODE, (iw_handler)cfg80211_wext_siwmode), + IW_HANDLER(SIOCGIWMODE, (iw_handler)cfg80211_wext_giwmode), + IW_HANDLER(SIOCSIWSENS, (iw_handler)orinoco_ioctl_setsens), + IW_HANDLER(SIOCGIWSENS, (iw_handler)orinoco_ioctl_getsens), + IW_HANDLER(SIOCGIWRANGE, (iw_handler)cfg80211_wext_giwrange), + IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), + IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), + IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), + IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), + IW_HANDLER(SIOCSIWAP, (iw_handler)orinoco_ioctl_setwap), + IW_HANDLER(SIOCGIWAP, (iw_handler)orinoco_ioctl_getwap), + IW_HANDLER(SIOCSIWSCAN, (iw_handler)cfg80211_wext_siwscan), + IW_HANDLER(SIOCGIWSCAN, (iw_handler)cfg80211_wext_giwscan), + IW_HANDLER(SIOCSIWESSID, (iw_handler)orinoco_ioctl_setessid), + IW_HANDLER(SIOCGIWESSID, (iw_handler)orinoco_ioctl_getessid), + IW_HANDLER(SIOCSIWRATE, (iw_handler)orinoco_ioctl_setrate), + IW_HANDLER(SIOCGIWRATE, (iw_handler)orinoco_ioctl_getrate), + IW_HANDLER(SIOCSIWRTS, (iw_handler)orinoco_ioctl_setrts), + IW_HANDLER(SIOCGIWRTS, (iw_handler)orinoco_ioctl_getrts), + IW_HANDLER(SIOCSIWFRAG, (iw_handler)orinoco_ioctl_setfrag), + IW_HANDLER(SIOCGIWFRAG, (iw_handler)orinoco_ioctl_getfrag), + IW_HANDLER(SIOCGIWRETRY, (iw_handler)orinoco_ioctl_getretry), + IW_HANDLER(SIOCSIWENCODE, (iw_handler)orinoco_ioctl_setiwencode), + IW_HANDLER(SIOCGIWENCODE, (iw_handler)orinoco_ioctl_getiwencode), + IW_HANDLER(SIOCSIWPOWER, (iw_handler)orinoco_ioctl_setpower), + IW_HANDLER(SIOCGIWPOWER, (iw_handler)orinoco_ioctl_getpower), + IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie), + IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie), + IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme), + IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth), + IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth), + IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext), + IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext), }; @@ -1552,15 +1550,15 @@ static const iw_handler orinoco_handler[] = { Added typecasting since we no longer use iwreq_data -- Moustafa */ static const iw_handler orinoco_private_handler[] = { - [0] = (iw_handler) orinoco_ioctl_reset, - [1] = (iw_handler) orinoco_ioctl_reset, - [2] = (iw_handler) orinoco_ioctl_setport3, - [3] = (iw_handler) orinoco_ioctl_getport3, - [4] = (iw_handler) orinoco_ioctl_setpreamble, - [5] = (iw_handler) orinoco_ioctl_getpreamble, - [6] = (iw_handler) orinoco_ioctl_setibssport, - [7] = (iw_handler) orinoco_ioctl_getibssport, - [9] = (iw_handler) orinoco_ioctl_getrid, + [0] = (iw_handler)orinoco_ioctl_reset, + [1] = (iw_handler)orinoco_ioctl_reset, + [2] = (iw_handler)orinoco_ioctl_setport3, + [3] = (iw_handler)orinoco_ioctl_getport3, + [4] = (iw_handler)orinoco_ioctl_setpreamble, + [5] = (iw_handler)orinoco_ioctl_getpreamble, + [6] = (iw_handler)orinoco_ioctl_setibssport, + [7] = (iw_handler)orinoco_ioctl_getibssport, + [9] = (iw_handler)orinoco_ioctl_getrid, }; const struct iw_handler_def orinoco_handler_def = { -- cgit v1.2.3 From 43ead78ac48b75aaf47de96fcf10cbf5962f32a6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 18 Mar 2010 18:29:40 -0700 Subject: drivers/net/wireless/ray_cs.c: Use iw_handler function prototypes Change local functions that are cast to iw_handler to the more standard use with "union iwreq_data *wrqu" so the iw_handler array no longer needs the casts. Signed-off-by: Joe Perches Signed-off-by: John W. Linville --- drivers/net/wireless/ray_cs.c | 204 +++++++++++++++++++----------------------- 1 file changed, 93 insertions(+), 111 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index a42ee01e7b14..4f5bdb528ef7 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -1113,10 +1113,10 @@ static const struct ethtool_ops netdev_ethtool_ops = { /* * Wireless Handler : get protocol name */ -static int ray_get_name(struct net_device *dev, - struct iw_request_info *info, char *cwrq, char *extra) +static int ray_get_name(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { - strcpy(cwrq, "IEEE 802.11-FH"); + strcpy(wrqu->name, "IEEE 802.11-FH"); return 0; } @@ -1124,9 +1124,8 @@ static int ray_get_name(struct net_device *dev, /* * Wireless Handler : set frequency */ -static int ray_set_freq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *fwrq, char *extra) +static int ray_set_freq(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { ray_dev_t *local = netdev_priv(dev); int err = -EINPROGRESS; /* Call commit handler */ @@ -1136,10 +1135,10 @@ static int ray_set_freq(struct net_device *dev, return -EBUSY; /* Setting by channel number */ - if ((fwrq->m > USA_HOP_MOD) || (fwrq->e > 0)) + if ((wrqu->freq.m > USA_HOP_MOD) || (wrqu->freq.e > 0)) err = -EOPNOTSUPP; else - local->sparm.b5.a_hop_pattern = fwrq->m; + local->sparm.b5.a_hop_pattern = wrqu->freq.m; return err; } @@ -1148,14 +1147,13 @@ static int ray_set_freq(struct net_device *dev, /* * Wireless Handler : get frequency */ -static int ray_get_freq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *fwrq, char *extra) +static int ray_get_freq(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { ray_dev_t *local = netdev_priv(dev); - fwrq->m = local->sparm.b5.a_hop_pattern; - fwrq->e = 0; + wrqu->freq.m = local->sparm.b5.a_hop_pattern; + wrqu->freq.e = 0; return 0; } @@ -1163,9 +1161,8 @@ static int ray_get_freq(struct net_device *dev, /* * Wireless Handler : set ESSID */ -static int ray_set_essid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, char *extra) +static int ray_set_essid(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { ray_dev_t *local = netdev_priv(dev); @@ -1174,19 +1171,17 @@ static int ray_set_essid(struct net_device *dev, return -EBUSY; /* Check if we asked for `any' */ - if (dwrq->flags == 0) { + if (wrqu->essid.flags == 0) /* Corey : can you do that ? */ return -EOPNOTSUPP; - } else { - /* Check the size of the string */ - if (dwrq->length > IW_ESSID_MAX_SIZE) { - return -E2BIG; - } - /* Set the ESSID in the card */ - memset(local->sparm.b5.a_current_ess_id, 0, IW_ESSID_MAX_SIZE); - memcpy(local->sparm.b5.a_current_ess_id, extra, dwrq->length); - } + /* Check the size of the string */ + if (wrqu->essid.length > IW_ESSID_MAX_SIZE) + return -E2BIG; + + /* Set the ESSID in the card */ + memset(local->sparm.b5.a_current_ess_id, 0, IW_ESSID_MAX_SIZE); + memcpy(local->sparm.b5.a_current_ess_id, extra, wrqu->essid.length); return -EINPROGRESS; /* Call commit handler */ } @@ -1195,9 +1190,8 @@ static int ray_set_essid(struct net_device *dev, /* * Wireless Handler : get ESSID */ -static int ray_get_essid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, char *extra) +static int ray_get_essid(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { ray_dev_t *local = netdev_priv(dev); @@ -1205,8 +1199,8 @@ static int ray_get_essid(struct net_device *dev, memcpy(extra, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE); /* Push it out ! */ - dwrq->length = strlen(extra); - dwrq->flags = 1; /* active */ + wrqu->essid.length = strlen(extra); + wrqu->essid.flags = 1; /* active */ return 0; } @@ -1215,14 +1209,13 @@ static int ray_get_essid(struct net_device *dev, /* * Wireless Handler : get AP address */ -static int ray_get_wap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *awrq, char *extra) +static int ray_get_wap(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { ray_dev_t *local = netdev_priv(dev); - memcpy(awrq->sa_data, local->bss_id, ETH_ALEN); - awrq->sa_family = ARPHRD_ETHER; + memcpy(wrqu->ap_addr.sa_data, local->bss_id, ETH_ALEN); + wrqu->ap_addr.sa_family = ARPHRD_ETHER; return 0; } @@ -1231,9 +1224,8 @@ static int ray_get_wap(struct net_device *dev, /* * Wireless Handler : set Bit-Rate */ -static int ray_set_rate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) +static int ray_set_rate(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { ray_dev_t *local = netdev_priv(dev); @@ -1242,15 +1234,15 @@ static int ray_set_rate(struct net_device *dev, return -EBUSY; /* Check if rate is in range */ - if ((vwrq->value != 1000000) && (vwrq->value != 2000000)) + if ((wrqu->bitrate.value != 1000000) && (wrqu->bitrate.value != 2000000)) return -EINVAL; /* Hack for 1.5 Mb/s instead of 2 Mb/s */ if ((local->fw_ver == 0x55) && /* Please check */ - (vwrq->value == 2000000)) + (wrqu->bitrate.value == 2000000)) local->net_default_tx_rate = 3; else - local->net_default_tx_rate = vwrq->value / 500000; + local->net_default_tx_rate = wrqu->bitrate.value / 500000; return 0; } @@ -1259,17 +1251,16 @@ static int ray_set_rate(struct net_device *dev, /* * Wireless Handler : get Bit-Rate */ -static int ray_get_rate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) +static int ray_get_rate(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { ray_dev_t *local = netdev_priv(dev); if (local->net_default_tx_rate == 3) - vwrq->value = 2000000; /* Hum... */ + wrqu->bitrate.value = 2000000; /* Hum... */ else - vwrq->value = local->net_default_tx_rate * 500000; - vwrq->fixed = 0; /* We are in auto mode */ + wrqu->bitrate.value = local->net_default_tx_rate * 500000; + wrqu->bitrate.fixed = 0; /* We are in auto mode */ return 0; } @@ -1278,19 +1269,18 @@ static int ray_get_rate(struct net_device *dev, /* * Wireless Handler : set RTS threshold */ -static int ray_set_rts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) +static int ray_set_rts(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { ray_dev_t *local = netdev_priv(dev); - int rthr = vwrq->value; + int rthr = wrqu->rts.value; /* Reject if card is already initialised */ if (local->card_status != CARD_AWAITING_PARAM) return -EBUSY; /* if(wrq->u.rts.fixed == 0) we should complain */ - if (vwrq->disabled) + if (wrqu->rts.disabled) rthr = 32767; else { if ((rthr < 0) || (rthr > 2347)) /* What's the max packet size ??? */ @@ -1306,16 +1296,15 @@ static int ray_set_rts(struct net_device *dev, /* * Wireless Handler : get RTS threshold */ -static int ray_get_rts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) +static int ray_get_rts(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { ray_dev_t *local = netdev_priv(dev); - vwrq->value = (local->sparm.b5.a_rts_threshold[0] << 8) + wrqu->rts.value = (local->sparm.b5.a_rts_threshold[0] << 8) + local->sparm.b5.a_rts_threshold[1]; - vwrq->disabled = (vwrq->value == 32767); - vwrq->fixed = 1; + wrqu->rts.disabled = (wrqu->rts.value == 32767); + wrqu->rts.fixed = 1; return 0; } @@ -1324,19 +1313,18 @@ static int ray_get_rts(struct net_device *dev, /* * Wireless Handler : set Fragmentation threshold */ -static int ray_set_frag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) +static int ray_set_frag(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { ray_dev_t *local = netdev_priv(dev); - int fthr = vwrq->value; + int fthr = wrqu->frag.value; /* Reject if card is already initialised */ if (local->card_status != CARD_AWAITING_PARAM) return -EBUSY; /* if(wrq->u.frag.fixed == 0) should complain */ - if (vwrq->disabled) + if (wrqu->frag.disabled) fthr = 32767; else { if ((fthr < 256) || (fthr > 2347)) /* To check out ! */ @@ -1352,16 +1340,15 @@ static int ray_set_frag(struct net_device *dev, /* * Wireless Handler : get Fragmentation threshold */ -static int ray_get_frag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) +static int ray_get_frag(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { ray_dev_t *local = netdev_priv(dev); - vwrq->value = (local->sparm.b5.a_frag_threshold[0] << 8) + wrqu->frag.value = (local->sparm.b5.a_frag_threshold[0] << 8) + local->sparm.b5.a_frag_threshold[1]; - vwrq->disabled = (vwrq->value == 32767); - vwrq->fixed = 1; + wrqu->frag.disabled = (wrqu->frag.value == 32767); + wrqu->frag.fixed = 1; return 0; } @@ -1370,8 +1357,8 @@ static int ray_get_frag(struct net_device *dev, /* * Wireless Handler : set Mode of Operation */ -static int ray_set_mode(struct net_device *dev, - struct iw_request_info *info, __u32 *uwrq, char *extra) +static int ray_set_mode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { ray_dev_t *local = netdev_priv(dev); int err = -EINPROGRESS; /* Call commit handler */ @@ -1381,7 +1368,7 @@ static int ray_set_mode(struct net_device *dev, if (local->card_status != CARD_AWAITING_PARAM) return -EBUSY; - switch (*uwrq) { + switch (wrqu->mode) { case IW_MODE_ADHOC: card_mode = 0; /* Fall through */ @@ -1399,15 +1386,15 @@ static int ray_set_mode(struct net_device *dev, /* * Wireless Handler : get Mode of Operation */ -static int ray_get_mode(struct net_device *dev, - struct iw_request_info *info, __u32 *uwrq, char *extra) +static int ray_get_mode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { ray_dev_t *local = netdev_priv(dev); if (local->sparm.b5.a_network_type) - *uwrq = IW_MODE_INFRA; + wrqu->mode = IW_MODE_INFRA; else - *uwrq = IW_MODE_ADHOC; + wrqu->mode = IW_MODE_ADHOC; return 0; } @@ -1416,16 +1403,15 @@ static int ray_get_mode(struct net_device *dev, /* * Wireless Handler : get range info */ -static int ray_get_range(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, char *extra) +static int ray_get_range(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct iw_range *range = (struct iw_range *)extra; - memset((char *)range, 0, sizeof(struct iw_range)); + memset(range, 0, sizeof(struct iw_range)); /* Set the length (very important for backward compatibility) */ - dwrq->length = sizeof(struct iw_range); + wrqu->data.length = sizeof(struct iw_range); /* Set the Wireless Extension versions */ range->we_version_compiled = WIRELESS_EXT; @@ -1448,8 +1434,7 @@ static int ray_get_range(struct net_device *dev, /* * Wireless Private Handler : set framing mode */ -static int ray_set_framing(struct net_device *dev, - struct iw_request_info *info, +static int ray_set_framing(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { translate = *(extra); /* Set framing mode */ @@ -1461,8 +1446,7 @@ static int ray_set_framing(struct net_device *dev, /* * Wireless Private Handler : get framing mode */ -static int ray_get_framing(struct net_device *dev, - struct iw_request_info *info, +static int ray_get_framing(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { *(extra) = translate; @@ -1474,8 +1458,7 @@ static int ray_get_framing(struct net_device *dev, /* * Wireless Private Handler : get country */ -static int ray_get_country(struct net_device *dev, - struct iw_request_info *info, +static int ray_get_country(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { *(extra) = country; @@ -1487,10 +1470,9 @@ static int ray_get_country(struct net_device *dev, /* * Commit handler : called after a bunch of SET operations */ -static int ray_commit(struct net_device *dev, struct iw_request_info *info, /* NULL */ - void *zwrq, /* NULL */ - char *extra) -{ /* NULL */ +static int ray_commit(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ return 0; } @@ -1531,28 +1513,28 @@ static iw_stats *ray_get_wireless_stats(struct net_device *dev) */ static const iw_handler ray_handler[] = { - IW_HANDLER(SIOCSIWCOMMIT, (iw_handler)ray_commit), - IW_HANDLER(SIOCGIWNAME, (iw_handler)ray_get_name), - IW_HANDLER(SIOCSIWFREQ, (iw_handler)ray_set_freq), - IW_HANDLER(SIOCGIWFREQ, (iw_handler)ray_get_freq), - IW_HANDLER(SIOCSIWMODE, (iw_handler)ray_set_mode), - IW_HANDLER(SIOCGIWMODE, (iw_handler)ray_get_mode), - IW_HANDLER(SIOCGIWRANGE, (iw_handler)ray_get_range), + IW_HANDLER(SIOCSIWCOMMIT, ray_commit), + IW_HANDLER(SIOCGIWNAME, ray_get_name), + IW_HANDLER(SIOCSIWFREQ, ray_set_freq), + IW_HANDLER(SIOCGIWFREQ, ray_get_freq), + IW_HANDLER(SIOCSIWMODE, ray_set_mode), + IW_HANDLER(SIOCGIWMODE, ray_get_mode), + IW_HANDLER(SIOCGIWRANGE, ray_get_range), #ifdef WIRELESS_SPY IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), #endif /* WIRELESS_SPY */ - IW_HANDLER(SIOCGIWAP, (iw_handler)ray_get_wap), - IW_HANDLER(SIOCSIWESSID, (iw_handler)ray_set_essid), - IW_HANDLER(SIOCGIWESSID, (iw_handler)ray_get_essid), - IW_HANDLER(SIOCSIWRATE, (iw_handler)ray_set_rate), - IW_HANDLER(SIOCGIWRATE, (iw_handler)ray_get_rate), - IW_HANDLER(SIOCSIWRTS, (iw_handler)ray_set_rts), - IW_HANDLER(SIOCGIWRTS, (iw_handler)ray_get_rts), - IW_HANDLER(SIOCSIWFRAG, (iw_handler)ray_set_frag), - IW_HANDLER(SIOCGIWFRAG, (iw_handler)ray_get_frag), + IW_HANDLER(SIOCGIWAP, ray_get_wap), + IW_HANDLER(SIOCSIWESSID, ray_set_essid), + IW_HANDLER(SIOCGIWESSID, ray_get_essid), + IW_HANDLER(SIOCSIWRATE, ray_set_rate), + IW_HANDLER(SIOCGIWRATE, ray_get_rate), + IW_HANDLER(SIOCSIWRTS, ray_set_rts), + IW_HANDLER(SIOCGIWRTS, ray_get_rts), + IW_HANDLER(SIOCSIWFRAG, ray_set_frag), + IW_HANDLER(SIOCGIWFRAG, ray_get_frag), }; #define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */ @@ -1560,9 +1542,9 @@ static const iw_handler ray_handler[] = { #define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3 /* Get country code */ static const iw_handler ray_private_handler[] = { - [0] = (iw_handler) ray_set_framing, - [1] = (iw_handler) ray_get_framing, - [3] = (iw_handler) ray_get_country, + [0] = ray_set_framing, + [1] = ray_get_framing, + [3] = ray_get_country, }; static const struct iw_priv_args ray_private_args[] = { -- cgit v1.2.3 From c5a079f46aabff026b2acaba0a2579a74c3c3731 Mon Sep 17 00:00:00 2001 From: Daniel Ngu Date: Tue, 23 Mar 2010 00:52:44 +1300 Subject: drivers/net/wireless/b43/main.c:4351: Fixed coding style WARNING: braces {} are not necessary for any arm of this statement Signed-off-by: Daniel Ngu Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 1521b1e78d21..14cf3bd7ea51 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4348,11 +4348,10 @@ static int b43_wireless_core_init(struct b43_wldev *dev) b43_set_phytxctl_defaults(dev); /* Minimum Contention Window */ - if (phy->type == B43_PHYTYPE_B) { + if (phy->type == B43_PHYTYPE_B) b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0x1F); - } else { + else b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0xF); - } /* Maximum Contention Window */ b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); -- cgit v1.2.3 From e1572c5eeca8ef87a250322364584458b2dadb35 Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 24 Mar 2010 13:42:13 +0530 Subject: ath9k_htc: Fix symbol collision with ath9k Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 22 +++++++++++----------- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 16 ++++++++-------- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 14 +++++++------- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 4 ++-- 4 files changed, 28 insertions(+), 28 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index ab09fe3416c7..777064945fca 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -41,7 +41,7 @@ ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) extern struct ieee80211_ops ath9k_htc_ops; -extern int modparam_nohwcrypt; +extern int htc_modparam_nohwcrypt; enum htc_phymode { HTC_MODE_AUTO = 0, @@ -408,8 +408,8 @@ void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, enum ath9k_tx_queue_subtype qtype); int get_hw_qnum(u16 queue, int *hwq_map); -int ath_txq_update(struct ath9k_htc_priv *priv, int qnum, - struct ath9k_tx_queue_info *qinfo); +int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, + struct ath9k_tx_queue_info *qinfo); int ath9k_rx_init(struct ath9k_htc_priv *priv); void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); @@ -427,15 +427,15 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); int ath9k_htc_resume(struct htc_target *htc_handle); #endif #ifdef CONFIG_ATH9K_HTC_DEBUGFS -int ath9k_debug_create_root(void); -void ath9k_debug_remove_root(void); -int ath9k_init_debug(struct ath_hw *ah); -void ath9k_exit_debug(struct ath_hw *ah); +int ath9k_htc_debug_create_root(void); +void ath9k_htc_debug_remove_root(void); +int ath9k_htc_init_debug(struct ath_hw *ah); +void ath9k_htc_exit_debug(struct ath_hw *ah); #else -static inline int ath9k_debug_create_root(void) { return 0; }; -static inline void ath9k_debug_remove_root(void) {}; -static inline int ath9k_init_debug(struct ath_hw *ah) { return 0; }; -static inline void ath9k_exit_debug(struct ath_hw *ah) {}; +static inline int ath9k_htc_debug_create_root(void) { return 0; }; +static inline void ath9k_htc_debug_remove_root(void) {}; +static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; +static inline void ath9k_htc_exit_debug(struct ath_hw *ah) {}; #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ #endif /* HTC_H */ diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index a653dec140b9..10c87605d2c4 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -24,8 +24,8 @@ static unsigned int ath9k_debug = ATH_DBG_DEFAULT; module_param_named(debug, ath9k_debug, uint, 0); MODULE_PARM_DESC(debug, "Debugging mask"); -int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); +int htc_modparam_nohwcrypt; +module_param_named(nohwcrypt, htc_modparam_nohwcrypt, int, 0444); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); #define CHAN2G(_freq, _idx) { \ @@ -93,7 +93,7 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) { - ath9k_exit_debug(priv->ah); + ath9k_htc_exit_debug(priv->ah); ath9k_hw_deinit(priv->ah); tasklet_kill(&priv->wmi_tasklet); tasklet_kill(&priv->rx_tasklet); @@ -474,7 +474,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) goto err_hw; } - ret = ath9k_init_debug(ah); + ret = ath9k_htc_init_debug(ah); if (ret) { ath_print(common, ATH_DBG_FATAL, "Unable to create debugfs files\n"); @@ -492,7 +492,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) return 0; err_queues: - ath9k_exit_debug(ah); + ath9k_htc_exit_debug(ah); err_debug: ath9k_hw_deinit(ah); err_hw: @@ -678,7 +678,7 @@ static int __init ath9k_htc_init(void) { int error; - error = ath9k_debug_create_root(); + error = ath9k_htc_debug_create_root(); if (error < 0) { printk(KERN_ERR "ath9k_htc: Unable to create debugfs root: %d\n", @@ -698,7 +698,7 @@ static int __init ath9k_htc_init(void) return 0; err_usb: - ath9k_debug_remove_root(); + ath9k_htc_debug_remove_root(); err_dbg: return error; } @@ -707,7 +707,7 @@ module_init(ath9k_htc_init); static void __exit ath9k_htc_exit(void) { ath9k_hif_usb_exit(); - ath9k_debug_remove_root(); + ath9k_htc_debug_remove_root(); printk(KERN_INFO "ath9k_htc: Driver unloaded\n"); } module_exit(ath9k_htc_exit); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 3184a2ac7b88..20a2c1341e20 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -595,7 +595,7 @@ static const struct file_operations fops_recv = { .owner = THIS_MODULE }; -int ath9k_init_debug(struct ath_hw *ah) +int ath9k_htc_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; @@ -630,11 +630,11 @@ int ath9k_init_debug(struct ath_hw *ah) return 0; err: - ath9k_exit_debug(ah); + ath9k_htc_exit_debug(ah); return -ENOMEM; } -void ath9k_exit_debug(struct ath_hw *ah) +void ath9k_htc_exit_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; @@ -645,7 +645,7 @@ void ath9k_exit_debug(struct ath_hw *ah) debugfs_remove(priv->debug.debugfs_phy); } -int ath9k_debug_create_root(void) +int ath9k_htc_debug_create_root(void) { ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); if (!ath9k_debugfs_root) @@ -654,7 +654,7 @@ int ath9k_debug_create_root(void) return 0; } -void ath9k_debug_remove_root(void) +void ath9k_htc_debug_remove_root(void) { debugfs_remove(ath9k_debugfs_root); ath9k_debugfs_root = NULL; @@ -1358,7 +1358,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, queue, qnum, params->aifs, params->cw_min, params->cw_max, params->txop); - ret = ath_txq_update(priv, qnum, &qi); + ret = ath_htc_txq_update(priv, qnum, &qi); if (ret) ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); @@ -1377,7 +1377,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, struct ath_common *common = ath9k_hw_common(priv->ah); int ret = 0; - if (modparam_nohwcrypt) + if (htc_modparam_nohwcrypt) return -ENOSPC; mutex_lock(&priv->mutex); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index dba22d3f87c3..ac66cf0b2d53 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -36,8 +36,8 @@ int get_hw_qnum(u16 queue, int *hwq_map) } } -int ath_txq_update(struct ath9k_htc_priv *priv, int qnum, - struct ath9k_tx_queue_info *qinfo) +int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, + struct ath9k_tx_queue_info *qinfo) { struct ath_hw *ah = priv->ah; int error = 0; -- cgit v1.2.3 From 921ca03c8f8e982f27fc406bc301caf2196b99f7 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 25 Feb 2010 17:16:36 -0800 Subject: libertas: add auto auth mode feature Auto auth mode is enabled by default. If user doesn't specify the auth mode, while association driver will first try with open mode and then with shared key mode. If user specifies an auth mode, auto auth is disabled and driver will not try association with another auth mode. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 22 +++++++++++++++++++++- drivers/net/wireless/libertas/dev.h | 1 + drivers/net/wireless/libertas/main.c | 1 + drivers/net/wireless/libertas/wext.c | 4 ++++ 4 files changed, 27 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index f03d5e4e59c3..95d3d4c5e08b 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -31,6 +31,9 @@ u8 lbs_bg_rates[MAX_RATES] = 0x00, 0x00 }; +static int assoc_helper_wep_keys(struct lbs_private *priv, + struct assoc_request *assoc_req); + /** * @brief This function finds common rates between rates and card rates. * @@ -610,7 +613,7 @@ static int lbs_assoc_post(struct lbs_private *priv, if (status_code) { lbs_mac_event_disconnected(priv); - ret = -1; + ret = status_code; goto done; } @@ -813,7 +816,24 @@ static int lbs_try_associate(struct lbs_private *priv, goto out; ret = lbs_associate(priv, assoc_req, CMD_802_11_ASSOCIATE); + /* If the association fails with current auth mode, let's + * try by changing the auth mode + */ + if ((priv->authtype_auto) && + (ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) && + (assoc_req->secinfo.wep_enabled) && + (priv->connect_status != LBS_CONNECTED)) { + if (priv->secinfo.auth_mode == IW_AUTH_ALG_OPEN_SYSTEM) + priv->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; + else + priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; + if (!assoc_helper_wep_keys(priv, assoc_req)) + ret = lbs_associate(priv, assoc_req, + CMD_802_11_ASSOCIATE); + } + if (ret) + ret = -1; out: lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); return ret; diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 6977ee820214..058d1720242e 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -133,6 +133,7 @@ struct lbs_private { u8 wpa_ie_len; u16 wep_tx_keyidx; struct enc_key wep_keys[4]; + u8 authtype_auto; /* Wake On LAN */ uint32_t wol_criteria; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 28a1c9d1627a..3c889f43d909 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -835,6 +835,7 @@ static int lbs_init_adapter(struct lbs_private *priv) priv->is_auto_deep_sleep_enabled = 0; priv->wakeup_dev_required = 0; init_waitqueue_head(&priv->ds_awake_q); + priv->authtype_auto = 1; mutex_init(&priv->lock); diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 71f88a08e090..aad6263dee6d 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -1440,8 +1440,10 @@ static int lbs_set_encode(struct net_device *dev, set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags); if (dwrq->flags & IW_ENCODE_RESTRICTED) { + priv->authtype_auto = 0; assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; } else if (dwrq->flags & IW_ENCODE_OPEN) { + priv->authtype_auto = 0; assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; } @@ -1620,8 +1622,10 @@ static int lbs_set_encodeext(struct net_device *dev, goto out; if (dwrq->flags & IW_ENCODE_RESTRICTED) { + priv->authtype_auto = 0; assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; } else if (dwrq->flags & IW_ENCODE_OPEN) { + priv->authtype_auto = 0; assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; } -- cgit v1.2.3 From 76232ebf898c4d5e657f2b663fbf7108bca80ded Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 24 Mar 2010 17:21:08 -0400 Subject: iwlwifi: fix build error for CONFIG_IWLAGN=n drivers/net/wireless/iwlwifi/iwl-rx.c: In function 'iwl_good_ack_health': drivers/net/wireless/iwlwifi/iwl-rx.c:647: error: 'struct iwl_priv' has no member named '_agn' Reported-by: Randy Dunlap Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-rx.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index b6a64d83718a..2fa30dfb7c59 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -621,6 +621,7 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, #define BA_TIMEOUT_CNT (5) #define BA_TIMEOUT_MAX (16) +#if defined(CONFIG_IWLAGN) || defined(CONFIG_IWLAGN_MODULE) /** * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries. * @@ -670,6 +671,7 @@ bool iwl_good_ack_health(struct iwl_priv *priv, return rc; } EXPORT_SYMBOL(iwl_good_ack_health); +#endif /** * iwl_good_plcp_health - checks for plcp error. -- cgit v1.2.3 From e184f67d39f681b1e8c9a43ff7001c3405c2bd7c Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Thu, 25 Mar 2010 11:14:52 -0700 Subject: Revert "iwlwifi: fix build error for CONFIG_IWLAGN=n" This reverts commit 76232ebf898c4d5e657f2b663fbf7108bca80ded. iwl_good_ack_health only applies to aggregation and thus only to iwlagn. We can thus move the function to iwlagn instead of modifying compile flags. This is done in following patch. Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-rx.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 2fa30dfb7c59..b6a64d83718a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -621,7 +621,6 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, #define BA_TIMEOUT_CNT (5) #define BA_TIMEOUT_MAX (16) -#if defined(CONFIG_IWLAGN) || defined(CONFIG_IWLAGN_MODULE) /** * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries. * @@ -671,7 +670,6 @@ bool iwl_good_ack_health(struct iwl_priv *priv, return rc; } EXPORT_SYMBOL(iwl_good_ack_health); -#endif /** * iwl_good_plcp_health - checks for plcp error. -- cgit v1.2.3 From 872c8ddcbec06995c1c7caa3e41c921290a8b6df Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 16 Mar 2010 10:46:31 -0700 Subject: iwlwifi: iwl_good_ack_health() only apply to AGN device iwl_good_ack_health() check for expected and actual ack count which only apply to aggregation mode. Move the function to iwlagn module. Reported-by: Chantry Xavier Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 54 +++++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-rx.c | 55 ---------------------------------- 3 files changed, 56 insertions(+), 55 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e69e6256a41b..680e897b92db 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1417,6 +1417,60 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) iwl_enable_interrupts(priv); } +/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ +#define ACK_CNT_RATIO (50) +#define BA_TIMEOUT_CNT (5) +#define BA_TIMEOUT_MAX (16) + +/** + * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries. + * + * When the ACK count ratio is 0 and aggregated BA timeout retries exceeding + * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal + * operation state. + */ +bool iwl_good_ack_health(struct iwl_priv *priv, + struct iwl_rx_packet *pkt) +{ + bool rc = true; + int actual_ack_cnt_delta, expected_ack_cnt_delta; + int ba_timeout_delta; + + actual_ack_cnt_delta = + le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - + le32_to_cpu(priv->statistics.tx.actual_ack_cnt); + expected_ack_cnt_delta = + le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) - + le32_to_cpu(priv->statistics.tx.expected_ack_cnt); + ba_timeout_delta = + le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) - + le32_to_cpu(priv->statistics.tx.agg.ba_timeout); + if ((priv->_agn.agg_tids_count > 0) && + (expected_ack_cnt_delta > 0) && + (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) + < ACK_CNT_RATIO) && + (ba_timeout_delta > BA_TIMEOUT_CNT)) { + IWL_DEBUG_RADIO(priv, "actual_ack_cnt delta = %d," + " expected_ack_cnt = %d\n", + actual_ack_cnt_delta, expected_ack_cnt_delta); + +#ifdef CONFIG_IWLWIFI_DEBUG + IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", + priv->delta_statistics.tx.rx_detected_cnt); + IWL_DEBUG_RADIO(priv, + "ack_or_ba_timeout_collision delta = %d\n", + priv->delta_statistics.tx. + ack_or_ba_timeout_collision); +#endif + IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", + ba_timeout_delta); + if (!actual_ack_cnt_delta && + (ba_timeout_delta >= BA_TIMEOUT_MAX)) + rc = false; + } + return rc; +} + /****************************************************************************** * diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 26eeb586ee00..42c291b12546 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -70,5 +70,7 @@ void iwl_disable_ict(struct iwl_priv *priv); int iwl_alloc_isr_ict(struct iwl_priv *priv); void iwl_free_isr_ict(struct iwl_priv *priv); irqreturn_t iwl_isr_ict(int irq, void *data); +bool iwl_good_ack_health(struct iwl_priv *priv, + struct iwl_rx_packet *pkt); #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index b6a64d83718a..de453f25f1c9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -616,61 +616,6 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, #define REG_RECALIB_PERIOD (60) -/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ -#define ACK_CNT_RATIO (50) -#define BA_TIMEOUT_CNT (5) -#define BA_TIMEOUT_MAX (16) - -/** - * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries. - * - * When the ACK count ratio is 0 and aggregated BA timeout retries exceeding - * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal - * operation state. - */ -bool iwl_good_ack_health(struct iwl_priv *priv, - struct iwl_rx_packet *pkt) -{ - bool rc = true; - int actual_ack_cnt_delta, expected_ack_cnt_delta; - int ba_timeout_delta; - - actual_ack_cnt_delta = - le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - - le32_to_cpu(priv->statistics.tx.actual_ack_cnt); - expected_ack_cnt_delta = - le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) - - le32_to_cpu(priv->statistics.tx.expected_ack_cnt); - ba_timeout_delta = - le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) - - le32_to_cpu(priv->statistics.tx.agg.ba_timeout); - if ((priv->_agn.agg_tids_count > 0) && - (expected_ack_cnt_delta > 0) && - (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) - < ACK_CNT_RATIO) && - (ba_timeout_delta > BA_TIMEOUT_CNT)) { - IWL_DEBUG_RADIO(priv, "actual_ack_cnt delta = %d," - " expected_ack_cnt = %d\n", - actual_ack_cnt_delta, expected_ack_cnt_delta); - -#ifdef CONFIG_IWLWIFI_DEBUG - IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", - priv->delta_statistics.tx.rx_detected_cnt); - IWL_DEBUG_RADIO(priv, - "ack_or_ba_timeout_collision delta = %d\n", - priv->delta_statistics.tx. - ack_or_ba_timeout_collision); -#endif - IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", - ba_timeout_delta); - if (!actual_ack_cnt_delta && - (ba_timeout_delta >= BA_TIMEOUT_MAX)) - rc = false; - } - return rc; -} -EXPORT_SYMBOL(iwl_good_ack_health); - /** * iwl_good_plcp_health - checks for plcp error. * -- cgit v1.2.3 From 792bc3cbe06cddabd865acc3122ee0415f854a11 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 16 Mar 2010 10:23:29 -0700 Subject: iwlwifi: move ucode loading related code to separated file Multiple iwlagn based devices shared the same ucode loading procedure. Move loading related code from iwl-5000.c to iwl-agn-ucode.c file. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/Makefile | 1 + drivers/net/wireless/iwlwifi/iwl-1000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 54 +----------------- drivers/net/wireless/iwlwifi/iwl-6000.c | 4 +- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 84 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 2 + 6 files changed, 92 insertions(+), 55 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-ucode.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index e31a5ccebea2..cc4fe20c45eb 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -10,6 +10,7 @@ CFLAGS_iwl-devtrace.o := -I$(src) # AGN obj-$(CONFIG_IWLAGN) += iwlagn.o iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o +iwlagn-objs += iwl-agn-ucode.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o iwlagn-$(CONFIG_IWL5000) += iwl-5000.o diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 9e392896005d..ad61464703cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -218,7 +218,7 @@ static struct iwl_lib_ops iwl1000_lib = { }; static const struct iwl_ops iwl1000_ops = { - .ucode = &iwl5000_ucode, + .ucode = &iwlagn_ucode, .lib = &iwl1000_lib, .hcmd = &iwl5000_hcmd, .utils = &iwl5000_hcmd_utils, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 2267cad49cbf..bbcb9c5dde6a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1348,45 +1348,6 @@ static int iwl5000_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) } } - -#define IWL5000_UCODE_GET(item) \ -static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\ - u32 api_ver) \ -{ \ - if (api_ver <= 2) \ - return le32_to_cpu(ucode->u.v1.item); \ - return le32_to_cpu(ucode->u.v2.item); \ -} - -static u32 iwl5000_ucode_get_header_size(u32 api_ver) -{ - if (api_ver <= 2) - return UCODE_HEADER_SIZE(1); - return UCODE_HEADER_SIZE(2); -} - -static u32 iwl5000_ucode_get_build(const struct iwl_ucode_header *ucode, - u32 api_ver) -{ - if (api_ver <= 2) - return 0; - return le32_to_cpu(ucode->u.v2.build); -} - -static u8 *iwl5000_ucode_get_data(const struct iwl_ucode_header *ucode, - u32 api_ver) -{ - if (api_ver <= 2) - return (u8 *) ucode->u.v1.data; - return (u8 *) ucode->u.v2.data; -} - -IWL5000_UCODE_GET(inst_size); -IWL5000_UCODE_GET(data_size); -IWL5000_UCODE_GET(init_size); -IWL5000_UCODE_GET(init_data_size); -IWL5000_UCODE_GET(boot_size); - static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) { struct iwl5000_channel_switch_cmd cmd; @@ -1435,17 +1396,6 @@ struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { .calc_rssi = iwl5000_calc_rssi, }; -struct iwl_ucode_ops iwl5000_ucode = { - .get_header_size = iwl5000_ucode_get_header_size, - .get_build = iwl5000_ucode_get_build, - .get_inst_size = iwl5000_ucode_get_inst_size, - .get_data_size = iwl5000_ucode_get_data_size, - .get_init_size = iwl5000_ucode_get_init_size, - .get_init_data_size = iwl5000_ucode_get_init_data_size, - .get_boot_size = iwl5000_ucode_get_boot_size, - .get_data = iwl5000_ucode_get_data, -}; - struct iwl_lib_ops iwl5000_lib = { .set_hw_params = iwl5000_hw_set_hw_params, .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, @@ -1562,7 +1512,7 @@ static struct iwl_lib_ops iwl5150_lib = { }; static const struct iwl_ops iwl5000_ops = { - .ucode = &iwl5000_ucode, + .ucode = &iwlagn_ucode, .lib = &iwl5000_lib, .hcmd = &iwl5000_hcmd, .utils = &iwl5000_hcmd_utils, @@ -1570,7 +1520,7 @@ static const struct iwl_ops iwl5000_ops = { }; static const struct iwl_ops iwl5150_ops = { - .ucode = &iwl5000_ucode, + .ucode = &iwlagn_ucode, .lib = &iwl5150_lib, .hcmd = &iwl5000_hcmd, .utils = &iwl5000_hcmd_utils, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index d75799946a7e..4026eb4e7faa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -284,7 +284,7 @@ static struct iwl_lib_ops iwl6000_lib = { }; static const struct iwl_ops iwl6000_ops = { - .ucode = &iwl5000_ucode, + .ucode = &iwlagn_ucode, .lib = &iwl6000_lib, .hcmd = &iwl5000_hcmd, .utils = &iwl5000_hcmd_utils, @@ -352,7 +352,7 @@ static struct iwl_lib_ops iwl6050_lib = { }; static const struct iwl_ops iwl6050_ops = { - .ucode = &iwl5000_ucode, + .ucode = &iwlagn_ucode, .lib = &iwl6050_lib, .hcmd = &iwl5000_hcmd, .utils = &iwl5000_hcmd_utils, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c new file mode 100644 index 000000000000..67f15c0d2a4a --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -0,0 +1,84 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#include +#include +#include + +#include "iwl-dev.h" +#include "iwl-core.h" + +#define IWL_UCODE_GET(item) \ +static u32 iwlagn_ucode_get_##item(const struct iwl_ucode_header *ucode,\ + u32 api_ver) \ +{ \ + if (api_ver <= 2) \ + return le32_to_cpu(ucode->u.v1.item); \ + return le32_to_cpu(ucode->u.v2.item); \ +} + +static u32 iwlagn_ucode_get_header_size(u32 api_ver) +{ + if (api_ver <= 2) + return UCODE_HEADER_SIZE(1); + return UCODE_HEADER_SIZE(2); +} + +static u32 iwlagn_ucode_get_build(const struct iwl_ucode_header *ucode, + u32 api_ver) +{ + if (api_ver <= 2) + return 0; + return le32_to_cpu(ucode->u.v2.build); +} + +static u8 *iwlagn_ucode_get_data(const struct iwl_ucode_header *ucode, + u32 api_ver) +{ + if (api_ver <= 2) + return (u8 *) ucode->u.v1.data; + return (u8 *) ucode->u.v2.data; +} + +IWL_UCODE_GET(inst_size); +IWL_UCODE_GET(data_size); +IWL_UCODE_GET(init_size); +IWL_UCODE_GET(init_data_size); +IWL_UCODE_GET(boot_size); + +struct iwl_ucode_ops iwlagn_ucode = { + .get_header_size = iwlagn_ucode_get_header_size, + .get_build = iwlagn_ucode_get_build, + .get_inst_size = iwlagn_ucode_get_inst_size, + .get_data_size = iwlagn_ucode_get_data_size, + .get_init_size = iwlagn_ucode_get_init_size, + .get_init_data_size = iwlagn_ucode_get_init_data_size, + .get_boot_size = iwlagn_ucode_get_boot_size, + .get_data = iwlagn_ucode_get_data, +}; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 42c291b12546..a266649a8bf5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -65,6 +65,8 @@ #include "iwl-dev.h" +extern struct iwl_ucode_ops iwlagn_ucode; + int iwl_reset_ict(struct iwl_priv *priv); void iwl_disable_ict(struct iwl_priv *priv); int iwl_alloc_isr_ict(struct iwl_priv *priv); -- cgit v1.2.3 From 81b8176eb8edac7d2135db2af03ab5fe0cb3b6f7 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 16 Mar 2010 10:23:30 -0700 Subject: iwlwifi: code cleanup for "load ucode" function Loading uCode functions are shared across multiple agn devices. Move those functions to iwl-agn-ucode.c file with other uCode related functions. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 103 +-------------------------- drivers/net/wireless/iwlwifi/iwl-6000.c | 4 +- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 102 ++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 3 + 5 files changed, 110 insertions(+), 104 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index ad61464703cb..283c4ed11709 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -173,7 +173,7 @@ static struct iwl_lib_ops iwl1000_lib = { .rx_handler_setup = iwl5000_rx_handler_setup, .setup_deferred_work = iwl5000_setup_deferred_work, .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, - .load_ucode = iwl5000_load_ucode, + .load_ucode = iwlagn_load_ucode, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index bbcb9c5dde6a..bea2f46ef26f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -423,105 +423,6 @@ static void iwl5000_rx_calib_complete(struct iwl_priv *priv, queue_work(priv->workqueue, &priv->restart); } -/* - * ucode - */ -static int iwl5000_load_section(struct iwl_priv *priv, const char *name, - struct fw_desc *image, u32 dst_addr) -{ - dma_addr_t phy_addr = image->p_addr; - u32 byte_cnt = image->len; - int ret; - - priv->ucode_write_complete = 0; - - iwl_write_direct32(priv, - FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); - - iwl_write_direct32(priv, - FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); - - iwl_write_direct32(priv, - FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), - phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); - - iwl_write_direct32(priv, - FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), - (iwl_get_dma_hi_addr(phy_addr) - << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); - - iwl_write_direct32(priv, - FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), - 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | - 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | - FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); - - iwl_write_direct32(priv, - FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | - FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); - - IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name); - ret = wait_event_interruptible_timeout(priv->wait_command_queue, - priv->ucode_write_complete, 5 * HZ); - if (ret == -ERESTARTSYS) { - IWL_ERR(priv, "Could not load the %s uCode section due " - "to interrupt\n", name); - return ret; - } - if (!ret) { - IWL_ERR(priv, "Could not load the %s uCode section\n", - name); - return -ETIMEDOUT; - } - - return 0; -} - -static int iwl5000_load_given_ucode(struct iwl_priv *priv, - struct fw_desc *inst_image, - struct fw_desc *data_image) -{ - int ret = 0; - - ret = iwl5000_load_section(priv, "INST", inst_image, - IWL50_RTC_INST_LOWER_BOUND); - if (ret) - return ret; - - return iwl5000_load_section(priv, "DATA", data_image, - IWL50_RTC_DATA_LOWER_BOUND); -} - -int iwl5000_load_ucode(struct iwl_priv *priv) -{ - int ret = 0; - - /* check whether init ucode should be loaded, or rather runtime ucode */ - if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) { - IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n"); - ret = iwl5000_load_given_ucode(priv, - &priv->ucode_init, &priv->ucode_init_data); - if (!ret) { - IWL_DEBUG_INFO(priv, "Init ucode load complete.\n"); - priv->ucode_type = UCODE_INIT; - } - } else { - IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. " - "Loading runtime ucode...\n"); - ret = iwl5000_load_given_ucode(priv, - &priv->ucode_code, &priv->ucode_data); - if (!ret) { - IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n"); - priv->ucode_type = UCODE_RT; - } - } - - return ret; -} - void iwl5000_init_alive_start(struct iwl_priv *priv) { int ret = 0; @@ -1413,7 +1314,7 @@ struct iwl_lib_ops iwl5000_lib = { .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, .dump_fh = iwl_dump_fh, - .load_ucode = iwl5000_load_ucode, + .load_ucode = iwlagn_load_ucode, .init_alive_start = iwl5000_init_alive_start, .alive_notify = iwl5000_alive_notify, .send_tx_power = iwl5000_send_tx_power, @@ -1470,7 +1371,7 @@ static struct iwl_lib_ops iwl5150_lib = { .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, - .load_ucode = iwl5000_load_ucode, + .load_ucode = iwlagn_load_ucode, .init_alive_start = iwl5000_init_alive_start, .alive_notify = iwl5000_alive_notify, .send_tx_power = iwl5000_send_tx_power, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 4026eb4e7faa..b7297177c054 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -237,7 +237,7 @@ static struct iwl_lib_ops iwl6000_lib = { .rx_handler_setup = iwl5000_rx_handler_setup, .setup_deferred_work = iwl5000_setup_deferred_work, .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, - .load_ucode = iwl5000_load_ucode, + .load_ucode = iwlagn_load_ucode, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, @@ -304,7 +304,7 @@ static struct iwl_lib_ops iwl6050_lib = { .rx_handler_setup = iwl5000_rx_handler_setup, .setup_deferred_work = iwl5000_setup_deferred_work, .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, - .load_ucode = iwl5000_load_ucode, + .load_ucode = iwlagn_load_ucode, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 67f15c0d2a4a..f57a4f8033f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -30,9 +30,111 @@ #include #include #include +#include #include "iwl-dev.h" #include "iwl-core.h" +#include "iwl-io.h" +#include "iwl-5000-hw.h" + +/* + * ucode + */ +static int iwlagn_load_section(struct iwl_priv *priv, const char *name, + struct fw_desc *image, u32 dst_addr) +{ + dma_addr_t phy_addr = image->p_addr; + u32 byte_cnt = image->len; + int ret; + + priv->ucode_write_complete = 0; + + iwl_write_direct32(priv, + FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); + + iwl_write_direct32(priv, + FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); + + iwl_write_direct32(priv, + FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), + phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); + + iwl_write_direct32(priv, + FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), + (iwl_get_dma_hi_addr(phy_addr) + << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); + + iwl_write_direct32(priv, + FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), + 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | + 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | + FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); + + iwl_write_direct32(priv, + FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | + FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); + + IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name); + ret = wait_event_interruptible_timeout(priv->wait_command_queue, + priv->ucode_write_complete, 5 * HZ); + if (ret == -ERESTARTSYS) { + IWL_ERR(priv, "Could not load the %s uCode section due " + "to interrupt\n", name); + return ret; + } + if (!ret) { + IWL_ERR(priv, "Could not load the %s uCode section\n", + name); + return -ETIMEDOUT; + } + + return 0; +} + +static int iwlagn_load_given_ucode(struct iwl_priv *priv, + struct fw_desc *inst_image, + struct fw_desc *data_image) +{ + int ret = 0; + + ret = iwlagn_load_section(priv, "INST", inst_image, + IWL50_RTC_INST_LOWER_BOUND); + if (ret) + return ret; + + return iwlagn_load_section(priv, "DATA", data_image, + IWL50_RTC_DATA_LOWER_BOUND); +} + +int iwlagn_load_ucode(struct iwl_priv *priv) +{ + int ret = 0; + + /* check whether init ucode should be loaded, or rather runtime ucode */ + if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) { + IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n"); + ret = iwlagn_load_given_ucode(priv, + &priv->ucode_init, &priv->ucode_init_data); + if (!ret) { + IWL_DEBUG_INFO(priv, "Init ucode load complete.\n"); + priv->ucode_type = UCODE_INIT; + } + } else { + IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. " + "Loading runtime ucode...\n"); + ret = iwlagn_load_given_ucode(priv, + &priv->ucode_code, &priv->ucode_data); + if (!ret) { + IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n"); + priv->ucode_type = UCODE_RT; + } + } + + return ret; +} #define IWL_UCODE_GET(item) \ static u32 iwlagn_ucode_get_##item(const struct iwl_ucode_header *ucode,\ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index a266649a8bf5..5af528dd3c63 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -75,4 +75,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data); bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt); +/* uCode */ +int iwlagn_load_ucode(struct iwl_priv *priv); + #endif /* __iwl_agn_h__ */ -- cgit v1.2.3 From 7dc77dba6a8bde512996824643da5669d73cbcdc Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 16 Mar 2010 10:23:31 -0700 Subject: iwlwifi: move hcmd related code to separate file Multiple iwlagn based devices shared the same hcmd related functions. Move from iwl-5000.c to iwl-agn-hcmd.c file. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/Makefile | 2 +- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 244 +------------------------ drivers/net/wireless/iwlwifi/iwl-6000.c | 8 +- drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 274 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 2 + 6 files changed, 287 insertions(+), 247 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index cc4fe20c45eb..46fad2d7226b 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -10,7 +10,7 @@ CFLAGS_iwl-devtrace.o := -I$(src) # AGN obj-$(CONFIG_IWLAGN) += iwlagn.o iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o -iwlagn-objs += iwl-agn-ucode.o +iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o iwlagn-$(CONFIG_IWL5000) += iwl-5000.o diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 283c4ed11709..67d8513cff3c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -220,8 +220,8 @@ static struct iwl_lib_ops iwl1000_lib = { static const struct iwl_ops iwl1000_ops = { .ucode = &iwlagn_ucode, .lib = &iwl1000_lib, - .hcmd = &iwl5000_hcmd, - .utils = &iwl5000_hcmd_utils, + .hcmd = &iwlagn_hcmd, + .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index bea2f46ef26f..8aa382e370f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -165,108 +165,6 @@ u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv) } -static void iwl5000_gain_computation(struct iwl_priv *priv, - u32 average_noise[NUM_RX_CHAINS], - u16 min_average_noise_antenna_i, - u32 min_average_noise, - u8 default_chain) -{ - int i; - s32 delta_g; - struct iwl_chain_noise_data *data = &priv->chain_noise_data; - - /* - * Find Gain Code for the chains based on "default chain" - */ - for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) { - if ((data->disconn_array[i])) { - data->delta_gain_code[i] = 0; - continue; - } - - delta_g = (priv->cfg->chain_noise_scale * - ((s32)average_noise[default_chain] - - (s32)average_noise[i])) / 1500; - - /* bound gain by 2 bits value max, 3rd bit is sign */ - data->delta_gain_code[i] = - min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); - - if (delta_g < 0) - /* - * set negative sign ... - * note to Intel developers: This is uCode API format, - * not the format of any internal device registers. - * Do not change this format for e.g. 6050 or similar - * devices. Change format only if more resolution - * (i.e. more than 2 bits magnitude) is needed. - */ - data->delta_gain_code[i] |= (1 << 2); - } - - IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n", - data->delta_gain_code[1], data->delta_gain_code[2]); - - if (!data->radio_write) { - struct iwl_calib_chain_noise_gain_cmd cmd; - - memset(&cmd, 0, sizeof(cmd)); - - cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; - cmd.hdr.first_group = 0; - cmd.hdr.groups_num = 1; - cmd.hdr.data_valid = 1; - cmd.delta_gain_1 = data->delta_gain_code[1]; - cmd.delta_gain_2 = data->delta_gain_code[2]; - iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, - sizeof(cmd), &cmd, NULL); - - data->radio_write = 1; - data->state = IWL_CHAIN_NOISE_CALIBRATED; - } - - data->chain_noise_a = 0; - data->chain_noise_b = 0; - data->chain_noise_c = 0; - data->chain_signal_a = 0; - data->chain_signal_b = 0; - data->chain_signal_c = 0; - data->beacon_count = 0; -} - -static void iwl5000_chain_noise_reset(struct iwl_priv *priv) -{ - struct iwl_chain_noise_data *data = &priv->chain_noise_data; - int ret; - - if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { - struct iwl_calib_chain_noise_reset_cmd cmd; - memset(&cmd, 0, sizeof(cmd)); - - cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; - cmd.hdr.first_group = 0; - cmd.hdr.groups_num = 1; - cmd.hdr.data_valid = 1; - ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, - sizeof(cmd), &cmd); - if (ret) - IWL_ERR(priv, - "Could not send REPLY_PHY_CALIBRATION_CMD\n"); - data->state = IWL_CHAIN_NOISE_ACCUMULATE; - IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); - } -} - -void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, - __le32 *tx_flags) -{ - if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || - (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) - *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; - else - *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; -} - static struct iwl_sensitivity_ranges iwl5000_sensitivity = { .min_nrg_cck = 95, .max_nrg_cck = 0, /* not used, set to 0 */ @@ -832,17 +730,6 @@ int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, return 0; } -u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) -{ - u16 size = (u16)sizeof(struct iwl_addsta_cmd); - struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data; - memcpy(addsta, cmd, size); - /* resrved in 5000 */ - addsta->rate_n_flags = cpu_to_le16(0); - return size; -} - - /* * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask * must be called under priv->lock and mac access @@ -1064,12 +951,6 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); } -/* Currently 5000 is the superset of everything */ -u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len) -{ - return len; -} - void iwl5000_setup_deferred_work(struct iwl_priv *priv) { /* in 5000 the tx power calibration is done in uCode */ @@ -1093,52 +974,6 @@ int iwl5000_hw_valid_rtc_data_addr(u32 addr) (addr < IWL50_RTC_DATA_UPPER_BOUND); } -static int iwl5000_send_rxon_assoc(struct iwl_priv *priv) -{ - int ret = 0; - struct iwl5000_rxon_assoc_cmd rxon_assoc; - const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; - const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; - - if ((rxon1->flags == rxon2->flags) && - (rxon1->filter_flags == rxon2->filter_flags) && - (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && - (rxon1->ofdm_ht_single_stream_basic_rates == - rxon2->ofdm_ht_single_stream_basic_rates) && - (rxon1->ofdm_ht_dual_stream_basic_rates == - rxon2->ofdm_ht_dual_stream_basic_rates) && - (rxon1->ofdm_ht_triple_stream_basic_rates == - rxon2->ofdm_ht_triple_stream_basic_rates) && - (rxon1->acquisition_data == rxon2->acquisition_data) && - (rxon1->rx_chain == rxon2->rx_chain) && - (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { - IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); - return 0; - } - - rxon_assoc.flags = priv->staging_rxon.flags; - rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; - rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; - rxon_assoc.reserved1 = 0; - rxon_assoc.reserved2 = 0; - rxon_assoc.reserved3 = 0; - rxon_assoc.ofdm_ht_single_stream_basic_rates = - priv->staging_rxon.ofdm_ht_single_stream_basic_rates; - rxon_assoc.ofdm_ht_dual_stream_basic_rates = - priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; - rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; - rxon_assoc.ofdm_ht_triple_stream_basic_rates = - priv->staging_rxon.ofdm_ht_triple_stream_basic_rates; - rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data; - - ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, - sizeof(rxon_assoc), &rxon_assoc, NULL); - if (ret) - return ret; - - return ret; -} int iwl5000_send_tx_power(struct iwl_priv *priv) { struct iwl5000_tx_power_dbm_cmd tx_power_cmd; @@ -1194,61 +1029,6 @@ static void iwl5150_temperature(struct iwl_priv *priv) iwl_tt_handler(priv); } -/* Calc max signal level (dBm) among 3 possible receivers */ -int iwl5000_calc_rssi(struct iwl_priv *priv, - struct iwl_rx_phy_res *rx_resp) -{ - /* data from PHY/DSP regarding signal strength, etc., - * contents are always there, not configurable by host - */ - struct iwl5000_non_cfg_phy *ncphy = - (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; - u32 val, rssi_a, rssi_b, rssi_c, max_rssi; - u8 agc; - - val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); - agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; - - /* Find max rssi among 3 possible receivers. - * These values are measured by the digital signal processor (DSP). - * They should stay fairly constant even as the signal strength varies, - * if the radio's automatic gain control (AGC) is working right. - * AGC value (see below) will provide the "interesting" info. - */ - val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); - rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; - rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; - val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); - rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; - - max_rssi = max_t(u32, rssi_a, rssi_b); - max_rssi = max_t(u32, max_rssi, rssi_c); - - IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", - rssi_a, rssi_b, rssi_c, max_rssi, agc); - - /* dBm = max_rssi dB - agc dB - constant. - * Higher AGC (higher radio gain) means lower signal. */ - return max_rssi - agc - IWL49_RSSI_OFFSET; -} - -static int iwl5000_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) -{ - struct iwl_tx_ant_config_cmd tx_ant_cmd = { - .valid = cpu_to_le32(valid_tx_ant), - }; - - if (IWL_UCODE_API(priv->ucode_ver) > 1) { - IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); - return iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, - sizeof(struct iwl_tx_ant_config_cmd), - &tx_ant_cmd); - } else { - IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n"); - return -EOPNOTSUPP; - } -} - static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) { struct iwl5000_channel_switch_cmd cmd; @@ -1281,22 +1061,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) return iwl_send_cmd_sync(priv, &hcmd); } -struct iwl_hcmd_ops iwl5000_hcmd = { - .rxon_assoc = iwl5000_send_rxon_assoc, - .commit_rxon = iwl_commit_rxon, - .set_rxon_chain = iwl_set_rxon_chain, - .set_tx_ant = iwl5000_send_tx_ant_config, -}; - -struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { - .get_hcmd_size = iwl5000_get_hcmd_size, - .build_addsta_hcmd = iwl5000_build_addsta_hcmd, - .gain_computation = iwl5000_gain_computation, - .chain_noise_reset = iwl5000_chain_noise_reset, - .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, - .calc_rssi = iwl5000_calc_rssi, -}; - struct iwl_lib_ops iwl5000_lib = { .set_hw_params = iwl5000_hw_set_hw_params, .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, @@ -1415,16 +1179,16 @@ static struct iwl_lib_ops iwl5150_lib = { static const struct iwl_ops iwl5000_ops = { .ucode = &iwlagn_ucode, .lib = &iwl5000_lib, - .hcmd = &iwl5000_hcmd, - .utils = &iwl5000_hcmd_utils, + .hcmd = &iwlagn_hcmd, + .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, }; static const struct iwl_ops iwl5150_ops = { .ucode = &iwlagn_ucode, .lib = &iwl5150_lib, - .hcmd = &iwl5000_hcmd, - .utils = &iwl5000_hcmd_utils, + .hcmd = &iwlagn_hcmd, + .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index b7297177c054..aff46b08703a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -286,8 +286,8 @@ static struct iwl_lib_ops iwl6000_lib = { static const struct iwl_ops iwl6000_ops = { .ucode = &iwlagn_ucode, .lib = &iwl6000_lib, - .hcmd = &iwl5000_hcmd, - .utils = &iwl5000_hcmd_utils, + .hcmd = &iwlagn_hcmd, + .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, }; @@ -354,8 +354,8 @@ static struct iwl_lib_ops iwl6050_lib = { static const struct iwl_ops iwl6050_ops = { .ucode = &iwlagn_ucode, .lib = &iwl6050_lib, - .hcmd = &iwl5000_hcmd, - .utils = &iwl5000_hcmd_utils, + .hcmd = &iwlagn_hcmd, + .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c new file mode 100644 index 000000000000..3ac010b1b1c5 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -0,0 +1,274 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#include +#include +#include +#include + +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-io.h" +#include "iwl-5000-hw.h" + +static int iwlagn_send_rxon_assoc(struct iwl_priv *priv) +{ + int ret = 0; + struct iwl5000_rxon_assoc_cmd rxon_assoc; + const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; + const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; + + if ((rxon1->flags == rxon2->flags) && + (rxon1->filter_flags == rxon2->filter_flags) && + (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && + (rxon1->ofdm_ht_single_stream_basic_rates == + rxon2->ofdm_ht_single_stream_basic_rates) && + (rxon1->ofdm_ht_dual_stream_basic_rates == + rxon2->ofdm_ht_dual_stream_basic_rates) && + (rxon1->ofdm_ht_triple_stream_basic_rates == + rxon2->ofdm_ht_triple_stream_basic_rates) && + (rxon1->acquisition_data == rxon2->acquisition_data) && + (rxon1->rx_chain == rxon2->rx_chain) && + (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { + IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); + return 0; + } + + rxon_assoc.flags = priv->staging_rxon.flags; + rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; + rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; + rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; + rxon_assoc.reserved1 = 0; + rxon_assoc.reserved2 = 0; + rxon_assoc.reserved3 = 0; + rxon_assoc.ofdm_ht_single_stream_basic_rates = + priv->staging_rxon.ofdm_ht_single_stream_basic_rates; + rxon_assoc.ofdm_ht_dual_stream_basic_rates = + priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; + rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; + rxon_assoc.ofdm_ht_triple_stream_basic_rates = + priv->staging_rxon.ofdm_ht_triple_stream_basic_rates; + rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data; + + ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, + sizeof(rxon_assoc), &rxon_assoc, NULL); + if (ret) + return ret; + + return ret; +} + +static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) +{ + struct iwl_tx_ant_config_cmd tx_ant_cmd = { + .valid = cpu_to_le32(valid_tx_ant), + }; + + if (IWL_UCODE_API(priv->ucode_ver) > 1) { + IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); + return iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, + sizeof(struct iwl_tx_ant_config_cmd), + &tx_ant_cmd); + } else { + IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n"); + return -EOPNOTSUPP; + } +} + +/* Currently this is the superset of everything */ +static u16 iwlagn_get_hcmd_size(u8 cmd_id, u16 len) +{ + return len; +} + +static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) +{ + u16 size = (u16)sizeof(struct iwl_addsta_cmd); + struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data; + memcpy(addsta, cmd, size); + /* resrved in 5000 */ + addsta->rate_n_flags = cpu_to_le16(0); + return size; +} + +static void iwlagn_gain_computation(struct iwl_priv *priv, + u32 average_noise[NUM_RX_CHAINS], + u16 min_average_noise_antenna_i, + u32 min_average_noise, + u8 default_chain) +{ + int i; + s32 delta_g; + struct iwl_chain_noise_data *data = &priv->chain_noise_data; + + /* + * Find Gain Code for the chains based on "default chain" + */ + for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) { + if ((data->disconn_array[i])) { + data->delta_gain_code[i] = 0; + continue; + } + + delta_g = (priv->cfg->chain_noise_scale * + ((s32)average_noise[default_chain] - + (s32)average_noise[i])) / 1500; + + /* bound gain by 2 bits value max, 3rd bit is sign */ + data->delta_gain_code[i] = + min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); + + if (delta_g < 0) + /* + * set negative sign ... + * note to Intel developers: This is uCode API format, + * not the format of any internal device registers. + * Do not change this format for e.g. 6050 or similar + * devices. Change format only if more resolution + * (i.e. more than 2 bits magnitude) is needed. + */ + data->delta_gain_code[i] |= (1 << 2); + } + + IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n", + data->delta_gain_code[1], data->delta_gain_code[2]); + + if (!data->radio_write) { + struct iwl_calib_chain_noise_gain_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + + cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; + cmd.hdr.first_group = 0; + cmd.hdr.groups_num = 1; + cmd.hdr.data_valid = 1; + cmd.delta_gain_1 = data->delta_gain_code[1]; + cmd.delta_gain_2 = data->delta_gain_code[2]; + iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, + sizeof(cmd), &cmd, NULL); + + data->radio_write = 1; + data->state = IWL_CHAIN_NOISE_CALIBRATED; + } + + data->chain_noise_a = 0; + data->chain_noise_b = 0; + data->chain_noise_c = 0; + data->chain_signal_a = 0; + data->chain_signal_b = 0; + data->chain_signal_c = 0; + data->beacon_count = 0; +} + +static void iwlagn_chain_noise_reset(struct iwl_priv *priv) +{ + struct iwl_chain_noise_data *data = &priv->chain_noise_data; + int ret; + + if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { + struct iwl_calib_chain_noise_reset_cmd cmd; + memset(&cmd, 0, sizeof(cmd)); + + cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; + cmd.hdr.first_group = 0; + cmd.hdr.groups_num = 1; + cmd.hdr.data_valid = 1; + ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, + sizeof(cmd), &cmd); + if (ret) + IWL_ERR(priv, + "Could not send REPLY_PHY_CALIBRATION_CMD\n"); + data->state = IWL_CHAIN_NOISE_ACCUMULATE; + IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); + } +} + +static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info, + __le32 *tx_flags) +{ + if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) + *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; + else + *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; +} + +/* Calc max signal level (dBm) among 3 possible receivers */ +static int iwlagn_calc_rssi(struct iwl_priv *priv, + struct iwl_rx_phy_res *rx_resp) +{ + /* data from PHY/DSP regarding signal strength, etc., + * contents are always there, not configurable by host + */ + struct iwl5000_non_cfg_phy *ncphy = + (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; + u32 val, rssi_a, rssi_b, rssi_c, max_rssi; + u8 agc; + + val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); + agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; + + /* Find max rssi among 3 possible receivers. + * These values are measured by the digital signal processor (DSP). + * They should stay fairly constant even as the signal strength varies, + * if the radio's automatic gain control (AGC) is working right. + * AGC value (see below) will provide the "interesting" info. + */ + val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); + rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; + rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; + val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); + rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; + + max_rssi = max_t(u32, rssi_a, rssi_b); + max_rssi = max_t(u32, max_rssi, rssi_c); + + IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", + rssi_a, rssi_b, rssi_c, max_rssi, agc); + + /* dBm = max_rssi dB - agc dB - constant. + * Higher AGC (higher radio gain) means lower signal. */ + return max_rssi - agc - IWL49_RSSI_OFFSET; +} + +struct iwl_hcmd_ops iwlagn_hcmd = { + .rxon_assoc = iwlagn_send_rxon_assoc, + .commit_rxon = iwl_commit_rxon, + .set_rxon_chain = iwl_set_rxon_chain, + .set_tx_ant = iwlagn_send_tx_ant_config, +}; + +struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { + .get_hcmd_size = iwlagn_get_hcmd_size, + .build_addsta_hcmd = iwlagn_build_addsta_hcmd, + .gain_computation = iwlagn_gain_computation, + .chain_noise_reset = iwlagn_chain_noise_reset, + .rts_tx_cmd_flag = iwlagn_rts_tx_cmd_flag, + .calc_rssi = iwlagn_calc_rssi, +}; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 5af528dd3c63..51e49df3644d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -66,6 +66,8 @@ #include "iwl-dev.h" extern struct iwl_ucode_ops iwlagn_ucode; +extern struct iwl_hcmd_ops iwlagn_hcmd; +extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; int iwl_reset_ict(struct iwl_priv *priv); void iwl_disable_ict(struct iwl_priv *priv); -- cgit v1.2.3 From b305a08058f794c8a99c5ee87827b92d6b8c24ae Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 16 Mar 2010 17:41:22 -0700 Subject: iwlwifi: move tx queue related code to separate file Multiple iwlagn based devices shared the same tansmit queue functions. Move tx queue related code from iwl-5000.c to iwl-agn-tx.c file. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/Makefile | 2 +- drivers/net/wireless/iwlwifi/iwl-1000.c | 10 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 253 ++-------------------------- drivers/net/wireless/iwlwifi/iwl-6000.c | 20 +-- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 268 ++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 17 ++ 6 files changed, 313 insertions(+), 257 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-tx.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 46fad2d7226b..fec44cf3c0a6 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -10,7 +10,7 @@ CFLAGS_iwl-devtrace.o := -I$(src) # AGN obj-$(CONFIG_IWLAGN) += iwlagn.o iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o -iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o +iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o iwlagn-$(CONFIG_IWL5000) += iwl-5000.o diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 67d8513cff3c..6bdbe2df2829 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -162,11 +162,11 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) static struct iwl_lib_ops iwl1000_lib = { .set_hw_params = iwl1000_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwl5000_txq_set_sched, - .txq_agg_enable = iwl5000_txq_agg_enable, - .txq_agg_disable = iwl5000_txq_agg_disable, + .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, + .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, + .txq_set_sched = iwlagn_txq_set_sched, + .txq_agg_enable = iwlagn_txq_agg_enable, + .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 8aa382e370f6..7e278956ec37 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -358,34 +358,6 @@ restart: queue_work(priv->workqueue, &priv->restart); } -static void iwl5000_set_wr_ptrs(struct iwl_priv *priv, - int txq_id, u32 index) -{ - iwl_write_direct32(priv, HBUS_TARG_WRPTR, - (index & 0xff) | (txq_id << 8)); - iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(txq_id), index); -} - -static void iwl5000_tx_queue_set_status(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - int tx_fifo_id, int scd_retry) -{ - int txq_id = txq->q.id; - int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; - - iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id), - (active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) | - (tx_fifo_id << IWL50_SCD_QUEUE_STTS_REG_POS_TXF) | - (1 << IWL50_SCD_QUEUE_STTS_REG_POS_WSL) | - IWL50_SCD_QUEUE_STTS_REG_MSK); - - txq->sched_retry = scd_retry; - - IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", - active ? "Activate" : "Deactivate", - scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); -} - int iwl5000_alive_notify(struct iwl_priv *priv) { u32 a; @@ -448,7 +420,7 @@ int iwl5000_alive_notify(struct iwl_priv *priv) /* Activate all Tx DMA/FIFO channels */ priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); - iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); + iwlagn_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); /* make sure all queue are not stopped */ memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); @@ -468,7 +440,7 @@ int iwl5000_alive_notify(struct iwl_priv *priv) if (ac == IWL_TX_FIFO_UNUSED) continue; - iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0); + iwlagn_tx_queue_set_status(priv, &priv->txq[i], ac, 0); } spin_unlock_irqrestore(&priv->lock, flags); @@ -539,207 +511,6 @@ int iwl5000_hw_set_hw_params(struct iwl_priv *priv) return 0; } -/** - * iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array - */ -void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - u16 byte_cnt) -{ - struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; - int write_ptr = txq->q.write_ptr; - int txq_id = txq->q.id; - u8 sec_ctl = 0; - u8 sta_id = 0; - u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; - __le16 bc_ent; - - WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); - - if (txq_id != IWL_CMD_QUEUE_NUM) { - sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; - sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; - - switch (sec_ctl & TX_CMD_SEC_MSK) { - case TX_CMD_SEC_CCM: - len += CCMP_MIC_LEN; - break; - case TX_CMD_SEC_TKIP: - len += TKIP_ICV_LEN; - break; - case TX_CMD_SEC_WEP: - len += WEP_IV_LEN + WEP_ICV_LEN; - break; - } - } - - bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); - - scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; - - if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) - scd_bc_tbl[txq_id]. - tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; -} - -void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq) -{ - struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; - int txq_id = txq->q.id; - int read_ptr = txq->q.read_ptr; - u8 sta_id = 0; - __le16 bc_ent; - - WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); - - if (txq_id != IWL_CMD_QUEUE_NUM) - sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; - - bc_ent = cpu_to_le16(1 | (sta_id << 12)); - scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; - - if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) - scd_bc_tbl[txq_id]. - tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; -} - -static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, - u16 txq_id) -{ - u32 tbl_dw_addr; - u32 tbl_dw; - u16 scd_q2ratid; - - scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; - - tbl_dw_addr = priv->scd_base_addr + - IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); - - tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); - - if (txq_id & 0x1) - tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); - else - tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); - - iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); - - return 0; -} -static void iwl5000_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) -{ - /* Simply stop the queue, but don't change any configuration; - * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ - iwl_write_prph(priv, - IWL50_SCD_QUEUE_STATUS_BITS(txq_id), - (0 << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE)| - (1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); -} - -int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, - int tx_fifo, int sta_id, int tid, u16 ssn_idx) -{ - unsigned long flags; - u16 ra_tid; - - if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || - (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues - <= txq_id)) { - IWL_WARN(priv, - "queue number out of range: %d, must be %d to %d\n", - txq_id, IWL50_FIRST_AMPDU_QUEUE, - IWL50_FIRST_AMPDU_QUEUE + - priv->cfg->num_of_ampdu_queues - 1); - return -EINVAL; - } - - ra_tid = BUILD_RAxTID(sta_id, tid); - - /* Modify device's station table to Tx this TID */ - iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); - - spin_lock_irqsave(&priv->lock, flags); - - /* Stop this Tx queue before configuring it */ - iwl5000_tx_queue_stop_scheduler(priv, txq_id); - - /* Map receiver-address / traffic-ID to this queue */ - iwl5000_tx_queue_set_q2ratid(priv, ra_tid, txq_id); - - /* Set this queue as a chain-building queue */ - iwl_set_bits_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, (1<txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - iwl5000_set_wr_ptrs(priv, txq_id, ssn_idx); - - /* Set up Tx window size and frame limit for this queue */ - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWL50_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + - sizeof(u32), - ((SCD_WIN_SIZE << - IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & - IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | - ((SCD_FRAME_LIMIT << - IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & - IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - - iwl_set_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); - - /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ - iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); - - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo) -{ - if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || - (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues - <= txq_id)) { - IWL_ERR(priv, - "queue number out of range: %d, must be %d to %d\n", - txq_id, IWL50_FIRST_AMPDU_QUEUE, - IWL50_FIRST_AMPDU_QUEUE + - priv->cfg->num_of_ampdu_queues - 1); - return -EINVAL; - } - - iwl5000_tx_queue_stop_scheduler(priv, txq_id); - - iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id)); - - priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - /* supposes that ssn_idx is valid (!= 0xFFF) */ - iwl5000_set_wr_ptrs(priv, txq_id, ssn_idx); - - iwl_clear_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); - iwl_txq_ctx_deactivate(priv, txq_id); - iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); - - return 0; -} - -/* - * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask - * must be called under priv->lock and mac access - */ -void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask) -{ - iwl_write_prph(priv, IWL50_SCD_TXFACT, mask); -} - - static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) { return le32_to_cpup((__le32 *)&tx_resp->status + @@ -1063,11 +834,11 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) struct iwl_lib_ops iwl5000_lib = { .set_hw_params = iwl5000_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwl5000_txq_set_sched, - .txq_agg_enable = iwl5000_txq_agg_enable, - .txq_agg_disable = iwl5000_txq_agg_disable, + .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, + .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, + .txq_set_sched = iwlagn_txq_set_sched, + .txq_agg_enable = iwlagn_txq_agg_enable, + .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, @@ -1121,11 +892,11 @@ struct iwl_lib_ops iwl5000_lib = { static struct iwl_lib_ops iwl5150_lib = { .set_hw_params = iwl5000_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwl5000_txq_set_sched, - .txq_agg_enable = iwl5000_txq_agg_enable, - .txq_agg_disable = iwl5000_txq_agg_disable, + .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, + .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, + .txq_set_sched = iwlagn_txq_set_sched, + .txq_agg_enable = iwlagn_txq_agg_enable, + .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index aff46b08703a..f37639003489 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -226,11 +226,11 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel) static struct iwl_lib_ops iwl6000_lib = { .set_hw_params = iwl6000_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwl5000_txq_set_sched, - .txq_agg_enable = iwl5000_txq_agg_enable, - .txq_agg_disable = iwl5000_txq_agg_disable, + .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, + .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, + .txq_set_sched = iwlagn_txq_set_sched, + .txq_agg_enable = iwlagn_txq_agg_enable, + .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, @@ -293,11 +293,11 @@ static const struct iwl_ops iwl6000_ops = { static struct iwl_lib_ops iwl6050_lib = { .set_hw_params = iwl6000_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwl5000_txq_set_sched, - .txq_agg_enable = iwl5000_txq_agg_enable, - .txq_agg_disable = iwl5000_txq_agg_disable, + .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, + .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, + .txq_set_sched = iwlagn_txq_set_sched, + .txq_agg_enable = iwlagn_txq_agg_enable, + .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c new file mode 100644 index 000000000000..44b3d53e9c76 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -0,0 +1,268 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#include +#include +#include +#include + +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-sta.h" +#include "iwl-io.h" +#include "iwl-5000-hw.h" + +/** + * iwlagn_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array + */ +void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + u16 byte_cnt) +{ + struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; + int write_ptr = txq->q.write_ptr; + int txq_id = txq->q.id; + u8 sec_ctl = 0; + u8 sta_id = 0; + u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; + __le16 bc_ent; + + WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); + + if (txq_id != IWL_CMD_QUEUE_NUM) { + sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; + sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; + + switch (sec_ctl & TX_CMD_SEC_MSK) { + case TX_CMD_SEC_CCM: + len += CCMP_MIC_LEN; + break; + case TX_CMD_SEC_TKIP: + len += TKIP_ICV_LEN; + break; + case TX_CMD_SEC_WEP: + len += WEP_IV_LEN + WEP_ICV_LEN; + break; + } + } + + bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); + + scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; + + if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) + scd_bc_tbl[txq_id]. + tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; +} + +void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq) +{ + struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; + int txq_id = txq->q.id; + int read_ptr = txq->q.read_ptr; + u8 sta_id = 0; + __le16 bc_ent; + + WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); + + if (txq_id != IWL_CMD_QUEUE_NUM) + sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; + + bc_ent = cpu_to_le16(1 | (sta_id << 12)); + scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; + + if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) + scd_bc_tbl[txq_id]. + tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; +} + +static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, + u16 txq_id) +{ + u32 tbl_dw_addr; + u32 tbl_dw; + u16 scd_q2ratid; + + scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; + + tbl_dw_addr = priv->scd_base_addr + + IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); + + tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); + + if (txq_id & 0x1) + tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); + else + tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); + + iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); + + return 0; +} + +static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) +{ + /* Simply stop the queue, but don't change any configuration; + * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ + iwl_write_prph(priv, + IWL50_SCD_QUEUE_STATUS_BITS(txq_id), + (0 << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE)| + (1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); +} + +void iwlagn_set_wr_ptrs(struct iwl_priv *priv, + int txq_id, u32 index) +{ + iwl_write_direct32(priv, HBUS_TARG_WRPTR, + (index & 0xff) | (txq_id << 8)); + iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(txq_id), index); +} + +void iwlagn_tx_queue_set_status(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + int tx_fifo_id, int scd_retry) +{ + int txq_id = txq->q.id; + int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; + + iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id), + (active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) | + (tx_fifo_id << IWL50_SCD_QUEUE_STTS_REG_POS_TXF) | + (1 << IWL50_SCD_QUEUE_STTS_REG_POS_WSL) | + IWL50_SCD_QUEUE_STTS_REG_MSK); + + txq->sched_retry = scd_retry; + + IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", + active ? "Activate" : "Deactivate", + scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); +} + +int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, + int tx_fifo, int sta_id, int tid, u16 ssn_idx) +{ + unsigned long flags; + u16 ra_tid; + + if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || + (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues + <= txq_id)) { + IWL_WARN(priv, + "queue number out of range: %d, must be %d to %d\n", + txq_id, IWL50_FIRST_AMPDU_QUEUE, + IWL50_FIRST_AMPDU_QUEUE + + priv->cfg->num_of_ampdu_queues - 1); + return -EINVAL; + } + + ra_tid = BUILD_RAxTID(sta_id, tid); + + /* Modify device's station table to Tx this TID */ + iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); + + spin_lock_irqsave(&priv->lock, flags); + + /* Stop this Tx queue before configuring it */ + iwlagn_tx_queue_stop_scheduler(priv, txq_id); + + /* Map receiver-address / traffic-ID to this queue */ + iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id); + + /* Set this queue as a chain-building queue */ + iwl_set_bits_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, (1<txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); + + /* Set up Tx window size and frame limit for this queue */ + iwl_write_targ_mem(priv, priv->scd_base_addr + + IWL50_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + + sizeof(u32), + ((SCD_WIN_SIZE << + IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & + IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | + ((SCD_FRAME_LIMIT << + IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & + IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); + + iwl_set_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); + + /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ + iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); + + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo) +{ + if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || + (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues + <= txq_id)) { + IWL_ERR(priv, + "queue number out of range: %d, must be %d to %d\n", + txq_id, IWL50_FIRST_AMPDU_QUEUE, + IWL50_FIRST_AMPDU_QUEUE + + priv->cfg->num_of_ampdu_queues - 1); + return -EINVAL; + } + + iwlagn_tx_queue_stop_scheduler(priv, txq_id); + + iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id)); + + priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + /* supposes that ssn_idx is valid (!= 0xFFF) */ + iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); + + iwl_clear_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_txq_ctx_deactivate(priv, txq_id); + iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); + + return 0; +} + +/* + * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask + * must be called under priv->lock and mac access + */ +void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask) +{ + iwl_write_prph(priv, IWL50_SCD_TXFACT, mask); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 51e49df3644d..2ff7b8f5df7f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -80,4 +80,21 @@ bool iwl_good_ack_health(struct iwl_priv *priv, /* uCode */ int iwlagn_load_ucode(struct iwl_priv *priv); +/* tx queue */ +void iwlagn_set_wr_ptrs(struct iwl_priv *priv, + int txq_id, u32 index); +void iwlagn_tx_queue_set_status(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + int tx_fifo_id, int scd_retry); +void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + u16 byte_cnt); +void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq); +int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, + int tx_fifo, int sta_id, int tid, u16 ssn_idx); +int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo); +void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); + #endif /* __iwl_agn_h__ */ -- cgit v1.2.3 From 19e6cda094002e9756a3d181cbb4c31ef2a9b6bb Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 16 Mar 2010 17:41:23 -0700 Subject: iwlwifi: move hw related defines to separate file Multiple iwlagn based devices shared the same hw definitions. Move device hardware related defines from iwl-5000-hw.h to iwl-agn-hw.h file. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 18 ++--- drivers/net/wireless/iwlwifi/iwl-5000-hw.h | 33 --------- drivers/net/wireless/iwlwifi/iwl-5000.c | 57 +++++++-------- drivers/net/wireless/iwlwifi/iwl-6000.c | 30 ++++---- drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 1 - drivers/net/wireless/iwlwifi/iwl-agn-hw.h | 102 +++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 22 +++--- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 6 +- 8 files changed, 169 insertions(+), 100 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-hw.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 6bdbe2df2829..f866410ea9d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -44,7 +44,7 @@ #include "iwl-sta.h" #include "iwl-agn.h" #include "iwl-helpers.h" -#include "iwl-5000-hw.h" +#include "iwl-agn-hw.h" #include "iwl-agn-led.h" /* Highest firmware API version supported */ @@ -118,7 +118,7 @@ static struct iwl_sensitivity_ranges iwl1000_sensitivity = { static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) { if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && - priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) + priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) priv->cfg->num_of_queues = priv->cfg->mod_params->num_of_queues; @@ -126,13 +126,13 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; priv->hw_params.scd_bc_tbls_size = priv->cfg->num_of_queues * - sizeof(struct iwl5000_scd_bc_tbl); + sizeof(struct iwlagn_scd_bc_tbl); priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.max_stations = IWL5000_STATION_COUNT; priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; - priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; + priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; priv->hw_params.max_bsm_size = 0; priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | @@ -235,8 +235,8 @@ struct iwl_cfg iwl1000_bgn_cfg = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_1000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_A, .valid_rx_ant = ANT_AB, @@ -265,8 +265,8 @@ struct iwl_cfg iwl1000_bg_cfg = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_1000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_A, .valid_rx_ant = ANT_AB, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 714e032f6217..146e6431ae95 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -68,25 +68,6 @@ #ifndef __iwl_5000_hw_h__ #define __iwl_5000_hw_h__ -#define IWL50_RTC_INST_LOWER_BOUND (0x000000) -#define IWL50_RTC_INST_UPPER_BOUND (0x020000) - -#define IWL50_RTC_DATA_LOWER_BOUND (0x800000) -#define IWL50_RTC_DATA_UPPER_BOUND (0x80C000) - -#define IWL50_RTC_INST_SIZE (IWL50_RTC_INST_UPPER_BOUND - \ - IWL50_RTC_INST_LOWER_BOUND) -#define IWL50_RTC_DATA_SIZE (IWL50_RTC_DATA_UPPER_BOUND - \ - IWL50_RTC_DATA_LOWER_BOUND) - -/* EEPROM */ -#define IWL_5000_EEPROM_IMG_SIZE 2048 - -#define IWL50_CMD_FIFO_NUM 7 -#define IWL50_NUM_QUEUES 20 -#define IWL50_NUM_AMPDU_QUEUES 10 -#define IWL50_FIRST_AMPDU_QUEUE 10 - /* 5150 only */ #define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5) @@ -103,19 +84,5 @@ static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); } -/* Fixed (non-configurable) rx data from phy */ - -/** - * struct iwl5000_schedq_bc_tbl scheduler byte count table - * base physical address of iwl5000_shared - * is provided to SCD_DRAM_BASE_ADDR - * @tfd_offset 0-12 - tx command byte count - * 12-16 - station index - */ -struct iwl5000_scd_bc_tbl { - __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; -} __attribute__ ((packed)); - - #endif /* __iwl_5000_hw_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 7e278956ec37..a41af47c1926 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -45,6 +45,7 @@ #include "iwl-helpers.h" #include "iwl-agn.h" #include "iwl-agn-led.h" +#include "iwl-agn-hw.h" #include "iwl-5000-hw.h" #include "iwl-6000-hw.h" @@ -69,7 +70,7 @@ static const s8 iwl5000_default_queue_to_tx_fifo[] = { IWL_TX_FIFO_VI, IWL_TX_FIFO_BE, IWL_TX_FIFO_BK, - IWL50_CMD_FIFO_NUM, + IWLAGN_CMD_FIFO_NUM, IWL_TX_FIFO_UNUSED, IWL_TX_FIFO_UNUSED, IWL_TX_FIFO_UNUSED, @@ -456,7 +457,7 @@ int iwl5000_alive_notify(struct iwl_priv *priv) int iwl5000_hw_set_hw_params(struct iwl_priv *priv) { if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && - priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) + priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) priv->cfg->num_of_queues = priv->cfg->mod_params->num_of_queues; @@ -464,13 +465,13 @@ int iwl5000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; priv->hw_params.scd_bc_tbls_size = priv->cfg->num_of_queues * - sizeof(struct iwl5000_scd_bc_tbl); + sizeof(struct iwlagn_scd_bc_tbl); priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.max_stations = IWL5000_STATION_COUNT; priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; - priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; + priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; priv->hw_params.max_bsm_size = 0; priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | @@ -741,8 +742,8 @@ void iwl5000_rx_handler_setup(struct iwl_priv *priv) int iwl5000_hw_valid_rtc_data_addr(u32 addr) { - return (addr >= IWL50_RTC_DATA_LOWER_BOUND) && - (addr < IWL50_RTC_DATA_UPPER_BOUND); + return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && + (addr < IWLAGN_RTC_DATA_UPPER_BOUND); } int iwl5000_send_tx_power(struct iwl_priv *priv) @@ -977,11 +978,11 @@ struct iwl_cfg iwl5300_agn_cfg = { .ucode_api_min = IWL5000_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .ops = &iwl5000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC, @@ -1004,11 +1005,11 @@ struct iwl_cfg iwl5100_bgn_cfg = { .ucode_api_min = IWL5000_UCODE_API_MIN, .sku = IWL_SKU_G|IWL_SKU_N, .ops = &iwl5000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_B, .valid_rx_ant = ANT_AB, @@ -1031,11 +1032,11 @@ struct iwl_cfg iwl5100_abg_cfg = { .ucode_api_min = IWL5000_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G, .ops = &iwl5000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_B, .valid_rx_ant = ANT_AB, @@ -1056,11 +1057,11 @@ struct iwl_cfg iwl5100_agn_cfg = { .ucode_api_min = IWL5000_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .ops = &iwl5000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_B, .valid_rx_ant = ANT_AB, @@ -1083,11 +1084,11 @@ struct iwl_cfg iwl5350_agn_cfg = { .ucode_api_min = IWL5000_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .ops = &iwl5000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_5050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC, @@ -1110,11 +1111,11 @@ struct iwl_cfg iwl5150_agn_cfg = { .ucode_api_min = IWL5150_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .ops = &iwl5150_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_5050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_A, .valid_rx_ant = ANT_AB, @@ -1137,11 +1138,11 @@ struct iwl_cfg iwl5150_abg_cfg = { .ucode_api_min = IWL5150_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G, .ops = &iwl5150_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_5050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_A, .valid_rx_ant = ANT_AB, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index f37639003489..2bbff18694c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -44,7 +44,7 @@ #include "iwl-sta.h" #include "iwl-agn.h" #include "iwl-helpers.h" -#include "iwl-5000-hw.h" +#include "iwl-agn-hw.h" #include "iwl-6000-hw.h" #include "iwl-agn-led.h" @@ -137,7 +137,7 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = { static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) { if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && - priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) + priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) priv->cfg->num_of_queues = priv->cfg->mod_params->num_of_queues; @@ -145,7 +145,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; priv->hw_params.scd_bc_tbls_size = priv->cfg->num_of_queues * - sizeof(struct iwl5000_scd_bc_tbl); + sizeof(struct iwlagn_scd_bc_tbl); priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.max_stations = IWL5000_STATION_COUNT; priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; @@ -372,8 +372,8 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_BC, .valid_rx_ant = ANT_BC, @@ -405,8 +405,8 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_BC, .valid_rx_ant = ANT_BC, @@ -437,8 +437,8 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_BC, .valid_rx_ant = ANT_BC, @@ -469,8 +469,8 @@ struct iwl_cfg iwl6050_2agn_cfg = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_AB, @@ -502,8 +502,8 @@ struct iwl_cfg iwl6050_2abg_cfg = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_AB, @@ -534,8 +534,8 @@ struct iwl_cfg iwl6000_3agn_cfg = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 3ac010b1b1c5..a0e3c1106138 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -35,7 +35,6 @@ #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-io.h" -#include "iwl-5000-hw.h" static int iwlagn_send_rxon_assoc(struct iwl_priv *priv) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h new file mode 100644 index 000000000000..e2ad870bb348 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Please use this file (iwl-agn-hw.h) only for hardware-related definitions. + */ + +#ifndef __iwl_agn_hw_h__ +#define __iwl_agn_hw_h__ + +#define IWLAGN_RTC_INST_LOWER_BOUND (0x000000) +#define IWLAGN_RTC_INST_UPPER_BOUND (0x020000) + +#define IWLAGN_RTC_DATA_LOWER_BOUND (0x800000) +#define IWLAGN_RTC_DATA_UPPER_BOUND (0x80C000) + +#define IWLAGN_RTC_INST_SIZE (IWLAGN_RTC_INST_UPPER_BOUND - \ + IWLAGN_RTC_INST_LOWER_BOUND) +#define IWLAGN_RTC_DATA_SIZE (IWLAGN_RTC_DATA_UPPER_BOUND - \ + IWLAGN_RTC_DATA_LOWER_BOUND) + +/* EEPROM */ +#define IWLAGN_EEPROM_IMG_SIZE 2048 + +#define IWLAGN_CMD_FIFO_NUM 7 +#define IWLAGN_NUM_QUEUES 20 +#define IWLAGN_NUM_AMPDU_QUEUES 10 +#define IWLAGN_FIRST_AMPDU_QUEUE 10 + +/* Fixed (non-configurable) rx data from phy */ + +/** + * struct iwlagn_schedq_bc_tbl scheduler byte count table + * base physical address provided by SCD_DRAM_BASE_ADDR + * @tfd_offset 0-12 - tx command byte count + * 12-16 - station index + */ +struct iwlagn_scd_bc_tbl { + __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; +} __attribute__ ((packed)); + + +#endif /* __iwl_agn_hw_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 44b3d53e9c76..43bdd9d9df4d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -36,7 +36,7 @@ #include "iwl-core.h" #include "iwl-sta.h" #include "iwl-io.h" -#include "iwl-5000-hw.h" +#include "iwl-agn-hw.h" /** * iwlagn_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array @@ -45,7 +45,7 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq, u16 byte_cnt) { - struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; + struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; int write_ptr = txq->q.write_ptr; int txq_id = txq->q.id; u8 sec_ctl = 0; @@ -84,7 +84,7 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq) { - struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; + struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; int txq_id = txq->q.id; int read_ptr = txq->q.read_ptr; u8 sta_id = 0; @@ -171,13 +171,13 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, unsigned long flags; u16 ra_tid; - if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || - (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues + if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || + (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues <= txq_id)) { IWL_WARN(priv, "queue number out of range: %d, must be %d to %d\n", - txq_id, IWL50_FIRST_AMPDU_QUEUE, - IWL50_FIRST_AMPDU_QUEUE + + txq_id, IWLAGN_FIRST_AMPDU_QUEUE, + IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues - 1); return -EINVAL; } @@ -231,13 +231,13 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, u8 tx_fifo) { - if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || - (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues + if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || + (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues <= txq_id)) { IWL_ERR(priv, "queue number out of range: %d, must be %d to %d\n", - txq_id, IWL50_FIRST_AMPDU_QUEUE, - IWL50_FIRST_AMPDU_QUEUE + + txq_id, IWLAGN_FIRST_AMPDU_QUEUE, + IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues - 1); return -EINVAL; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index f57a4f8033f7..f0af3881b74c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -35,7 +35,7 @@ #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-io.h" -#include "iwl-5000-hw.h" +#include "iwl-agn-hw.h" /* * ucode @@ -101,12 +101,12 @@ static int iwlagn_load_given_ucode(struct iwl_priv *priv, int ret = 0; ret = iwlagn_load_section(priv, "INST", inst_image, - IWL50_RTC_INST_LOWER_BOUND); + IWLAGN_RTC_INST_LOWER_BOUND); if (ret) return ret; return iwlagn_load_section(priv, "DATA", data_image, - IWL50_RTC_DATA_LOWER_BOUND); + IWLAGN_RTC_DATA_LOWER_BOUND); } int iwlagn_load_ucode(struct iwl_priv *priv) -- cgit v1.2.3 From 741a626627e42812afd957f875c34c89be8a103e Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 16 Mar 2010 12:37:24 -0700 Subject: iwlwifi: move ucode alive related code to separate file uCode alive for iwlagn based devices share the same functions. Move those functions from iwl-5000.c to iwl-agn-ucode.c. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 239 +-------------------------- drivers/net/wireless/iwlwifi/iwl-6000.c | 8 +- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 230 ++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 12 +- 5 files changed, 251 insertions(+), 242 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index f866410ea9d8..9d211606c040 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -178,8 +178,8 @@ static struct iwl_lib_ops iwl1000_lib = { .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, .dump_fh = iwl_dump_fh, - .init_alive_start = iwl5000_init_alive_start, - .alive_notify = iwl5000_alive_notify, + .init_alive_start = iwlagn_init_alive_start, + .alive_notify = iwlagn_alive_notify, .send_tx_power = iwl5000_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .apm_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index a41af47c1926..9128ccd8dfae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -65,19 +65,6 @@ #define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" #define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api) -static const s8 iwl5000_default_queue_to_tx_fifo[] = { - IWL_TX_FIFO_VO, - IWL_TX_FIFO_VI, - IWL_TX_FIFO_BE, - IWL_TX_FIFO_BK, - IWLAGN_CMD_FIFO_NUM, - IWL_TX_FIFO_UNUSED, - IWL_TX_FIFO_UNUSED, - IWL_TX_FIFO_UNUSED, - IWL_TX_FIFO_UNUSED, - IWL_TX_FIFO_UNUSED, -}; - /* NIC configuration for 5000 series */ void iwl5000_nic_config(struct iwl_priv *priv) { @@ -240,220 +227,6 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; } -/* - * Calibration - */ -static int iwl5000_set_Xtal_calib(struct iwl_priv *priv) -{ - struct iwl_calib_xtal_freq_cmd cmd; - __le16 *xtal_calib = - (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); - - cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; - cmd.hdr.first_group = 0; - cmd.hdr.groups_num = 1; - cmd.hdr.data_valid = 1; - cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); - cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); - return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], - (u8 *)&cmd, sizeof(cmd)); -} - -static int iwl5000_send_calib_cfg(struct iwl_priv *priv) -{ - struct iwl_calib_cfg_cmd calib_cfg_cmd; - struct iwl_host_cmd cmd = { - .id = CALIBRATION_CFG_CMD, - .len = sizeof(struct iwl_calib_cfg_cmd), - .data = &calib_cfg_cmd, - }; - - memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); - calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; - calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL; - calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL; - calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL; - - return iwl_send_cmd(priv, &cmd); -} - -static void iwl5000_rx_calib_result(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; - int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; - int index; - - /* reduce the size of the length field itself */ - len -= 4; - - /* Define the order in which the results will be sent to the runtime - * uCode. iwl_send_calib_results sends them in a row according to their - * index. We sort them here */ - switch (hdr->op_code) { - case IWL_PHY_CALIBRATE_DC_CMD: - index = IWL_CALIB_DC; - break; - case IWL_PHY_CALIBRATE_LO_CMD: - index = IWL_CALIB_LO; - break; - case IWL_PHY_CALIBRATE_TX_IQ_CMD: - index = IWL_CALIB_TX_IQ; - break; - case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD: - index = IWL_CALIB_TX_IQ_PERD; - break; - case IWL_PHY_CALIBRATE_BASE_BAND_CMD: - index = IWL_CALIB_BASE_BAND; - break; - default: - IWL_ERR(priv, "Unknown calibration notification %d\n", - hdr->op_code); - return; - } - iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); -} - -static void iwl5000_rx_calib_complete(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); - queue_work(priv->workqueue, &priv->restart); -} - -void iwl5000_init_alive_start(struct iwl_priv *priv) -{ - int ret = 0; - - /* Check alive response for "valid" sign from uCode */ - if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { - /* We had an error bringing up the hardware, so take it - * all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); - goto restart; - } - - /* initialize uCode was loaded... verify inst image. - * This is a paranoid check, because we would not have gotten the - * "initialize" alive if code weren't properly loaded. */ - if (iwl_verify_ucode(priv)) { - /* Runtime instruction load was bad; - * take it all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); - goto restart; - } - - ret = priv->cfg->ops->lib->alive_notify(priv); - if (ret) { - IWL_WARN(priv, - "Could not complete ALIVE transition: %d\n", ret); - goto restart; - } - - iwl5000_send_calib_cfg(priv); - return; - -restart: - /* real restart (first load init_ucode) */ - queue_work(priv->workqueue, &priv->restart); -} - -int iwl5000_alive_notify(struct iwl_priv *priv) -{ - u32 a; - unsigned long flags; - int i, chan; - u32 reg_val; - - spin_lock_irqsave(&priv->lock, flags); - - priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR); - a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET; - for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET; - a += 4) - iwl_write_targ_mem(priv, a, 0); - for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET; - a += 4) - iwl_write_targ_mem(priv, a, 0); - for (; a < priv->scd_base_addr + - IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) - iwl_write_targ_mem(priv, a, 0); - - iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, - priv->scd_bc_tbls.dma >> 10); - - /* Enable DMA channel */ - for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++) - iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); - - /* Update FH chicken bits */ - reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); - iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, - reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); - - iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, - IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); - iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); - - /* initiate the queues */ - for (i = 0; i < priv->hw_params.max_txq_num; i++) { - iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(i), 0); - iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWL50_SCD_CONTEXT_QUEUE_OFFSET(i), 0); - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWL50_SCD_CONTEXT_QUEUE_OFFSET(i) + - sizeof(u32), - ((SCD_WIN_SIZE << - IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & - IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | - ((SCD_FRAME_LIMIT << - IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & - IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - } - - iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK, - IWL_MASK(0, priv->hw_params.max_txq_num)); - - /* Activate all Tx DMA/FIFO channels */ - priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); - - iwlagn_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); - - /* make sure all queue are not stopped */ - memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); - for (i = 0; i < 4; i++) - atomic_set(&priv->queue_stop_count[i], 0); - - /* reset to 0 to enable all the queue first */ - priv->txq_ctx_active_msk = 0; - /* map qos queues to fifos one-to-one */ - BUILD_BUG_ON(ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo) != 10); - - for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) { - int ac = iwl5000_default_queue_to_tx_fifo[i]; - - iwl_txq_ctx_activate(priv, i); - - if (ac == IWL_TX_FIFO_UNUSED) - continue; - - iwlagn_tx_queue_set_status(priv, &priv->txq[i], ac, 0); - } - - spin_unlock_irqrestore(&priv->lock, flags); - - iwl_send_wimax_coex(priv); - - iwl5000_set_Xtal_calib(priv); - iwl_send_calib_results(priv); - - return 0; -} - int iwl5000_hw_set_hw_params(struct iwl_priv *priv) { if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && @@ -733,9 +506,9 @@ void iwl5000_rx_handler_setup(struct iwl_priv *priv) { /* init calibration handlers */ priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = - iwl5000_rx_calib_result; + iwlagn_rx_calib_result; priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = - iwl5000_rx_calib_complete; + iwlagn_rx_calib_complete; priv->rx_handlers[REPLY_TX] = iwl5000_rx_reply_tx; } @@ -851,8 +624,8 @@ struct iwl_lib_ops iwl5000_lib = { .dump_csr = iwl_dump_csr, .dump_fh = iwl_dump_fh, .load_ucode = iwlagn_load_ucode, - .init_alive_start = iwl5000_init_alive_start, - .alive_notify = iwl5000_alive_notify, + .init_alive_start = iwlagn_init_alive_start, + .alive_notify = iwlagn_alive_notify, .send_tx_power = iwl5000_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl5000_hw_channel_switch, @@ -908,8 +681,8 @@ static struct iwl_lib_ops iwl5150_lib = { .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, .load_ucode = iwlagn_load_ucode, - .init_alive_start = iwl5000_init_alive_start, - .alive_notify = iwl5000_alive_notify, + .init_alive_start = iwlagn_init_alive_start, + .alive_notify = iwlagn_alive_notify, .send_tx_power = iwl5000_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl5000_hw_channel_switch, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 2bbff18694c8..96f4fa6e0e21 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -242,8 +242,8 @@ static struct iwl_lib_ops iwl6000_lib = { .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, .dump_fh = iwl_dump_fh, - .init_alive_start = iwl5000_init_alive_start, - .alive_notify = iwl5000_alive_notify, + .init_alive_start = iwlagn_init_alive_start, + .alive_notify = iwlagn_alive_notify, .send_tx_power = iwl5000_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl6000_hw_channel_switch, @@ -309,8 +309,8 @@ static struct iwl_lib_ops iwl6050_lib = { .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, .dump_fh = iwl_dump_fh, - .init_alive_start = iwl5000_init_alive_start, - .alive_notify = iwl5000_alive_notify, + .init_alive_start = iwlagn_init_alive_start, + .alive_notify = iwlagn_alive_notify, .send_tx_power = iwl5000_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl6000_hw_channel_switch, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index f0af3881b74c..52ae157968b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -35,7 +35,22 @@ #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-io.h" +#include "iwl-helpers.h" #include "iwl-agn-hw.h" +#include "iwl-agn.h" + +static const s8 iwlagn_default_queue_to_tx_fifo[] = { + IWL_TX_FIFO_VO, + IWL_TX_FIFO_VI, + IWL_TX_FIFO_BE, + IWL_TX_FIFO_BK, + IWLAGN_CMD_FIFO_NUM, + IWL_TX_FIFO_UNUSED, + IWL_TX_FIFO_UNUSED, + IWL_TX_FIFO_UNUSED, + IWL_TX_FIFO_UNUSED, + IWL_TX_FIFO_UNUSED, +}; /* * ucode @@ -184,3 +199,218 @@ struct iwl_ucode_ops iwlagn_ucode = { .get_boot_size = iwlagn_ucode_get_boot_size, .get_data = iwlagn_ucode_get_data, }; + +/* + * Calibration + */ +static int iwlagn_set_Xtal_calib(struct iwl_priv *priv) +{ + struct iwl_calib_xtal_freq_cmd cmd; + __le16 *xtal_calib = + (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); + + cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; + cmd.hdr.first_group = 0; + cmd.hdr.groups_num = 1; + cmd.hdr.data_valid = 1; + cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); + cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); + return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], + (u8 *)&cmd, sizeof(cmd)); +} + +static int iwlagn_send_calib_cfg(struct iwl_priv *priv) +{ + struct iwl_calib_cfg_cmd calib_cfg_cmd; + struct iwl_host_cmd cmd = { + .id = CALIBRATION_CFG_CMD, + .len = sizeof(struct iwl_calib_cfg_cmd), + .data = &calib_cfg_cmd, + }; + + memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); + calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; + calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL; + calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL; + calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL; + + return iwl_send_cmd(priv, &cmd); +} + +void iwlagn_rx_calib_result(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; + int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; + int index; + + /* reduce the size of the length field itself */ + len -= 4; + + /* Define the order in which the results will be sent to the runtime + * uCode. iwl_send_calib_results sends them in a row according to + * their index. We sort them here + */ + switch (hdr->op_code) { + case IWL_PHY_CALIBRATE_DC_CMD: + index = IWL_CALIB_DC; + break; + case IWL_PHY_CALIBRATE_LO_CMD: + index = IWL_CALIB_LO; + break; + case IWL_PHY_CALIBRATE_TX_IQ_CMD: + index = IWL_CALIB_TX_IQ; + break; + case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD: + index = IWL_CALIB_TX_IQ_PERD; + break; + case IWL_PHY_CALIBRATE_BASE_BAND_CMD: + index = IWL_CALIB_BASE_BAND; + break; + default: + IWL_ERR(priv, "Unknown calibration notification %d\n", + hdr->op_code); + return; + } + iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); +} + +void iwlagn_rx_calib_complete(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); + queue_work(priv->workqueue, &priv->restart); +} + +void iwlagn_init_alive_start(struct iwl_priv *priv) +{ + int ret = 0; + + /* Check alive response for "valid" sign from uCode */ + if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { + /* We had an error bringing up the hardware, so take it + * all the way back down so we can try again */ + IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); + goto restart; + } + + /* initialize uCode was loaded... verify inst image. + * This is a paranoid check, because we would not have gotten the + * "initialize" alive if code weren't properly loaded. */ + if (iwl_verify_ucode(priv)) { + /* Runtime instruction load was bad; + * take it all the way back down so we can try again */ + IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); + goto restart; + } + + ret = priv->cfg->ops->lib->alive_notify(priv); + if (ret) { + IWL_WARN(priv, + "Could not complete ALIVE transition: %d\n", ret); + goto restart; + } + + iwlagn_send_calib_cfg(priv); + return; + +restart: + /* real restart (first load init_ucode) */ + queue_work(priv->workqueue, &priv->restart); +} + +int iwlagn_alive_notify(struct iwl_priv *priv) +{ + u32 a; + unsigned long flags; + int i, chan; + u32 reg_val; + + spin_lock_irqsave(&priv->lock, flags); + + priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR); + a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET; + for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET; + a += 4) + iwl_write_targ_mem(priv, a, 0); + for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET; + a += 4) + iwl_write_targ_mem(priv, a, 0); + for (; a < priv->scd_base_addr + + IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) + iwl_write_targ_mem(priv, a, 0); + + iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, + priv->scd_bc_tbls.dma >> 10); + + /* Enable DMA channel */ + for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++) + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); + + /* Update FH chicken bits */ + reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); + iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, + reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); + + iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, + IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); + iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); + + /* initiate the queues */ + for (i = 0; i < priv->hw_params.max_txq_num; i++) { + iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(i), 0); + iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); + iwl_write_targ_mem(priv, priv->scd_base_addr + + IWL50_SCD_CONTEXT_QUEUE_OFFSET(i), 0); + iwl_write_targ_mem(priv, priv->scd_base_addr + + IWL50_SCD_CONTEXT_QUEUE_OFFSET(i) + + sizeof(u32), + ((SCD_WIN_SIZE << + IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & + IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | + ((SCD_FRAME_LIMIT << + IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & + IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); + } + + iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK, + IWL_MASK(0, priv->hw_params.max_txq_num)); + + /* Activate all Tx DMA/FIFO channels */ + priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); + + iwlagn_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); + + /* make sure all queue are not stopped */ + memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); + for (i = 0; i < 4; i++) + atomic_set(&priv->queue_stop_count[i], 0); + + /* reset to 0 to enable all the queue first */ + priv->txq_ctx_active_msk = 0; + /* map qos queues to fifos one-to-one */ + BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10); + + for (i = 0; i < ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); i++) { + int ac = iwlagn_default_queue_to_tx_fifo[i]; + + iwl_txq_ctx_activate(priv, i); + + if (ac == IWL_TX_FIFO_UNUSED) + continue; + + iwlagn_tx_queue_set_status(priv, &priv->txq[i], ac, 0); + } + + spin_unlock_irqrestore(&priv->lock, flags); + + iwl_send_wimax_coex(priv); + + iwlagn_set_Xtal_calib(priv); + iwl_send_calib_results(priv); + + return 0; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 2ff7b8f5df7f..9b6676569827 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -77,9 +77,6 @@ irqreturn_t iwl_isr_ict(int irq, void *data); bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt); -/* uCode */ -int iwlagn_load_ucode(struct iwl_priv *priv); - /* tx queue */ void iwlagn_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index); @@ -97,4 +94,13 @@ int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, u8 tx_fifo); void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); +/* uCode */ +int iwlagn_load_ucode(struct iwl_priv *priv); +void iwlagn_rx_calib_result(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb); +void iwlagn_rx_calib_complete(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb); +void iwlagn_init_alive_start(struct iwl_priv *priv); +int iwlagn_alive_notify(struct iwl_priv *priv); + #endif /* __iwl_agn_h__ */ -- cgit v1.2.3 From e04ed0a5bb62520345c73587d7ebf51e426642ee Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 16 Mar 2010 17:47:58 -0700 Subject: iwlwifi: move agn common code to iwlagn library file Multiple iwlagn based devices share the same common functions. Move those functions from iwl-5000.c to iwl-agn-lib.c file. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/Makefile | 1 + drivers/net/wireless/iwlwifi/iwl-1000.c | 28 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 394 ++--------------------------- drivers/net/wireless/iwlwifi/iwl-6000.c | 56 ++-- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 377 +++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 10 + drivers/net/wireless/iwlwifi/iwl-eeprom.h | 14 +- 7 files changed, 464 insertions(+), 416 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-lib.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index fec44cf3c0a6..a684a72eb6e9 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -11,6 +11,7 @@ CFLAGS_iwl-devtrace.o := -I$(src) obj-$(CONFIG_IWLAGN) += iwlagn.o iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o +iwlagn-objs += iwl-agn-lib.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o iwlagn-$(CONFIG_IWL5000) += iwl-5000.o diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 9d211606c040..a99945be6d07 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -170,9 +170,9 @@ static struct iwl_lib_ops iwl1000_lib = { .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, - .rx_handler_setup = iwl5000_rx_handler_setup, - .setup_deferred_work = iwl5000_setup_deferred_work, - .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, + .rx_handler_setup = iwlagn_rx_handler_setup, + .setup_deferred_work = iwlagn_setup_deferred_work, + .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .load_ucode = iwlagn_load_ucode, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, @@ -180,7 +180,7 @@ static struct iwl_lib_ops iwl1000_lib = { .dump_fh = iwl_dump_fh, .init_alive_start = iwlagn_init_alive_start, .alive_notify = iwlagn_alive_notify, - .send_tx_power = iwl5000_send_tx_power, + .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .apm_ops = { .init = iwl_apm_init, @@ -190,25 +190,25 @@ static struct iwl_lib_ops iwl1000_lib = { }, .eeprom_ops = { .regulatory_bands = { - EEPROM_5000_REG_BAND_1_CHANNELS, - EEPROM_5000_REG_BAND_2_CHANNELS, - EEPROM_5000_REG_BAND_3_CHANNELS, - EEPROM_5000_REG_BAND_4_CHANNELS, - EEPROM_5000_REG_BAND_5_CHANNELS, - EEPROM_5000_REG_BAND_24_HT40_CHANNELS, - EEPROM_5000_REG_BAND_52_HT40_CHANNELS + EEPROM_REG_BAND_1_CHANNELS, + EEPROM_REG_BAND_2_CHANNELS, + EEPROM_REG_BAND_3_CHANNELS, + EEPROM_REG_BAND_4_CHANNELS, + EEPROM_REG_BAND_5_CHANNELS, + EEPROM_REG_BAND_24_HT40_CHANNELS, + EEPROM_REG_BAND_52_HT40_CHANNELS }, .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwl5000_eeprom_calib_version, - .query_addr = iwl5000_eeprom_query_addr, + .calib_version = iwlagn_eeprom_calib_version, + .query_addr = iwlagn_eeprom_query_addr, }, .post_associate = iwl_post_associate, .isr = iwl_isr_ict, .config_ap = iwl_config_ap, .temp_ops = { - .temperature = iwl5000_temperature, + .temperature = iwlagn_temperature, .set_ct_kill = iwl1000_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 9128ccd8dfae..4d3dda1beb25 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -47,7 +47,6 @@ #include "iwl-agn-led.h" #include "iwl-agn-hw.h" #include "iwl-5000-hw.h" -#include "iwl-6000-hw.h" /* Highest firmware API version supported */ #define IWL5000_UCODE_API_MAX 2 @@ -99,60 +98,6 @@ void iwl5000_nic_config(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } - -/* - * EEPROM - */ -static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) -{ - u16 offset = 0; - - if ((address & INDIRECT_ADDRESS) == 0) - return address; - - switch (address & INDIRECT_TYPE_MSK) { - case INDIRECT_HOST: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST); - break; - case INDIRECT_GENERAL: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL); - break; - case INDIRECT_REGULATORY: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY); - break; - case INDIRECT_CALIBRATION: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION); - break; - case INDIRECT_PROCESS_ADJST: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST); - break; - case INDIRECT_OTHERS: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS); - break; - default: - IWL_ERR(priv, "illegal indirect type: 0x%X\n", - address & INDIRECT_TYPE_MSK); - break; - } - - /* translate the offset from words to byte */ - return (address & ADDRESS_MSK) + (offset << 1); -} - -u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv) -{ - struct iwl_eeprom_calib_hdr { - u8 version; - u8 pa_type; - u16 voltage; - } *hdr; - - hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, - EEPROM_5000_CALIB_ALL); - return hdr->version; - -} - static struct iwl_sensitivity_ranges iwl5000_sensitivity = { .min_nrg_cck = 95, .max_nrg_cck = 0, /* not used, set to 0 */ @@ -204,14 +149,6 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = { .nrg_th_cca = 62, }; -const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, - size_t offset) -{ - u32 address = eeprom_indirect_address(priv, offset); - BUG_ON(address >= priv->cfg->eeprom_size); - return &priv->eeprom[address]; -} - static void iwl5150_set_ct_threshold(struct iwl_priv *priv) { const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; @@ -285,283 +222,6 @@ int iwl5000_hw_set_hw_params(struct iwl_priv *priv) return 0; } -static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) -{ - return le32_to_cpup((__le32 *)&tx_resp->status + - tx_resp->frame_count) & MAX_SN; -} - -static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, - struct iwl_ht_agg *agg, - struct iwl5000_tx_resp *tx_resp, - int txq_id, u16 start_idx) -{ - u16 status; - struct agg_tx_status *frame_status = &tx_resp->status; - struct ieee80211_tx_info *info = NULL; - struct ieee80211_hdr *hdr = NULL; - u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); - int i, sh, idx; - u16 seq; - - if (agg->wait_for_ba) - IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); - - agg->frame_count = tx_resp->frame_count; - agg->start_idx = start_idx; - agg->rate_n_flags = rate_n_flags; - agg->bitmap = 0; - - /* # frames attempted by Tx command */ - if (agg->frame_count == 1) { - /* Only one frame was attempted; no block-ack will arrive */ - status = le16_to_cpu(frame_status[0].status); - idx = start_idx; - - /* FIXME: code repetition */ - IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", - agg->frame_count, agg->start_idx, idx); - - info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); - info->status.rates[0].count = tx_resp->failure_frame + 1; - info->flags &= ~IEEE80211_TX_CTL_AMPDU; - info->flags |= iwl_tx_status_to_mac80211(status); - iwl_hwrate_to_tx_control(priv, rate_n_flags, info); - - /* FIXME: code repetition end */ - - IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", - status & 0xff, tx_resp->failure_frame); - IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags); - - agg->wait_for_ba = 0; - } else { - /* Two or more frames were attempted; expect block-ack */ - u64 bitmap = 0; - int start = agg->start_idx; - - /* Construct bit-map of pending frames within Tx window */ - for (i = 0; i < agg->frame_count; i++) { - u16 sc; - status = le16_to_cpu(frame_status[i].status); - seq = le16_to_cpu(frame_status[i].sequence); - idx = SEQ_TO_INDEX(seq); - txq_id = SEQ_TO_QUEUE(seq); - - if (status & (AGG_TX_STATE_FEW_BYTES_MSK | - AGG_TX_STATE_ABORT_MSK)) - continue; - - IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", - agg->frame_count, txq_id, idx); - - hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); - if (!hdr) { - IWL_ERR(priv, - "BUG_ON idx doesn't point to valid skb" - " idx=%d, txq_id=%d\n", idx, txq_id); - return -1; - } - - sc = le16_to_cpu(hdr->seq_ctrl); - if (idx != (SEQ_TO_SN(sc) & 0xff)) { - IWL_ERR(priv, - "BUG_ON idx doesn't match seq control" - " idx=%d, seq_idx=%d, seq=%d\n", - idx, SEQ_TO_SN(sc), - hdr->seq_ctrl); - return -1; - } - - IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", - i, idx, SEQ_TO_SN(sc)); - - sh = idx - start; - if (sh > 64) { - sh = (start - idx) + 0xff; - bitmap = bitmap << sh; - sh = 0; - start = idx; - } else if (sh < -64) - sh = 0xff - (start - idx); - else if (sh < 0) { - sh = start - idx; - start = idx; - bitmap = bitmap << sh; - sh = 0; - } - bitmap |= 1ULL << sh; - IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", - start, (unsigned long long)bitmap); - } - - agg->bitmap = bitmap; - agg->start_idx = start; - IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", - agg->frame_count, agg->start_idx, - (unsigned long long)agg->bitmap); - - if (bitmap) - agg->wait_for_ba = 1; - } - return 0; -} - -static void iwl5000_rx_reply_tx(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - u16 sequence = le16_to_cpu(pkt->hdr.sequence); - int txq_id = SEQ_TO_QUEUE(sequence); - int index = SEQ_TO_INDEX(sequence); - struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct ieee80211_tx_info *info; - struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; - u32 status = le16_to_cpu(tx_resp->status.status); - int tid; - int sta_id; - int freed; - - if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { - IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " - "is out of range [0-%d] %d %d\n", txq_id, - index, txq->q.n_bd, txq->q.write_ptr, - txq->q.read_ptr); - return; - } - - info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); - memset(&info->status, 0, sizeof(info->status)); - - tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; - sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; - - if (txq->sched_retry) { - const u32 scd_ssn = iwl5000_get_scd_ssn(tx_resp); - struct iwl_ht_agg *agg = NULL; - - agg = &priv->stations[sta_id].tid[tid].agg; - - iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); - - /* check if BAR is needed */ - if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) - info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - - if (txq->q.read_ptr != (scd_ssn & 0xff)) { - index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); - IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim " - "scd_ssn=%d idx=%d txq=%d swq=%d\n", - scd_ssn , index, txq_id, txq->swq_id); - - freed = iwl_tx_queue_reclaim(priv, txq_id, index); - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); - - if (priv->mac80211_registered && - (iwl_queue_space(&txq->q) > txq->q.low_mark) && - (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { - if (agg->state == IWL_AGG_OFF) - iwl_wake_queue(priv, txq_id); - else - iwl_wake_queue(priv, txq->swq_id); - } - } - } else { - BUG_ON(txq_id != txq->swq_id); - - info->status.rates[0].count = tx_resp->failure_frame + 1; - info->flags |= iwl_tx_status_to_mac80211(status); - iwl_hwrate_to_tx_control(priv, - le32_to_cpu(tx_resp->rate_n_flags), - info); - - IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " - "0x%x retries %d\n", - txq_id, - iwl_get_tx_fail_reason(status), status, - le32_to_cpu(tx_resp->rate_n_flags), - tx_resp->failure_frame); - - freed = iwl_tx_queue_reclaim(priv, txq_id, index); - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); - - if (priv->mac80211_registered && - (iwl_queue_space(&txq->q) > txq->q.low_mark)) - iwl_wake_queue(priv, txq_id); - } - - iwl_txq_check_empty(priv, sta_id, tid, txq_id); - - if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) - IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); -} - -void iwl5000_setup_deferred_work(struct iwl_priv *priv) -{ - /* in 5000 the tx power calibration is done in uCode */ - priv->disable_tx_power_cal = 1; -} - -void iwl5000_rx_handler_setup(struct iwl_priv *priv) -{ - /* init calibration handlers */ - priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = - iwlagn_rx_calib_result; - priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = - iwlagn_rx_calib_complete; - priv->rx_handlers[REPLY_TX] = iwl5000_rx_reply_tx; -} - - -int iwl5000_hw_valid_rtc_data_addr(u32 addr) -{ - return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && - (addr < IWLAGN_RTC_DATA_UPPER_BOUND); -} - -int iwl5000_send_tx_power(struct iwl_priv *priv) -{ - struct iwl5000_tx_power_dbm_cmd tx_power_cmd; - u8 tx_ant_cfg_cmd; - - /* half dBm need to multiply */ - tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); - - if (priv->tx_power_lmt_in_half_dbm && - priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) { - /* - * For the newer devices which using enhanced/extend tx power - * table in EEPROM, the format is in half dBm. driver need to - * convert to dBm format before report to mac80211. - * By doing so, there is a possibility of 1/2 dBm resolution - * lost. driver will perform "round-up" operation before - * reporting, but it will cause 1/2 dBm tx power over the - * regulatory limit. Perform the checking here, if the - * "tx_power_user_lmt" is higher than EEPROM value (in - * half-dBm format), lower the tx power based on EEPROM - */ - tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; - } - tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; - tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; - - if (IWL_UCODE_API(priv->ucode_ver) == 1) - tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1; - else - tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; - - return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd, - sizeof(tx_power_cmd), &tx_power_cmd, - NULL); -} - -void iwl5000_temperature(struct iwl_priv *priv) -{ - /* store temperature from statistics (in Celsius) */ - priv->temperature = le32_to_cpu(priv->statistics.general.temperature); - iwl_tt_handler(priv); -} - static void iwl5150_temperature(struct iwl_priv *priv) { u32 vt = 0; @@ -616,9 +276,9 @@ struct iwl_lib_ops iwl5000_lib = { .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, - .rx_handler_setup = iwl5000_rx_handler_setup, - .setup_deferred_work = iwl5000_setup_deferred_work, - .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, + .rx_handler_setup = iwlagn_rx_handler_setup, + .setup_deferred_work = iwlagn_setup_deferred_work, + .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, @@ -626,7 +286,7 @@ struct iwl_lib_ops iwl5000_lib = { .load_ucode = iwlagn_load_ucode, .init_alive_start = iwlagn_init_alive_start, .alive_notify = iwlagn_alive_notify, - .send_tx_power = iwl5000_send_tx_power, + .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl5000_hw_channel_switch, .apm_ops = { @@ -637,25 +297,25 @@ struct iwl_lib_ops iwl5000_lib = { }, .eeprom_ops = { .regulatory_bands = { - EEPROM_5000_REG_BAND_1_CHANNELS, - EEPROM_5000_REG_BAND_2_CHANNELS, - EEPROM_5000_REG_BAND_3_CHANNELS, - EEPROM_5000_REG_BAND_4_CHANNELS, - EEPROM_5000_REG_BAND_5_CHANNELS, - EEPROM_5000_REG_BAND_24_HT40_CHANNELS, - EEPROM_5000_REG_BAND_52_HT40_CHANNELS + EEPROM_REG_BAND_1_CHANNELS, + EEPROM_REG_BAND_2_CHANNELS, + EEPROM_REG_BAND_3_CHANNELS, + EEPROM_REG_BAND_4_CHANNELS, + EEPROM_REG_BAND_5_CHANNELS, + EEPROM_REG_BAND_24_HT40_CHANNELS, + EEPROM_REG_BAND_52_HT40_CHANNELS }, .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwl5000_eeprom_calib_version, - .query_addr = iwl5000_eeprom_query_addr, + .calib_version = iwlagn_eeprom_calib_version, + .query_addr = iwlagn_eeprom_query_addr, }, .post_associate = iwl_post_associate, .isr = iwl_isr_ict, .config_ap = iwl_config_ap, .temp_ops = { - .temperature = iwl5000_temperature, + .temperature = iwlagn_temperature, .set_ct_kill = iwl5000_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, @@ -674,16 +334,16 @@ static struct iwl_lib_ops iwl5150_lib = { .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, - .rx_handler_setup = iwl5000_rx_handler_setup, - .setup_deferred_work = iwl5000_setup_deferred_work, - .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, + .rx_handler_setup = iwlagn_rx_handler_setup, + .setup_deferred_work = iwlagn_setup_deferred_work, + .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, .load_ucode = iwlagn_load_ucode, .init_alive_start = iwlagn_init_alive_start, .alive_notify = iwlagn_alive_notify, - .send_tx_power = iwl5000_send_tx_power, + .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl5000_hw_channel_switch, .apm_ops = { @@ -694,19 +354,19 @@ static struct iwl_lib_ops iwl5150_lib = { }, .eeprom_ops = { .regulatory_bands = { - EEPROM_5000_REG_BAND_1_CHANNELS, - EEPROM_5000_REG_BAND_2_CHANNELS, - EEPROM_5000_REG_BAND_3_CHANNELS, - EEPROM_5000_REG_BAND_4_CHANNELS, - EEPROM_5000_REG_BAND_5_CHANNELS, - EEPROM_5000_REG_BAND_24_HT40_CHANNELS, - EEPROM_5000_REG_BAND_52_HT40_CHANNELS + EEPROM_REG_BAND_1_CHANNELS, + EEPROM_REG_BAND_2_CHANNELS, + EEPROM_REG_BAND_3_CHANNELS, + EEPROM_REG_BAND_4_CHANNELS, + EEPROM_REG_BAND_5_CHANNELS, + EEPROM_REG_BAND_24_HT40_CHANNELS, + EEPROM_REG_BAND_52_HT40_CHANNELS }, .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwl5000_eeprom_calib_version, - .query_addr = iwl5000_eeprom_query_addr, + .calib_version = iwlagn_eeprom_calib_version, + .query_addr = iwlagn_eeprom_query_addr, }, .post_associate = iwl_post_associate, .isr = iwl_isr_ict, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 96f4fa6e0e21..92b407f89d32 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -234,9 +234,9 @@ static struct iwl_lib_ops iwl6000_lib = { .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, - .rx_handler_setup = iwl5000_rx_handler_setup, - .setup_deferred_work = iwl5000_setup_deferred_work, - .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, + .rx_handler_setup = iwlagn_rx_handler_setup, + .setup_deferred_work = iwlagn_setup_deferred_work, + .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .load_ucode = iwlagn_load_ucode, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, @@ -244,7 +244,7 @@ static struct iwl_lib_ops iwl6000_lib = { .dump_fh = iwl_dump_fh, .init_alive_start = iwlagn_init_alive_start, .alive_notify = iwlagn_alive_notify, - .send_tx_power = iwl5000_send_tx_power, + .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl6000_hw_channel_switch, .apm_ops = { @@ -255,26 +255,26 @@ static struct iwl_lib_ops iwl6000_lib = { }, .eeprom_ops = { .regulatory_bands = { - EEPROM_5000_REG_BAND_1_CHANNELS, - EEPROM_5000_REG_BAND_2_CHANNELS, - EEPROM_5000_REG_BAND_3_CHANNELS, - EEPROM_5000_REG_BAND_4_CHANNELS, - EEPROM_5000_REG_BAND_5_CHANNELS, - EEPROM_5000_REG_BAND_24_HT40_CHANNELS, - EEPROM_5000_REG_BAND_52_HT40_CHANNELS + EEPROM_REG_BAND_1_CHANNELS, + EEPROM_REG_BAND_2_CHANNELS, + EEPROM_REG_BAND_3_CHANNELS, + EEPROM_REG_BAND_4_CHANNELS, + EEPROM_REG_BAND_5_CHANNELS, + EEPROM_REG_BAND_24_HT40_CHANNELS, + EEPROM_REG_BAND_52_HT40_CHANNELS }, .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwl5000_eeprom_calib_version, - .query_addr = iwl5000_eeprom_query_addr, + .calib_version = iwlagn_eeprom_calib_version, + .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, .post_associate = iwl_post_associate, .isr = iwl_isr_ict, .config_ap = iwl_config_ap, .temp_ops = { - .temperature = iwl5000_temperature, + .temperature = iwlagn_temperature, .set_ct_kill = iwl6000_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, @@ -301,9 +301,9 @@ static struct iwl_lib_ops iwl6050_lib = { .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, - .rx_handler_setup = iwl5000_rx_handler_setup, - .setup_deferred_work = iwl5000_setup_deferred_work, - .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, + .rx_handler_setup = iwlagn_rx_handler_setup, + .setup_deferred_work = iwlagn_setup_deferred_work, + .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .load_ucode = iwlagn_load_ucode, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, @@ -311,7 +311,7 @@ static struct iwl_lib_ops iwl6050_lib = { .dump_fh = iwl_dump_fh, .init_alive_start = iwlagn_init_alive_start, .alive_notify = iwlagn_alive_notify, - .send_tx_power = iwl5000_send_tx_power, + .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl6000_hw_channel_switch, .apm_ops = { @@ -322,26 +322,26 @@ static struct iwl_lib_ops iwl6050_lib = { }, .eeprom_ops = { .regulatory_bands = { - EEPROM_5000_REG_BAND_1_CHANNELS, - EEPROM_5000_REG_BAND_2_CHANNELS, - EEPROM_5000_REG_BAND_3_CHANNELS, - EEPROM_5000_REG_BAND_4_CHANNELS, - EEPROM_5000_REG_BAND_5_CHANNELS, - EEPROM_5000_REG_BAND_24_HT40_CHANNELS, - EEPROM_5000_REG_BAND_52_HT40_CHANNELS + EEPROM_REG_BAND_1_CHANNELS, + EEPROM_REG_BAND_2_CHANNELS, + EEPROM_REG_BAND_3_CHANNELS, + EEPROM_REG_BAND_4_CHANNELS, + EEPROM_REG_BAND_5_CHANNELS, + EEPROM_REG_BAND_24_HT40_CHANNELS, + EEPROM_REG_BAND_52_HT40_CHANNELS }, .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwl5000_eeprom_calib_version, - .query_addr = iwl5000_eeprom_query_addr, + .calib_version = iwlagn_eeprom_calib_version, + .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, .post_associate = iwl_post_associate, .isr = iwl_isr_ict, .config_ap = iwl_config_ap, .temp_ops = { - .temperature = iwl5000_temperature, + .temperature = iwlagn_temperature, .set_ct_kill = iwl6000_set_ct_threshold, .set_calib_version = iwl6050_set_calib_version, }, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c new file mode 100644 index 000000000000..e4c0726601af --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -0,0 +1,377 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#include +#include +#include +#include + +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-io.h" +#include "iwl-helpers.h" +#include "iwl-agn-hw.h" +#include "iwl-agn.h" + +static inline u32 iwlagn_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) +{ + return le32_to_cpup((__le32 *)&tx_resp->status + + tx_resp->frame_count) & MAX_SN; +} + +static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, + struct iwl_ht_agg *agg, + struct iwl5000_tx_resp *tx_resp, + int txq_id, u16 start_idx) +{ + u16 status; + struct agg_tx_status *frame_status = &tx_resp->status; + struct ieee80211_tx_info *info = NULL; + struct ieee80211_hdr *hdr = NULL; + u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); + int i, sh, idx; + u16 seq; + + if (agg->wait_for_ba) + IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); + + agg->frame_count = tx_resp->frame_count; + agg->start_idx = start_idx; + agg->rate_n_flags = rate_n_flags; + agg->bitmap = 0; + + /* # frames attempted by Tx command */ + if (agg->frame_count == 1) { + /* Only one frame was attempted; no block-ack will arrive */ + status = le16_to_cpu(frame_status[0].status); + idx = start_idx; + + /* FIXME: code repetition */ + IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", + agg->frame_count, agg->start_idx, idx); + + info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); + info->status.rates[0].count = tx_resp->failure_frame + 1; + info->flags &= ~IEEE80211_TX_CTL_AMPDU; + info->flags |= iwl_tx_status_to_mac80211(status); + iwl_hwrate_to_tx_control(priv, rate_n_flags, info); + + /* FIXME: code repetition end */ + + IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", + status & 0xff, tx_resp->failure_frame); + IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags); + + agg->wait_for_ba = 0; + } else { + /* Two or more frames were attempted; expect block-ack */ + u64 bitmap = 0; + int start = agg->start_idx; + + /* Construct bit-map of pending frames within Tx window */ + for (i = 0; i < agg->frame_count; i++) { + u16 sc; + status = le16_to_cpu(frame_status[i].status); + seq = le16_to_cpu(frame_status[i].sequence); + idx = SEQ_TO_INDEX(seq); + txq_id = SEQ_TO_QUEUE(seq); + + if (status & (AGG_TX_STATE_FEW_BYTES_MSK | + AGG_TX_STATE_ABORT_MSK)) + continue; + + IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", + agg->frame_count, txq_id, idx); + + hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); + if (!hdr) { + IWL_ERR(priv, + "BUG_ON idx doesn't point to valid skb" + " idx=%d, txq_id=%d\n", idx, txq_id); + return -1; + } + + sc = le16_to_cpu(hdr->seq_ctrl); + if (idx != (SEQ_TO_SN(sc) & 0xff)) { + IWL_ERR(priv, + "BUG_ON idx doesn't match seq control" + " idx=%d, seq_idx=%d, seq=%d\n", + idx, SEQ_TO_SN(sc), + hdr->seq_ctrl); + return -1; + } + + IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", + i, idx, SEQ_TO_SN(sc)); + + sh = idx - start; + if (sh > 64) { + sh = (start - idx) + 0xff; + bitmap = bitmap << sh; + sh = 0; + start = idx; + } else if (sh < -64) + sh = 0xff - (start - idx); + else if (sh < 0) { + sh = start - idx; + start = idx; + bitmap = bitmap << sh; + sh = 0; + } + bitmap |= 1ULL << sh; + IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", + start, (unsigned long long)bitmap); + } + + agg->bitmap = bitmap; + agg->start_idx = start; + IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", + agg->frame_count, agg->start_idx, + (unsigned long long)agg->bitmap); + + if (bitmap) + agg->wait_for_ba = 1; + } + return 0; +} + +static void iwlagn_rx_reply_tx(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + u16 sequence = le16_to_cpu(pkt->hdr.sequence); + int txq_id = SEQ_TO_QUEUE(sequence); + int index = SEQ_TO_INDEX(sequence); + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct ieee80211_tx_info *info; + struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; + u32 status = le16_to_cpu(tx_resp->status.status); + int tid; + int sta_id; + int freed; + + if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { + IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " + "is out of range [0-%d] %d %d\n", txq_id, + index, txq->q.n_bd, txq->q.write_ptr, + txq->q.read_ptr); + return; + } + + info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); + memset(&info->status, 0, sizeof(info->status)); + + tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; + sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; + + if (txq->sched_retry) { + const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); + struct iwl_ht_agg *agg = NULL; + + agg = &priv->stations[sta_id].tid[tid].agg; + + iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); + + /* check if BAR is needed */ + if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) + info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + + if (txq->q.read_ptr != (scd_ssn & 0xff)) { + index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); + IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim " + "scd_ssn=%d idx=%d txq=%d swq=%d\n", + scd_ssn , index, txq_id, txq->swq_id); + + freed = iwl_tx_queue_reclaim(priv, txq_id, index); + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); + + if (priv->mac80211_registered && + (iwl_queue_space(&txq->q) > txq->q.low_mark) && + (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { + if (agg->state == IWL_AGG_OFF) + iwl_wake_queue(priv, txq_id); + else + iwl_wake_queue(priv, txq->swq_id); + } + } + } else { + BUG_ON(txq_id != txq->swq_id); + + info->status.rates[0].count = tx_resp->failure_frame + 1; + info->flags |= iwl_tx_status_to_mac80211(status); + iwl_hwrate_to_tx_control(priv, + le32_to_cpu(tx_resp->rate_n_flags), + info); + + IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " + "0x%x retries %d\n", + txq_id, + iwl_get_tx_fail_reason(status), status, + le32_to_cpu(tx_resp->rate_n_flags), + tx_resp->failure_frame); + + freed = iwl_tx_queue_reclaim(priv, txq_id, index); + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); + + if (priv->mac80211_registered && + (iwl_queue_space(&txq->q) > txq->q.low_mark)) + iwl_wake_queue(priv, txq_id); + } + + iwl_txq_check_empty(priv, sta_id, tid, txq_id); + + if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) + IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); +} + +void iwlagn_rx_handler_setup(struct iwl_priv *priv) +{ + /* init calibration handlers */ + priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = + iwlagn_rx_calib_result; + priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = + iwlagn_rx_calib_complete; + priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; +} + +void iwlagn_setup_deferred_work(struct iwl_priv *priv) +{ + /* in agn, the tx power calibration is done in uCode */ + priv->disable_tx_power_cal = 1; +} + +int iwlagn_hw_valid_rtc_data_addr(u32 addr) +{ + return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && + (addr < IWLAGN_RTC_DATA_UPPER_BOUND); +} + +int iwlagn_send_tx_power(struct iwl_priv *priv) +{ + struct iwl5000_tx_power_dbm_cmd tx_power_cmd; + u8 tx_ant_cfg_cmd; + + /* half dBm need to multiply */ + tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); + + if (priv->tx_power_lmt_in_half_dbm && + priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) { + /* + * For the newer devices which using enhanced/extend tx power + * table in EEPROM, the format is in half dBm. driver need to + * convert to dBm format before report to mac80211. + * By doing so, there is a possibility of 1/2 dBm resolution + * lost. driver will perform "round-up" operation before + * reporting, but it will cause 1/2 dBm tx power over the + * regulatory limit. Perform the checking here, if the + * "tx_power_user_lmt" is higher than EEPROM value (in + * half-dBm format), lower the tx power based on EEPROM + */ + tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; + } + tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; + tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; + + if (IWL_UCODE_API(priv->ucode_ver) == 1) + tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1; + else + tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; + + return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd, + sizeof(tx_power_cmd), &tx_power_cmd, + NULL); +} + +void iwlagn_temperature(struct iwl_priv *priv) +{ + /* store temperature from statistics (in Celsius) */ + priv->temperature = le32_to_cpu(priv->statistics.general.temperature); + iwl_tt_handler(priv); +} + +u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv) +{ + struct iwl_eeprom_calib_hdr { + u8 version; + u8 pa_type; + u16 voltage; + } *hdr; + + hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, + EEPROM_5000_CALIB_ALL); + return hdr->version; + +} + +/* + * EEPROM + */ +static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) +{ + u16 offset = 0; + + if ((address & INDIRECT_ADDRESS) == 0) + return address; + + switch (address & INDIRECT_TYPE_MSK) { + case INDIRECT_HOST: + offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST); + break; + case INDIRECT_GENERAL: + offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL); + break; + case INDIRECT_REGULATORY: + offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY); + break; + case INDIRECT_CALIBRATION: + offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION); + break; + case INDIRECT_PROCESS_ADJST: + offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST); + break; + case INDIRECT_OTHERS: + offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS); + break; + default: + IWL_ERR(priv, "illegal indirect type: 0x%X\n", + address & INDIRECT_TYPE_MSK); + break; + } + + /* translate the offset from words to byte */ + return (address & ADDRESS_MSK) + (offset << 1); +} + +const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, + size_t offset) +{ + u32 address = eeprom_indirect_address(priv, offset); + BUG_ON(address >= priv->cfg->eeprom_size); + return &priv->eeprom[address]; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 9b6676569827..aa49e6670979 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -103,4 +103,14 @@ void iwlagn_rx_calib_complete(struct iwl_priv *priv, void iwlagn_init_alive_start(struct iwl_priv *priv); int iwlagn_alive_notify(struct iwl_priv *priv); +/* lib */ +void iwlagn_rx_handler_setup(struct iwl_priv *priv); +void iwlagn_setup_deferred_work(struct iwl_priv *priv); +int iwlagn_hw_valid_rtc_data_addr(u32 addr); +int iwlagn_send_tx_power(struct iwl_priv *priv); +void iwlagn_temperature(struct iwl_priv *priv); +u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); +const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, + size_t offset); + #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 4e1ba824dc50..907a30a97d6c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -188,19 +188,19 @@ struct iwl_eeprom_enhanced_txpwr { /* 5000 regulatory - indirect access */ #define EEPROM_5000_REG_SKU_ID ((0x02)\ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 4 bytes */ -#define EEPROM_5000_REG_BAND_1_CHANNELS ((0x08)\ +#define EEPROM_REG_BAND_1_CHANNELS ((0x08)\ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */ -#define EEPROM_5000_REG_BAND_2_CHANNELS ((0x26)\ +#define EEPROM_REG_BAND_2_CHANNELS ((0x26)\ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 26 bytes */ -#define EEPROM_5000_REG_BAND_3_CHANNELS ((0x42)\ +#define EEPROM_REG_BAND_3_CHANNELS ((0x42)\ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ -#define EEPROM_5000_REG_BAND_4_CHANNELS ((0x5C)\ +#define EEPROM_REG_BAND_4_CHANNELS ((0x5C)\ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ -#define EEPROM_5000_REG_BAND_5_CHANNELS ((0x74)\ +#define EEPROM_REG_BAND_5_CHANNELS ((0x74)\ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */ -#define EEPROM_5000_REG_BAND_24_HT40_CHANNELS ((0x82)\ +#define EEPROM_REG_BAND_24_HT40_CHANNELS ((0x82)\ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ -#define EEPROM_5000_REG_BAND_52_HT40_CHANNELS ((0x92)\ +#define EEPROM_REG_BAND_52_HT40_CHANNELS ((0x92)\ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ /* 6000 and up regulatory tx power - indirect access */ -- cgit v1.2.3 From 00e70590dc2707043b82c0cf9a6929b81e640fee Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 16 Mar 2010 12:37:26 -0700 Subject: iwlwifi: each device has its own eeprom tx power version Each device has it own eeprom, so the tx power version could be different, define TX_POWER_VERSION per device. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-6000.c | 12 ++++++------ drivers/net/wireless/iwlwifi/iwl-eeprom.h | 3 +++ 3 files changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index a99945be6d07..cf0aa71abdf3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -234,7 +234,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { .ops = &iwl1000_ops, .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_1000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, + .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, @@ -264,7 +264,7 @@ struct iwl_cfg iwl1000_bg_cfg = { .ops = &iwl1000_ops, .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_1000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, + .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 92b407f89d32..cb9c2d6905f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -371,7 +371,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .ops = &iwl6000_ops, .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, + .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, @@ -404,7 +404,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .ops = &iwl6000_ops, .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, + .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, @@ -436,7 +436,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .ops = &iwl6000_ops, .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, + .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, @@ -468,7 +468,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .ops = &iwl6050_ops, .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6050_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, + .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, @@ -501,7 +501,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { .ops = &iwl6050_ops, .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6050_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, + .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, @@ -533,7 +533,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .ops = &iwl6000_ops, .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, + .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwl50_mod_params, diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 907a30a97d6c..cb6d50b78140 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -261,12 +261,15 @@ struct iwl_eeprom_enhanced_txpwr { #define EEPROM_5050_EEPROM_VERSION (0x21E) /* 1000 Specific */ +#define EEPROM_1000_TX_POWER_VERSION (4) #define EEPROM_1000_EEPROM_VERSION (0x15C) /* 6x00 Specific */ +#define EEPROM_6000_TX_POWER_VERSION (4) #define EEPROM_6000_EEPROM_VERSION (0x434) /* 6x50 Specific */ +#define EEPROM_6050_TX_POWER_VERSION (4) #define EEPROM_6050_EEPROM_VERSION (0x532) /* OTP */ -- cgit v1.2.3 From 348ee7cd57831c47373dd157f138c558daaf129d Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 16 Mar 2010 12:37:27 -0700 Subject: iwlwifi: move agn module parameter structure to common place agn module parameter data structure shared by all agn devices, move it iwl-agn-lib.c file. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-5000.c | 31 ++++++++++++------------------ drivers/net/wireless/iwlwifi/iwl-6000.c | 12 ++++++------ drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 1 + 5 files changed, 27 insertions(+), 27 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index cf0aa71abdf3..b941b3e95697 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -237,7 +237,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_A, .valid_rx_ant = ANT_AB, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, @@ -267,7 +267,7 @@ struct iwl_cfg iwl1000_bg_cfg = { .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_A, .valid_rx_ant = ANT_AB, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 4d3dda1beb25..6c09b2477b95 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -397,13 +397,6 @@ static const struct iwl_ops iwl5150_ops = { .led = &iwlagn_led_ops, }; -struct iwl_mod_params iwl50_mod_params = { - .amsdu_size_8K = 1, - .restart_fw = 1, - /* the rest are 0 by default */ -}; - - struct iwl_cfg iwl5300_agn_cfg = { .name = "Intel(R) Ultimate N WiFi Link 5300 AGN", .fw_name_pre = IWL5000_FW_PRE, @@ -416,7 +409,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, @@ -443,7 +436,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_B, .valid_rx_ant = ANT_AB, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, @@ -470,7 +463,7 @@ struct iwl_cfg iwl5100_abg_cfg = { .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_B, .valid_rx_ant = ANT_AB, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, @@ -495,7 +488,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_B, .valid_rx_ant = ANT_AB, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, @@ -522,7 +515,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, @@ -549,7 +542,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_A, .valid_rx_ant = ANT_AB, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, @@ -576,7 +569,7 @@ struct iwl_cfg iwl5150_abg_cfg = { .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_A, .valid_rx_ant = ANT_AB, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, @@ -592,15 +585,15 @@ struct iwl_cfg iwl5150_abg_cfg = { MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); -module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, S_IRUGO); +module_param_named(swcrypto50, iwlagn_mod_params.sw_crypto, bool, S_IRUGO); MODULE_PARM_DESC(swcrypto50, "using software crypto engine (default 0 [hardware])\n"); -module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, S_IRUGO); +module_param_named(queues_num50, iwlagn_mod_params.num_of_queues, int, S_IRUGO); MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); -module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, S_IRUGO); +module_param_named(11n_disable50, iwlagn_mod_params.disable_11n, int, S_IRUGO); MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality"); -module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, +module_param_named(amsdu_size_8K50, iwlagn_mod_params.amsdu_size_8K, int, S_IRUGO); MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series"); -module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, S_IRUGO); +module_param_named(fw_restart50, iwlagn_mod_params.restart_fw, int, S_IRUGO); MODULE_PARM_DESC(fw_restart50, "restart firmware in case of error"); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index cb9c2d6905f9..f89e1c794388 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -374,7 +374,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_BC, .valid_rx_ant = ANT_BC, .pll_cfg_val = 0, @@ -407,7 +407,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_BC, .valid_rx_ant = ANT_BC, .pll_cfg_val = 0, @@ -439,7 +439,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_BC, .valid_rx_ant = ANT_BC, .pll_cfg_val = 0, @@ -471,7 +471,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_AB, .pll_cfg_val = 0, @@ -504,7 +504,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_AB, .pll_cfg_val = 0, @@ -536,7 +536,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .mod_params = &iwl50_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC, .pll_cfg_val = 0, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index e4c0726601af..c826b7f54256 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -375,3 +375,9 @@ const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, BUG_ON(address >= priv->cfg->eeprom_size); return &priv->eeprom[address]; } + +struct iwl_mod_params iwlagn_mod_params = { + .amsdu_size_8K = 1, + .restart_fw = 1, + /* the rest are 0 by default */ +}; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index aa49e6670979..ad9b47e1a817 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -65,6 +65,7 @@ #include "iwl-dev.h" +extern struct iwl_mod_params iwlagn_mod_params; extern struct iwl_ucode_ops iwlagn_ucode; extern struct iwl_hcmd_ops iwlagn_hcmd; extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; -- cgit v1.2.3 From 74bcdb33e99f49ef5202dd2f8109945b4570edc2 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 17 Mar 2010 13:34:34 -0700 Subject: iwlwifi: move agn only tx functions from iwlcore to iwlagn Identify the tx functions only used by agn driver and move those from iwlcore to iwlagn. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-4965.c | 7 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 136 +++- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 1022 ++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 14 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 17 + drivers/net/wireless/iwlwifi/iwl-core.c | 51 -- drivers/net/wireless/iwlwifi/iwl-core.h | 12 - drivers/net/wireless/iwlwifi/iwl-devtrace.c | 1 + drivers/net/wireless/iwlwifi/iwl-rx.c | 80 --- drivers/net/wireless/iwlwifi/iwl-sta.c | 1 + drivers/net/wireless/iwlwifi/iwl-tx.c | 1029 --------------------------- 11 files changed, 1185 insertions(+), 1185 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 3949133d9ee2..cee31cdf0a22 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -46,6 +46,7 @@ #include "iwl-calib.h" #include "iwl-sta.h" #include "iwl-agn-led.h" +#include "iwl-agn.h" static int iwl4965_send_tx_power(struct iwl_priv *priv); static int iwl4965_hw_get_temperature(struct iwl_priv *priv); @@ -2020,7 +2021,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " "%d index %d\n", scd_ssn , index); - freed = iwl_tx_queue_reclaim(priv, txq_id, index); + freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); iwl_free_tfds_in_queue(priv, sta_id, tid, freed); if (priv->mac80211_registered && @@ -2046,7 +2047,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, le32_to_cpu(tx_resp->rate_n_flags), tx_resp->failure_frame); - freed = iwl_tx_queue_reclaim(priv, txq_id, index); + freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); if (qc && likely(sta_id != IWL_INVALID_STATION)) priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; @@ -2056,7 +2057,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, } if (qc && likely(sta_id != IWL_INVALID_STATION)) - iwl_txq_check_empty(priv, sta_id, tid, txq_id); + iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index c826b7f54256..6f9d52d04464 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -208,7 +208,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, "scd_ssn=%d idx=%d txq=%d swq=%d\n", scd_ssn , index, txq_id, txq->swq_id); - freed = iwl_tx_queue_reclaim(priv, txq_id, index); + freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); iwl_free_tfds_in_queue(priv, sta_id, tid, freed); if (priv->mac80211_registered && @@ -236,7 +236,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, le32_to_cpu(tx_resp->rate_n_flags), tx_resp->failure_frame); - freed = iwl_tx_queue_reclaim(priv, txq_id, index); + freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); iwl_free_tfds_in_queue(priv, sta_id, tid, freed); if (priv->mac80211_registered && @@ -244,7 +244,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, iwl_wake_queue(priv, txq_id); } - iwl_txq_check_empty(priv, sta_id, tid, txq_id); + iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); @@ -381,3 +381,133 @@ struct iwl_mod_params iwlagn_mod_params = { .restart_fw = 1, /* the rest are 0 by default */ }; + +void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) +{ + unsigned long flags; + int i; + spin_lock_irqsave(&rxq->lock, flags); + INIT_LIST_HEAD(&rxq->rx_free); + INIT_LIST_HEAD(&rxq->rx_used); + /* Fill the rx_used queue with _all_ of the Rx buffers */ + for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { + /* In the reset function, these buffers may have been allocated + * to an SKB, so we need to unmap and free potential storage */ + if (rxq->pool[i].page != NULL) { + pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, + PAGE_SIZE << priv->hw_params.rx_page_order, + PCI_DMA_FROMDEVICE); + __iwl_free_pages(priv, rxq->pool[i].page); + rxq->pool[i].page = NULL; + } + list_add_tail(&rxq->pool[i].list, &rxq->rx_used); + } + + /* Set us so that we have processed and used all buffers, but have + * not restocked the Rx queue with fresh buffers */ + rxq->read = rxq->write = 0; + rxq->write_actual = 0; + rxq->free_count = 0; + spin_unlock_irqrestore(&rxq->lock, flags); +} + +int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) +{ + u32 rb_size; + const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ + u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ + + if (!priv->cfg->use_isr_legacy) + rb_timeout = RX_RB_TIMEOUT; + + if (priv->cfg->mod_params->amsdu_size_8K) + rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; + else + rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; + + /* Stop Rx DMA */ + iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + + /* Reset driver's Rx queue write index */ + iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); + + /* Tell device where to find RBD circular buffer in DRAM */ + iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, + (u32)(rxq->dma_addr >> 8)); + + /* Tell device where in DRAM to update its Rx status */ + iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, + rxq->rb_stts_dma >> 4); + + /* Enable Rx DMA + * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in + * the credit mechanism in 5000 HW RX FIFO + * Direct rx interrupts to hosts + * Rx buffer size 4 or 8k + * RB timeout 0x10 + * 256 RBDs + */ + iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, + FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | + FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | + FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | + FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | + rb_size| + (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| + (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); + + /* Set interrupt coalescing timer to default (2048 usecs) */ + iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); + + return 0; +} + +int iwlagn_hw_nic_init(struct iwl_priv *priv) +{ + unsigned long flags; + struct iwl_rx_queue *rxq = &priv->rxq; + int ret; + + /* nic_init */ + spin_lock_irqsave(&priv->lock, flags); + priv->cfg->ops->lib->apm_ops.init(priv); + + /* Set interrupt coalescing calibration timer to default (512 usecs) */ + iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); + + spin_unlock_irqrestore(&priv->lock, flags); + + ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); + + priv->cfg->ops->lib->apm_ops.config(priv); + + /* Allocate the RX queue, or reset if it is already allocated */ + if (!rxq->bd) { + ret = iwl_rx_queue_alloc(priv); + if (ret) { + IWL_ERR(priv, "Unable to initialize Rx queue\n"); + return -ENOMEM; + } + } else + iwlagn_rx_queue_reset(priv, rxq); + + iwl_rx_replenish(priv); + + iwlagn_rx_init(priv, rxq); + + spin_lock_irqsave(&priv->lock, flags); + + rxq->need_update = 1; + iwl_rx_queue_update_write_ptr(priv, rxq); + + spin_unlock_irqrestore(&priv->lock, flags); + + /* Allocate and init all Tx and Command queues */ + ret = iwlagn_txq_ctx_reset(priv); + if (ret) + return ret; + + set_bit(STATUS_INIT, &priv->status); + + return 0; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 43bdd9d9df4d..4e4b70d10804 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -36,8 +36,61 @@ #include "iwl-core.h" #include "iwl-sta.h" #include "iwl-io.h" +#include "iwl-helpers.h" #include "iwl-agn-hw.h" +/* + * mac80211 queues, ACs, hardware queues, FIFOs. + * + * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues + * + * Mac80211 uses the following numbers, which we get as from it + * by way of skb_get_queue_mapping(skb): + * + * VO 0 + * VI 1 + * BE 2 + * BK 3 + * + * + * Regular (not A-MPDU) frames are put into hardware queues corresponding + * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their + * own queue per aggregation session (RA/TID combination), such queues are + * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In + * order to map frames to the right queue, we also need an AC->hw queue + * mapping. This is implemented here. + * + * Due to the way hw queues are set up (by the hw specific modules like + * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity + * mapping. + */ + +static const u8 tid_to_ac[] = { + /* this matches the mac80211 numbers */ + 2, 3, 3, 2, 1, 1, 0, 0 +}; + +static const u8 ac_to_fifo[] = { + IWL_TX_FIFO_VO, + IWL_TX_FIFO_VI, + IWL_TX_FIFO_BE, + IWL_TX_FIFO_BK, +}; + +static inline int get_fifo_from_ac(u8 ac) +{ + return ac_to_fifo[ac]; +} + +static inline int get_fifo_from_tid(u16 tid) +{ + if (likely(tid < ARRAY_SIZE(tid_to_ac))) + return get_fifo_from_ac(tid_to_ac[tid]); + + /* no support for TIDs 8-15 yet */ + return -EINVAL; +} + /** * iwlagn_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array */ @@ -266,3 +319,972 @@ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask) { iwl_write_prph(priv, IWL50_SCD_TXFACT, mask); } + +static inline int get_queue_from_ac(u16 ac) +{ + return ac; +} + +/* + * handle build REPLY_TX command notification. + */ +static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, + struct iwl_tx_cmd *tx_cmd, + struct ieee80211_tx_info *info, + struct ieee80211_hdr *hdr, + u8 std_id) +{ + __le16 fc = hdr->frame_control; + __le32 tx_flags = tx_cmd->tx_flags; + + tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { + tx_flags |= TX_CMD_FLG_ACK_MSK; + if (ieee80211_is_mgmt(fc)) + tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; + if (ieee80211_is_probe_resp(fc) && + !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) + tx_flags |= TX_CMD_FLG_TSF_MSK; + } else { + tx_flags &= (~TX_CMD_FLG_ACK_MSK); + tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; + } + + if (ieee80211_is_back_req(fc)) + tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; + + + tx_cmd->sta_id = std_id; + if (ieee80211_has_morefrags(fc)) + tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; + + if (ieee80211_is_data_qos(fc)) { + u8 *qc = ieee80211_get_qos_ctl(hdr); + tx_cmd->tid_tspec = qc[0] & 0xf; + tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; + } else { + tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; + } + + priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); + + if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) + tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; + + tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); + if (ieee80211_is_mgmt(fc)) { + if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) + tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3); + else + tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2); + } else { + tx_cmd->timeout.pm_frame_timeout = 0; + } + + tx_cmd->driver_txop = 0; + tx_cmd->tx_flags = tx_flags; + tx_cmd->next_frame_len = 0; +} + +#define RTS_DFAULT_RETRY_LIMIT 60 + +static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, + struct iwl_tx_cmd *tx_cmd, + struct ieee80211_tx_info *info, + __le16 fc) +{ + u32 rate_flags; + int rate_idx; + u8 rts_retry_limit; + u8 data_retry_limit; + u8 rate_plcp; + + /* Set retry limit on DATA packets and Probe Responses*/ + if (ieee80211_is_probe_resp(fc)) + data_retry_limit = 3; + else + data_retry_limit = IWL_DEFAULT_TX_RETRY; + tx_cmd->data_retry_limit = data_retry_limit; + + /* Set retry limit on RTS packets */ + rts_retry_limit = RTS_DFAULT_RETRY_LIMIT; + if (data_retry_limit < rts_retry_limit) + rts_retry_limit = data_retry_limit; + tx_cmd->rts_retry_limit = rts_retry_limit; + + /* DATA packets will use the uCode station table for rate/antenna + * selection */ + if (ieee80211_is_data(fc)) { + tx_cmd->initial_rate_index = 0; + tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; + return; + } + + /** + * If the current TX rate stored in mac80211 has the MCS bit set, it's + * not really a TX rate. Thus, we use the lowest supported rate for + * this band. Also use the lowest supported rate if the stored rate + * index is invalid. + */ + rate_idx = info->control.rates[0].idx; + if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || + (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) + rate_idx = rate_lowest_index(&priv->bands[info->band], + info->control.sta); + /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ + if (info->band == IEEE80211_BAND_5GHZ) + rate_idx += IWL_FIRST_OFDM_RATE; + /* Get PLCP rate for tx_cmd->rate_n_flags */ + rate_plcp = iwl_rates[rate_idx].plcp; + /* Zero out flags for this packet */ + rate_flags = 0; + + /* Set CCK flag as needed */ + if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) + rate_flags |= RATE_MCS_CCK_MSK; + + /* Set up RTS and CTS flags for certain packets */ + switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { + case cpu_to_le16(IEEE80211_STYPE_AUTH): + case cpu_to_le16(IEEE80211_STYPE_DEAUTH): + case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): + case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): + if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { + tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; + tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; + } + break; + default: + break; + } + + /* Set up antennas */ + priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); + rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); + + /* Set the rate in the TX cmd */ + tx_cmd->rate_n_flags = iwl_hw_set_rate_n_flags(rate_plcp, rate_flags); +} + +static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, + struct ieee80211_tx_info *info, + struct iwl_tx_cmd *tx_cmd, + struct sk_buff *skb_frag, + int sta_id) +{ + struct ieee80211_key_conf *keyconf = info->control.hw_key; + + switch (keyconf->alg) { + case ALG_CCMP: + tx_cmd->sec_ctl = TX_CMD_SEC_CCM; + memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); + if (info->flags & IEEE80211_TX_CTL_AMPDU) + tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; + IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); + break; + + case ALG_TKIP: + tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; + ieee80211_get_tkip_key(keyconf, skb_frag, + IEEE80211_TKIP_P2_KEY, tx_cmd->key); + IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); + break; + + case ALG_WEP: + tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | + (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); + + if (keyconf->keylen == WEP_KEY_LEN_128) + tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; + + memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); + + IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " + "with key %d\n", keyconf->keyidx); + break; + + default: + IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg); + break; + } +} + +/* + * start REPLY_TX command process + */ +int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *sta = info->control.sta; + struct iwl_station_priv *sta_priv = NULL; + struct iwl_tx_queue *txq; + struct iwl_queue *q; + struct iwl_device_cmd *out_cmd; + struct iwl_cmd_meta *out_meta; + struct iwl_tx_cmd *tx_cmd; + int swq_id, txq_id; + dma_addr_t phys_addr; + dma_addr_t txcmd_phys; + dma_addr_t scratch_phys; + u16 len, len_org, firstlen, secondlen; + u16 seq_number = 0; + __le16 fc; + u8 hdr_len; + u8 sta_id; + u8 wait_write_ptr = 0; + u8 tid = 0; + u8 *qc = NULL; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + if (iwl_is_rfkill(priv)) { + IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); + goto drop_unlock; + } + + fc = hdr->frame_control; + +#ifdef CONFIG_IWLWIFI_DEBUG + if (ieee80211_is_auth(fc)) + IWL_DEBUG_TX(priv, "Sending AUTH frame\n"); + else if (ieee80211_is_assoc_req(fc)) + IWL_DEBUG_TX(priv, "Sending ASSOC frame\n"); + else if (ieee80211_is_reassoc_req(fc)) + IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); +#endif + + hdr_len = ieee80211_hdrlen(fc); + + /* Find (or create) index into station table for destination station */ + if (info->flags & IEEE80211_TX_CTL_INJECTED) + sta_id = priv->hw_params.bcast_sta_id; + else + sta_id = iwl_get_sta_id(priv, hdr); + if (sta_id == IWL_INVALID_STATION) { + IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", + hdr->addr1); + goto drop_unlock; + } + + IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); + + if (sta) + sta_priv = (void *)sta->drv_priv; + + if (sta_priv && sta_id != priv->hw_params.bcast_sta_id && + sta_priv->asleep) { + WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); + /* + * This sends an asynchronous command to the device, + * but we can rely on it being processed before the + * next frame is processed -- and the next frame to + * this station is the one that will consume this + * counter. + * For now set the counter to just 1 since we do not + * support uAPSD yet. + */ + iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); + } + + txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); + if (ieee80211_is_data_qos(fc)) { + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + if (unlikely(tid >= MAX_TID_COUNT)) + goto drop_unlock; + seq_number = priv->stations[sta_id].tid[tid].seq_number; + seq_number &= IEEE80211_SCTL_SEQ; + hdr->seq_ctrl = hdr->seq_ctrl & + cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(seq_number); + seq_number += 0x10; + /* aggregation is on for this */ + if (info->flags & IEEE80211_TX_CTL_AMPDU && + priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { + txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; + } + } + + txq = &priv->txq[txq_id]; + swq_id = txq->swq_id; + q = &txq->q; + + if (unlikely(iwl_queue_space(q) < q->high_mark)) + goto drop_unlock; + + if (ieee80211_is_data_qos(fc)) + priv->stations[sta_id].tid[tid].tfds_in_queue++; + + /* Set up driver data for this TFD */ + memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); + txq->txb[q->write_ptr].skb[0] = skb; + + /* Set up first empty entry in queue's array of Tx/cmd buffers */ + out_cmd = txq->cmd[q->write_ptr]; + out_meta = &txq->meta[q->write_ptr]; + tx_cmd = &out_cmd->cmd.tx; + memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); + memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); + + /* + * Set up the Tx-command (not MAC!) header. + * Store the chosen Tx queue and TFD index within the sequence field; + * after Tx, uCode's Tx response will return this value so driver can + * locate the frame within the tx queue and do post-tx processing. + */ + out_cmd->hdr.cmd = REPLY_TX; + out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | + INDEX_TO_SEQ(q->write_ptr))); + + /* Copy MAC header from skb into command buffer */ + memcpy(tx_cmd->hdr, hdr, hdr_len); + + + /* Total # bytes to be transmitted */ + len = (u16)skb->len; + tx_cmd->len = cpu_to_le16(len); + + if (info->control.hw_key) + iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); + + /* TODO need this for burst mode later on */ + iwlagn_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id); + iwl_dbg_log_tx_data_frame(priv, len, hdr); + + iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc); + + iwl_update_stats(priv, true, fc, len); + /* + * Use the first empty entry in this queue's command buffer array + * to contain the Tx command and MAC header concatenated together + * (payload data will be in another buffer). + * Size of this varies, due to varying MAC header length. + * If end is not dword aligned, we'll have 2 extra bytes at the end + * of the MAC header (device reads on dword boundaries). + * We'll tell device about this padding later. + */ + len = sizeof(struct iwl_tx_cmd) + + sizeof(struct iwl_cmd_header) + hdr_len; + + len_org = len; + firstlen = len = (len + 3) & ~3; + + if (len_org != len) + len_org = 1; + else + len_org = 0; + + /* Tell NIC about any 2-byte padding after MAC header */ + if (len_org) + tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; + + /* Physical address of this Tx command's header (not MAC header!), + * within command buffer array. */ + txcmd_phys = pci_map_single(priv->pci_dev, + &out_cmd->hdr, len, + PCI_DMA_BIDIRECTIONAL); + pci_unmap_addr_set(out_meta, mapping, txcmd_phys); + pci_unmap_len_set(out_meta, len, len); + /* Add buffer containing Tx command and MAC(!) header to TFD's + * first entry */ + priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, + txcmd_phys, len, 1, 0); + + if (!ieee80211_has_morefrags(hdr->frame_control)) { + txq->need_update = 1; + if (qc) + priv->stations[sta_id].tid[tid].seq_number = seq_number; + } else { + wait_write_ptr = 1; + txq->need_update = 0; + } + + /* Set up TFD's 2nd entry to point directly to remainder of skb, + * if any (802.11 null frames have no payload). */ + secondlen = len = skb->len - hdr_len; + if (len) { + phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, + len, PCI_DMA_TODEVICE); + priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, + phys_addr, len, + 0, 0); + } + + scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + + offsetof(struct iwl_tx_cmd, scratch); + + len = sizeof(struct iwl_tx_cmd) + + sizeof(struct iwl_cmd_header) + hdr_len; + /* take back ownership of DMA buffer to enable update */ + pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys, + len, PCI_DMA_BIDIRECTIONAL); + tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); + tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); + + IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", + le16_to_cpu(out_cmd->hdr.sequence)); + IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); + iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); + iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); + + /* Set up entry for this TFD in Tx byte-count array */ + if (info->flags & IEEE80211_TX_CTL_AMPDU) + priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, + le16_to_cpu(tx_cmd->len)); + + pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, + len, PCI_DMA_BIDIRECTIONAL); + + trace_iwlwifi_dev_tx(priv, + &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], + sizeof(struct iwl_tfd), + &out_cmd->hdr, firstlen, + skb->data + hdr_len, secondlen); + + /* Tell device the write index *just past* this latest filled TFD */ + q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); + iwl_txq_update_write_ptr(priv, txq); + spin_unlock_irqrestore(&priv->lock, flags); + + /* + * At this point the frame is "transmitted" successfully + * and we will get a TX status notification eventually, + * regardless of the value of ret. "ret" only indicates + * whether or not we should update the write pointer. + */ + + /* avoid atomic ops if it isn't an associated client */ + if (sta_priv && sta_priv->client) + atomic_inc(&sta_priv->pending_frames); + + if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { + if (wait_write_ptr) { + spin_lock_irqsave(&priv->lock, flags); + txq->need_update = 1; + iwl_txq_update_write_ptr(priv, txq); + spin_unlock_irqrestore(&priv->lock, flags); + } else { + iwl_stop_queue(priv, txq->swq_id); + } + } + + return 0; + +drop_unlock: + spin_unlock_irqrestore(&priv->lock, flags); + return -1; +} + +static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv, + struct iwl_dma_ptr *ptr, size_t size) +{ + ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma, + GFP_KERNEL); + if (!ptr->addr) + return -ENOMEM; + ptr->size = size; + return 0; +} + +static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv, + struct iwl_dma_ptr *ptr) +{ + if (unlikely(!ptr->addr)) + return; + + dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma); + memset(ptr, 0, sizeof(*ptr)); +} + +/** + * iwlagn_hw_txq_ctx_free - Free TXQ Context + * + * Destroy all TX DMA queues and structures + */ +void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) +{ + int txq_id; + + /* Tx queues */ + if (priv->txq) { + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; + txq_id++) + if (txq_id == IWL_CMD_QUEUE_NUM) + iwl_cmd_queue_free(priv); + else + iwl_tx_queue_free(priv, txq_id); + } + iwlagn_free_dma_ptr(priv, &priv->kw); + + iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); + + /* free tx queue structure */ + iwl_free_txq_mem(priv); +} + +/** + * iwlagn_txq_ctx_reset - Reset TX queue context + * Destroys all DMA structures and initialize them again + * + * @param priv + * @return error code + */ +int iwlagn_txq_ctx_reset(struct iwl_priv *priv) +{ + int ret = 0; + int txq_id, slots_num; + unsigned long flags; + + /* Free all tx/cmd queues and keep-warm buffer */ + iwlagn_hw_txq_ctx_free(priv); + + ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls, + priv->hw_params.scd_bc_tbls_size); + if (ret) { + IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); + goto error_bc_tbls; + } + /* Alloc keep-warm buffer */ + ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); + if (ret) { + IWL_ERR(priv, "Keep Warm allocation failed\n"); + goto error_kw; + } + + /* allocate tx queue structure */ + ret = iwl_alloc_txq_mem(priv); + if (ret) + goto error; + + spin_lock_irqsave(&priv->lock, flags); + + /* Turn off all Tx DMA fifos */ + priv->cfg->ops->lib->txq_set_sched(priv, 0); + + /* Tell NIC where to find the "keep warm" buffer */ + iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); + + spin_unlock_irqrestore(&priv->lock, flags); + + /* Alloc and init all Tx queues, including the command queue (#4) */ + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { + slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? + TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; + ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, + txq_id); + if (ret) { + IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); + goto error; + } + } + + return ret; + + error: + iwlagn_hw_txq_ctx_free(priv); + iwlagn_free_dma_ptr(priv, &priv->kw); + error_kw: + iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); + error_bc_tbls: + return ret; +} + +/** + * iwlagn_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory + */ +void iwlagn_txq_ctx_stop(struct iwl_priv *priv) +{ + int ch; + unsigned long flags; + + /* Turn off all Tx DMA fifos */ + spin_lock_irqsave(&priv->lock, flags); + + priv->cfg->ops->lib->txq_set_sched(priv, 0); + + /* Stop each Tx DMA channel, and wait for it to be idle */ + for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); + iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, + FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), + 1000); + } + spin_unlock_irqrestore(&priv->lock, flags); + + /* Deallocate memory for all Tx queues */ + iwlagn_hw_txq_ctx_free(priv); +} + +/* + * Find first available (lowest unused) Tx Queue, mark it "active". + * Called only when finding queue for aggregation. + * Should never return anything < 7, because they should already + * be in use as EDCA AC (0-3), Command (4), reserved (5, 6) + */ +static int iwlagn_txq_ctx_activate_free(struct iwl_priv *priv) +{ + int txq_id; + + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) + if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) + return txq_id; + return -1; +} + +int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) +{ + int sta_id; + int tx_fifo; + int txq_id; + int ret; + unsigned long flags; + struct iwl_tid_data *tid_data; + + tx_fifo = get_fifo_from_tid(tid); + if (unlikely(tx_fifo < 0)) + return tx_fifo; + + IWL_WARN(priv, "%s on ra = %pM tid = %d\n", + __func__, ra, tid); + + sta_id = iwl_find_station(priv, ra); + if (sta_id == IWL_INVALID_STATION) { + IWL_ERR(priv, "Start AGG on invalid station\n"); + return -ENXIO; + } + if (unlikely(tid >= MAX_TID_COUNT)) + return -EINVAL; + + if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { + IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); + return -ENXIO; + } + + txq_id = iwlagn_txq_ctx_activate_free(priv); + if (txq_id == -1) { + IWL_ERR(priv, "No free aggregation queue available\n"); + return -ENXIO; + } + + spin_lock_irqsave(&priv->sta_lock, flags); + tid_data = &priv->stations[sta_id].tid[tid]; + *ssn = SEQ_TO_SN(tid_data->seq_number); + tid_data->agg.txq_id = txq_id; + priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(tx_fifo, txq_id); + spin_unlock_irqrestore(&priv->sta_lock, flags); + + ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, + sta_id, tid, *ssn); + if (ret) + return ret; + + if (tid_data->tfds_in_queue == 0) { + IWL_DEBUG_HT(priv, "HW queue is empty\n"); + tid_data->agg.state = IWL_AGG_ON; + ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid); + } else { + IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", + tid_data->tfds_in_queue); + tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; + } + return ret; +} + +int iwlagn_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) +{ + int tx_fifo_id, txq_id, sta_id, ssn = -1; + struct iwl_tid_data *tid_data; + int write_ptr, read_ptr; + unsigned long flags; + + if (!ra) { + IWL_ERR(priv, "ra = NULL\n"); + return -EINVAL; + } + + tx_fifo_id = get_fifo_from_tid(tid); + if (unlikely(tx_fifo_id < 0)) + return tx_fifo_id; + + sta_id = iwl_find_station(priv, ra); + + if (sta_id == IWL_INVALID_STATION) { + IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); + return -ENXIO; + } + + if (priv->stations[sta_id].tid[tid].agg.state == + IWL_EMPTYING_HW_QUEUE_ADDBA) { + IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); + ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); + priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; + return 0; + } + + if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) + IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); + + tid_data = &priv->stations[sta_id].tid[tid]; + ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; + txq_id = tid_data->agg.txq_id; + write_ptr = priv->txq[txq_id].q.write_ptr; + read_ptr = priv->txq[txq_id].q.read_ptr; + + /* The queue is not empty */ + if (write_ptr != read_ptr) { + IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); + priv->stations[sta_id].tid[tid].agg.state = + IWL_EMPTYING_HW_QUEUE_DELBA; + return 0; + } + + IWL_DEBUG_HT(priv, "HW queue is empty\n"); + priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; + + spin_lock_irqsave(&priv->lock, flags); + /* + * the only reason this call can fail is queue number out of range, + * which can happen if uCode is reloaded and all the station + * information are lost. if it is outside the range, there is no need + * to deactivate the uCode queue, just return "success" to allow + * mac80211 to clean up it own data. + */ + priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, + tx_fifo_id); + spin_unlock_irqrestore(&priv->lock, flags); + + ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); + + return 0; +} + +int iwlagn_txq_check_empty(struct iwl_priv *priv, + int sta_id, u8 tid, int txq_id) +{ + struct iwl_queue *q = &priv->txq[txq_id].q; + u8 *addr = priv->stations[sta_id].sta.sta.addr; + struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; + + switch (priv->stations[sta_id].tid[tid].agg.state) { + case IWL_EMPTYING_HW_QUEUE_DELBA: + /* We are reclaiming the last packet of the */ + /* aggregated HW queue */ + if ((txq_id == tid_data->agg.txq_id) && + (q->read_ptr == q->write_ptr)) { + u16 ssn = SEQ_TO_SN(tid_data->seq_number); + int tx_fifo = get_fifo_from_tid(tid); + IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); + priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, + ssn, tx_fifo); + tid_data->agg.state = IWL_AGG_OFF; + ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid); + } + break; + case IWL_EMPTYING_HW_QUEUE_ADDBA: + /* We are reclaiming the last packet of the queue */ + if (tid_data->tfds_in_queue == 0) { + IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); + tid_data->agg.state = IWL_AGG_ON; + ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid); + } + break; + } + return 0; +} + +static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_sta *sta; + struct iwl_station_priv *sta_priv; + + sta = ieee80211_find_sta(priv->vif, hdr->addr1); + if (sta) { + sta_priv = (void *)sta->drv_priv; + /* avoid atomic ops if this isn't a client */ + if (sta_priv->client && + atomic_dec_return(&sta_priv->pending_frames) == 0) + ieee80211_sta_block_awake(priv->hw, sta, false); + } + + ieee80211_tx_status_irqsafe(priv->hw, skb); +} + +int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) +{ + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct iwl_queue *q = &txq->q; + struct iwl_tx_info *tx_info; + int nfreed = 0; + struct ieee80211_hdr *hdr; + + if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { + IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " + "is out of range [0-%d] %d %d.\n", txq_id, + index, q->n_bd, q->write_ptr, q->read_ptr); + return 0; + } + + for (index = iwl_queue_inc_wrap(index, q->n_bd); + q->read_ptr != index; + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { + + tx_info = &txq->txb[txq->q.read_ptr]; + iwlagn_tx_status(priv, tx_info->skb[0]); + + hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; + if (hdr && ieee80211_is_data_qos(hdr->frame_control)) + nfreed++; + tx_info->skb[0] = NULL; + + if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) + priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); + + priv->cfg->ops->lib->txq_free_tfd(priv, txq); + } + return nfreed; +} + +/** + * iwlagn_tx_status_reply_compressed_ba - Update tx status from block-ack + * + * Go through block-ack's bitmap of ACK'd frames, update driver's record of + * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. + */ +static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, + struct iwl_ht_agg *agg, + struct iwl_compressed_ba_resp *ba_resp) + +{ + int i, sh, ack; + u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); + u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); + u64 bitmap; + int successes = 0; + struct ieee80211_tx_info *info; + + if (unlikely(!agg->wait_for_ba)) { + IWL_ERR(priv, "Received BA when not expected\n"); + return -EINVAL; + } + + /* Mark that the expected block-ack response arrived */ + agg->wait_for_ba = 0; + IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); + + /* Calculate shift to align block-ack bits with our Tx window bits */ + sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); + if (sh < 0) /* tbw something is wrong with indices */ + sh += 0x100; + + /* don't use 64-bit values for now */ + bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; + + if (agg->frame_count > (64 - sh)) { + IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); + return -1; + } + + /* check for success or failure according to the + * transmitted bitmap and block-ack bitmap */ + bitmap &= agg->bitmap; + + /* For each frame attempted in aggregation, + * update driver's record of tx frame's status. */ + for (i = 0; i < agg->frame_count ; i++) { + ack = bitmap & (1ULL << i); + successes += !!ack; + IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", + ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, + agg->start_idx + i); + } + + info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); + memset(&info->status, 0, sizeof(info->status)); + info->flags |= IEEE80211_TX_STAT_ACK; + info->flags |= IEEE80211_TX_STAT_AMPDU; + info->status.ampdu_ack_map = successes; + info->status.ampdu_ack_len = agg->frame_count; + iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info); + + IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); + + return 0; +} + +/** + * iwlagn_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA + * + * Handles block-acknowledge notification from device, which reports success + * of frames sent via aggregation. + */ +void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; + struct iwl_tx_queue *txq = NULL; + struct iwl_ht_agg *agg; + int index; + int sta_id; + int tid; + + /* "flow" corresponds to Tx queue */ + u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); + + /* "ssn" is start of block-ack Tx window, corresponds to index + * (in Tx queue's circular buffer) of first TFD/frame in window */ + u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); + + if (scd_flow >= priv->hw_params.max_txq_num) { + IWL_ERR(priv, + "BUG_ON scd_flow is bigger than number of queues\n"); + return; + } + + txq = &priv->txq[scd_flow]; + sta_id = ba_resp->sta_id; + tid = ba_resp->tid; + agg = &priv->stations[sta_id].tid[tid].agg; + + /* Find index just before block-ack window */ + index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); + + /* TODO: Need to get this copy more safely - now good for debug */ + + IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " + "sta_id = %d\n", + agg->wait_for_ba, + (u8 *) &ba_resp->sta_addr_lo32, + ba_resp->sta_id); + IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " + "%d, scd_ssn = %d\n", + ba_resp->tid, + ba_resp->seq_ctl, + (unsigned long long)le64_to_cpu(ba_resp->bitmap), + ba_resp->scd_flow, + ba_resp->scd_ssn); + IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx \n", + agg->start_idx, + (unsigned long long)agg->bitmap); + + /* Update driver's record of ACK vs. not for each frame in window */ + iwlagn_tx_status_reply_compressed_ba(priv, agg, ba_resp); + + /* Release all TFDs before the SSN, i.e. all TFDs in front of + * block-ack window (we assume that they've been successfully + * transmitted ... if not, it's too late anyway). */ + if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { + /* calculate mac80211 ampdu sw queue to wake */ + int freed = iwlagn_tx_queue_reclaim(priv, scd_flow, index); + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); + + if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && + priv->mac80211_registered && + (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) + iwl_wake_queue(priv, txq->swq_id); + + iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); + } +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 680e897b92db..a57933b8f6fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -887,7 +887,7 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy; priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx; /* block ack */ - priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl_rx_reply_compressed_ba; + priv->rx_handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba; /* Set up hardware specific Rx handlers */ priv->cfg->ops->lib->rx_handler_setup(priv); } @@ -2249,7 +2249,7 @@ static void __iwl_down(struct iwl_priv *priv) /* device going down, Stop using ICT table */ iwl_disable_ict(priv); - iwl_txq_ctx_stop(priv); + iwlagn_txq_ctx_stop(priv); iwl_rxq_stop(priv); /* Power-down device's busmaster DMA clocks */ @@ -2371,7 +2371,7 @@ static int __iwl_up(struct iwl_priv *priv) iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - ret = iwl_hw_nic_init(priv); + ret = iwlagn_hw_nic_init(priv); if (ret) { IWL_ERR(priv, "Unable to init nic\n"); return ret; @@ -2782,7 +2782,7 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); - if (iwl_tx_skb(priv, skb)) + if (iwlagn_tx_skb(priv, skb)) dev_kfree_skb_any(skb); IWL_DEBUG_MACDUMP(priv, "leave\n"); @@ -2970,7 +2970,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return ret; case IEEE80211_AMPDU_TX_START: IWL_DEBUG_HT(priv, "start Tx\n"); - ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn); + ret = iwlagn_tx_agg_start(priv, sta->addr, tid, ssn); if (ret == 0) { priv->_agn.agg_tids_count++; IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", @@ -2979,7 +2979,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return ret; case IEEE80211_AMPDU_TX_STOP: IWL_DEBUG_HT(priv, "stop Tx\n"); - ret = iwl_tx_agg_stop(priv, sta->addr, tid); + ret = iwlagn_tx_agg_stop(priv, sta->addr, tid); if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { priv->_agn.agg_tids_count--; IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", @@ -3738,7 +3738,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) if (priv->rxq.bd) iwl_rx_queue_free(priv, &priv->rxq); - iwl_hw_txq_ctx_free(priv); + iwlagn_hw_txq_ctx_free(priv); iwl_eeprom_free(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index ad9b47e1a817..c75a767872f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -113,5 +113,22 @@ void iwlagn_temperature(struct iwl_priv *priv); u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); +void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); +int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); +int iwlagn_hw_nic_init(struct iwl_priv *priv); + +/* tx */ +int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); +int iwlagn_tx_agg_start(struct iwl_priv *priv, + const u8 *ra, u16 tid, u16 *ssn); +int iwlagn_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); +int iwlagn_txq_check_empty(struct iwl_priv *priv, + int sta_id, u8 tid, int txq_id); +void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb); +int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); +void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv); +int iwlagn_txq_ctx_reset(struct iwl_priv *priv); +void iwlagn_txq_ctx_stop(struct iwl_priv *priv); #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5180fb24cd38..0dc41d84dc15 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -265,57 +265,6 @@ void iwl_hw_detect(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_hw_detect); -int iwl_hw_nic_init(struct iwl_priv *priv) -{ - unsigned long flags; - struct iwl_rx_queue *rxq = &priv->rxq; - int ret; - - /* nic_init */ - spin_lock_irqsave(&priv->lock, flags); - priv->cfg->ops->lib->apm_ops.init(priv); - - /* Set interrupt coalescing calibration timer to default (512 usecs) */ - iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); - - spin_unlock_irqrestore(&priv->lock, flags); - - ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); - - priv->cfg->ops->lib->apm_ops.config(priv); - - /* Allocate the RX queue, or reset if it is already allocated */ - if (!rxq->bd) { - ret = iwl_rx_queue_alloc(priv); - if (ret) { - IWL_ERR(priv, "Unable to initialize Rx queue\n"); - return -ENOMEM; - } - } else - iwl_rx_queue_reset(priv, rxq); - - iwl_rx_replenish(priv); - - iwl_rx_init(priv, rxq); - - spin_lock_irqsave(&priv->lock, flags); - - rxq->need_update = 1; - iwl_rx_queue_update_write_ptr(priv, rxq); - - spin_unlock_irqrestore(&priv->lock, flags); - - /* Allocate and init all Tx and Command queues */ - ret = iwl_txq_ctx_reset(priv); - if (ret) - return ret; - - set_bit(STATUS_INIT, &priv->status); - - return 0; -} -EXPORT_SYMBOL(iwl_hw_nic_init); - /* * QoS support */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index b3e698b576e1..446d27bd4301 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -336,7 +336,6 @@ void iwl_irq_handle_error(struct iwl_priv *priv); void iwl_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, u64 multicast); -int iwl_hw_nic_init(struct iwl_priv *priv); int iwl_set_hw_params(struct iwl_priv *priv); bool iwl_is_monitor_mode(struct iwl_priv *priv); void iwl_post_associate(struct iwl_priv *priv); @@ -426,15 +425,12 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv); void iwl_rx_handle(struct iwl_priv *priv); void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q); -void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); void iwl_rx_replenish(struct iwl_priv *priv); void iwl_rx_replenish_now(struct iwl_priv *priv); -int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); void iwl_rx_queue_restock(struct iwl_priv *priv); int iwl_rx_queue_space(const struct iwl_rx_queue *q); void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); -int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); /* Handlers */ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); @@ -455,13 +451,10 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); /***************************************************** * TX ******************************************************/ -int iwl_txq_ctx_reset(struct iwl_priv *priv); void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, dma_addr_t addr, u16 len, u8 reset, u8 pad); -int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); -void iwl_hw_txq_ctx_free(struct iwl_priv *priv); int iwl_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq); void iwl_free_tfds_in_queue(struct iwl_priv *priv, @@ -470,9 +463,6 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, int slots_num, u32 txq_id); void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); -int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); -int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); -int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); /***************************************************** * TX power ****************************************************/ @@ -689,8 +679,6 @@ extern void iwl_rx_reply_rx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); -void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); void iwl_apm_stop(struct iwl_priv *priv); int iwl_apm_init(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index 36580d8d8b8d..f469aa92316a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c @@ -35,6 +35,7 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite8); EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32); EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32); EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); +EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_tx); EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event); diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index de453f25f1c9..b75c3ccd1c43 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -395,86 +395,6 @@ err_bd: } EXPORT_SYMBOL(iwl_rx_queue_alloc); -void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) -{ - unsigned long flags; - int i; - spin_lock_irqsave(&rxq->lock, flags); - INIT_LIST_HEAD(&rxq->rx_free); - INIT_LIST_HEAD(&rxq->rx_used); - /* Fill the rx_used queue with _all_ of the Rx buffers */ - for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { - /* In the reset function, these buffers may have been allocated - * to an SKB, so we need to unmap and free potential storage */ - if (rxq->pool[i].page != NULL) { - pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, - PAGE_SIZE << priv->hw_params.rx_page_order, - PCI_DMA_FROMDEVICE); - __iwl_free_pages(priv, rxq->pool[i].page); - rxq->pool[i].page = NULL; - } - list_add_tail(&rxq->pool[i].list, &rxq->rx_used); - } - - /* Set us so that we have processed and used all buffers, but have - * not restocked the Rx queue with fresh buffers */ - rxq->read = rxq->write = 0; - rxq->write_actual = 0; - rxq->free_count = 0; - spin_unlock_irqrestore(&rxq->lock, flags); -} - -int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) -{ - u32 rb_size; - const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ - u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ - - if (!priv->cfg->use_isr_legacy) - rb_timeout = RX_RB_TIMEOUT; - - if (priv->cfg->mod_params->amsdu_size_8K) - rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; - else - rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; - - /* Stop Rx DMA */ - iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - - /* Reset driver's Rx queue write index */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); - - /* Tell device where to find RBD circular buffer in DRAM */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, - (u32)(rxq->dma_addr >> 8)); - - /* Tell device where in DRAM to update its Rx status */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, - rxq->rb_stts_dma >> 4); - - /* Enable Rx DMA - * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in - * the credit mechanism in 5000 HW RX FIFO - * Direct rx interrupts to hosts - * Rx buffer size 4 or 8k - * RB timeout 0x10 - * 256 RBDs - */ - iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, - FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | - FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | - FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | - FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | - rb_size| - (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| - (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); - - /* Set interrupt coalescing timer to default (2048 usecs) */ - iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); - - return 0; -} - int iwl_rxq_stop(struct iwl_priv *priv) { diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index d401b6f226f9..9c28ad7a2de1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1395,6 +1395,7 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); } +EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 34c983833a8f..91f9c89b1b6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -37,84 +37,6 @@ #include "iwl-io.h" #include "iwl-helpers.h" -/* - * mac80211 queues, ACs, hardware queues, FIFOs. - * - * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues - * - * Mac80211 uses the following numbers, which we get as from it - * by way of skb_get_queue_mapping(skb): - * - * VO 0 - * VI 1 - * BE 2 - * BK 3 - * - * - * Regular (not A-MPDU) frames are put into hardware queues corresponding - * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their - * own queue per aggregation session (RA/TID combination), such queues are - * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In - * order to map frames to the right queue, we also need an AC->hw queue - * mapping. This is implemented here. - * - * Due to the way hw queues are set up (by the hw specific modules like - * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity - * mapping. - */ - -static const u8 tid_to_ac[] = { - /* this matches the mac80211 numbers */ - 2, 3, 3, 2, 1, 1, 0, 0 -}; - -static const u8 ac_to_fifo[] = { - IWL_TX_FIFO_VO, - IWL_TX_FIFO_VI, - IWL_TX_FIFO_BE, - IWL_TX_FIFO_BK, -}; - -static inline int get_fifo_from_ac(u8 ac) -{ - return ac_to_fifo[ac]; -} - -static inline int get_queue_from_ac(u16 ac) -{ - return ac; -} - -static inline int get_fifo_from_tid(u16 tid) -{ - if (likely(tid < ARRAY_SIZE(tid_to_ac))) - return get_fifo_from_ac(tid_to_ac[tid]); - - /* no support for TIDs 8-15 yet */ - return -EINVAL; -} - -static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, - struct iwl_dma_ptr *ptr, size_t size) -{ - ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma, - GFP_KERNEL); - if (!ptr->addr) - return -ENOMEM; - ptr->size = size; - return 0; -} - -static inline void iwl_free_dma_ptr(struct iwl_priv *priv, - struct iwl_dma_ptr *ptr) -{ - if (unlikely(!ptr->addr)) - return; - - dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma); - memset(ptr, 0, sizeof(*ptr)); -} - /** * iwl_txq_update_write_ptr - Send new write index to hardware */ @@ -448,579 +370,6 @@ out_free_arrays: } EXPORT_SYMBOL(iwl_tx_queue_init); -/** - * iwl_hw_txq_ctx_free - Free TXQ Context - * - * Destroy all TX DMA queues and structures - */ -void iwl_hw_txq_ctx_free(struct iwl_priv *priv) -{ - int txq_id; - - /* Tx queues */ - if (priv->txq) { - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; - txq_id++) - if (txq_id == IWL_CMD_QUEUE_NUM) - iwl_cmd_queue_free(priv); - else - iwl_tx_queue_free(priv, txq_id); - } - iwl_free_dma_ptr(priv, &priv->kw); - - iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); - - /* free tx queue structure */ - iwl_free_txq_mem(priv); -} -EXPORT_SYMBOL(iwl_hw_txq_ctx_free); - -/** - * iwl_txq_ctx_reset - Reset TX queue context - * Destroys all DMA structures and initialize them again - * - * @param priv - * @return error code - */ -int iwl_txq_ctx_reset(struct iwl_priv *priv) -{ - int ret = 0; - int txq_id, slots_num; - unsigned long flags; - - /* Free all tx/cmd queues and keep-warm buffer */ - iwl_hw_txq_ctx_free(priv); - - ret = iwl_alloc_dma_ptr(priv, &priv->scd_bc_tbls, - priv->hw_params.scd_bc_tbls_size); - if (ret) { - IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); - goto error_bc_tbls; - } - /* Alloc keep-warm buffer */ - ret = iwl_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); - if (ret) { - IWL_ERR(priv, "Keep Warm allocation failed\n"); - goto error_kw; - } - - /* allocate tx queue structure */ - ret = iwl_alloc_txq_mem(priv); - if (ret) - goto error; - - spin_lock_irqsave(&priv->lock, flags); - - /* Turn off all Tx DMA fifos */ - priv->cfg->ops->lib->txq_set_sched(priv, 0); - - /* Tell NIC where to find the "keep warm" buffer */ - iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); - - spin_unlock_irqrestore(&priv->lock, flags); - - /* Alloc and init all Tx queues, including the command queue (#4) */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { - slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? - TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, - txq_id); - if (ret) { - IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); - goto error; - } - } - - return ret; - - error: - iwl_hw_txq_ctx_free(priv); - iwl_free_dma_ptr(priv, &priv->kw); - error_kw: - iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); - error_bc_tbls: - return ret; -} - -/** - * iwl_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory - */ -void iwl_txq_ctx_stop(struct iwl_priv *priv) -{ - int ch; - unsigned long flags; - - /* Turn off all Tx DMA fifos */ - spin_lock_irqsave(&priv->lock, flags); - - priv->cfg->ops->lib->txq_set_sched(priv, 0); - - /* Stop each Tx DMA channel, and wait for it to be idle */ - for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { - iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); - iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, - FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), - 1000); - } - spin_unlock_irqrestore(&priv->lock, flags); - - /* Deallocate memory for all Tx queues */ - iwl_hw_txq_ctx_free(priv); -} -EXPORT_SYMBOL(iwl_txq_ctx_stop); - -/* - * handle build REPLY_TX command notification. - */ -static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, - struct iwl_tx_cmd *tx_cmd, - struct ieee80211_tx_info *info, - struct ieee80211_hdr *hdr, - u8 std_id) -{ - __le16 fc = hdr->frame_control; - __le32 tx_flags = tx_cmd->tx_flags; - - tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { - tx_flags |= TX_CMD_FLG_ACK_MSK; - if (ieee80211_is_mgmt(fc)) - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - if (ieee80211_is_probe_resp(fc) && - !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) - tx_flags |= TX_CMD_FLG_TSF_MSK; - } else { - tx_flags &= (~TX_CMD_FLG_ACK_MSK); - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - } - - if (ieee80211_is_back_req(fc)) - tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; - - - tx_cmd->sta_id = std_id; - if (ieee80211_has_morefrags(fc)) - tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; - - if (ieee80211_is_data_qos(fc)) { - u8 *qc = ieee80211_get_qos_ctl(hdr); - tx_cmd->tid_tspec = qc[0] & 0xf; - tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; - } else { - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - } - - priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); - - if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) - tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; - - tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); - if (ieee80211_is_mgmt(fc)) { - if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) - tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3); - else - tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2); - } else { - tx_cmd->timeout.pm_frame_timeout = 0; - } - - tx_cmd->driver_txop = 0; - tx_cmd->tx_flags = tx_flags; - tx_cmd->next_frame_len = 0; -} - -#define RTS_DFAULT_RETRY_LIMIT 60 - -static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, - struct iwl_tx_cmd *tx_cmd, - struct ieee80211_tx_info *info, - __le16 fc) -{ - u32 rate_flags; - int rate_idx; - u8 rts_retry_limit; - u8 data_retry_limit; - u8 rate_plcp; - - /* Set retry limit on DATA packets and Probe Responses*/ - if (ieee80211_is_probe_resp(fc)) - data_retry_limit = 3; - else - data_retry_limit = IWL_DEFAULT_TX_RETRY; - tx_cmd->data_retry_limit = data_retry_limit; - - /* Set retry limit on RTS packets */ - rts_retry_limit = RTS_DFAULT_RETRY_LIMIT; - if (data_retry_limit < rts_retry_limit) - rts_retry_limit = data_retry_limit; - tx_cmd->rts_retry_limit = rts_retry_limit; - - /* DATA packets will use the uCode station table for rate/antenna - * selection */ - if (ieee80211_is_data(fc)) { - tx_cmd->initial_rate_index = 0; - tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; - return; - } - - /** - * If the current TX rate stored in mac80211 has the MCS bit set, it's - * not really a TX rate. Thus, we use the lowest supported rate for - * this band. Also use the lowest supported rate if the stored rate - * index is invalid. - */ - rate_idx = info->control.rates[0].idx; - if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || - (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) - rate_idx = rate_lowest_index(&priv->bands[info->band], - info->control.sta); - /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ - if (info->band == IEEE80211_BAND_5GHZ) - rate_idx += IWL_FIRST_OFDM_RATE; - /* Get PLCP rate for tx_cmd->rate_n_flags */ - rate_plcp = iwl_rates[rate_idx].plcp; - /* Zero out flags for this packet */ - rate_flags = 0; - - /* Set CCK flag as needed */ - if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) - rate_flags |= RATE_MCS_CCK_MSK; - - /* Set up RTS and CTS flags for certain packets */ - switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { - case cpu_to_le16(IEEE80211_STYPE_AUTH): - case cpu_to_le16(IEEE80211_STYPE_DEAUTH): - case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): - case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): - if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { - tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; - tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; - } - break; - default: - break; - } - - /* Set up antennas */ - priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); - rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); - - /* Set the rate in the TX cmd */ - tx_cmd->rate_n_flags = iwl_hw_set_rate_n_flags(rate_plcp, rate_flags); -} - -static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv, - struct ieee80211_tx_info *info, - struct iwl_tx_cmd *tx_cmd, - struct sk_buff *skb_frag, - int sta_id) -{ - struct ieee80211_key_conf *keyconf = info->control.hw_key; - - switch (keyconf->alg) { - case ALG_CCMP: - tx_cmd->sec_ctl = TX_CMD_SEC_CCM; - memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); - if (info->flags & IEEE80211_TX_CTL_AMPDU) - tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; - IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); - break; - - case ALG_TKIP: - tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; - ieee80211_get_tkip_key(keyconf, skb_frag, - IEEE80211_TKIP_P2_KEY, tx_cmd->key); - IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); - break; - - case ALG_WEP: - tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | - (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); - - if (keyconf->keylen == WEP_KEY_LEN_128) - tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; - - memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); - - IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " - "with key %d\n", keyconf->keyidx); - break; - - default: - IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg); - break; - } -} - -/* - * start REPLY_TX command process - */ -int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_sta *sta = info->control.sta; - struct iwl_station_priv *sta_priv = NULL; - struct iwl_tx_queue *txq; - struct iwl_queue *q; - struct iwl_device_cmd *out_cmd; - struct iwl_cmd_meta *out_meta; - struct iwl_tx_cmd *tx_cmd; - int swq_id, txq_id; - dma_addr_t phys_addr; - dma_addr_t txcmd_phys; - dma_addr_t scratch_phys; - u16 len, len_org, firstlen, secondlen; - u16 seq_number = 0; - __le16 fc; - u8 hdr_len; - u8 sta_id; - u8 wait_write_ptr = 0; - u8 tid = 0; - u8 *qc = NULL; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); - goto drop_unlock; - } - - fc = hdr->frame_control; - -#ifdef CONFIG_IWLWIFI_DEBUG - if (ieee80211_is_auth(fc)) - IWL_DEBUG_TX(priv, "Sending AUTH frame\n"); - else if (ieee80211_is_assoc_req(fc)) - IWL_DEBUG_TX(priv, "Sending ASSOC frame\n"); - else if (ieee80211_is_reassoc_req(fc)) - IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); -#endif - - hdr_len = ieee80211_hdrlen(fc); - - /* Find (or create) index into station table for destination station */ - if (info->flags & IEEE80211_TX_CTL_INJECTED) - sta_id = priv->hw_params.bcast_sta_id; - else - sta_id = iwl_get_sta_id(priv, hdr); - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", - hdr->addr1); - goto drop_unlock; - } - - IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); - - if (sta) - sta_priv = (void *)sta->drv_priv; - - if (sta_priv && sta_id != priv->hw_params.bcast_sta_id && - sta_priv->asleep) { - WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); - /* - * This sends an asynchronous command to the device, - * but we can rely on it being processed before the - * next frame is processed -- and the next frame to - * this station is the one that will consume this - * counter. - * For now set the counter to just 1 since we do not - * support uAPSD yet. - */ - iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); - } - - txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); - if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - if (unlikely(tid >= MAX_TID_COUNT)) - goto drop_unlock; - seq_number = priv->stations[sta_id].tid[tid].seq_number; - seq_number &= IEEE80211_SCTL_SEQ; - hdr->seq_ctrl = hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(seq_number); - seq_number += 0x10; - /* aggregation is on for this */ - if (info->flags & IEEE80211_TX_CTL_AMPDU && - priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { - txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; - } - } - - txq = &priv->txq[txq_id]; - swq_id = txq->swq_id; - q = &txq->q; - - if (unlikely(iwl_queue_space(q) < q->high_mark)) - goto drop_unlock; - - if (ieee80211_is_data_qos(fc)) - priv->stations[sta_id].tid[tid].tfds_in_queue++; - - /* Set up driver data for this TFD */ - memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); - txq->txb[q->write_ptr].skb[0] = skb; - - /* Set up first empty entry in queue's array of Tx/cmd buffers */ - out_cmd = txq->cmd[q->write_ptr]; - out_meta = &txq->meta[q->write_ptr]; - tx_cmd = &out_cmd->cmd.tx; - memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); - memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); - - /* - * Set up the Tx-command (not MAC!) header. - * Store the chosen Tx queue and TFD index within the sequence field; - * after Tx, uCode's Tx response will return this value so driver can - * locate the frame within the tx queue and do post-tx processing. - */ - out_cmd->hdr.cmd = REPLY_TX; - out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | - INDEX_TO_SEQ(q->write_ptr))); - - /* Copy MAC header from skb into command buffer */ - memcpy(tx_cmd->hdr, hdr, hdr_len); - - - /* Total # bytes to be transmitted */ - len = (u16)skb->len; - tx_cmd->len = cpu_to_le16(len); - - if (info->control.hw_key) - iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); - - /* TODO need this for burst mode later on */ - iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id); - iwl_dbg_log_tx_data_frame(priv, len, hdr); - - iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc); - - iwl_update_stats(priv, true, fc, len); - /* - * Use the first empty entry in this queue's command buffer array - * to contain the Tx command and MAC header concatenated together - * (payload data will be in another buffer). - * Size of this varies, due to varying MAC header length. - * If end is not dword aligned, we'll have 2 extra bytes at the end - * of the MAC header (device reads on dword boundaries). - * We'll tell device about this padding later. - */ - len = sizeof(struct iwl_tx_cmd) + - sizeof(struct iwl_cmd_header) + hdr_len; - - len_org = len; - firstlen = len = (len + 3) & ~3; - - if (len_org != len) - len_org = 1; - else - len_org = 0; - - /* Tell NIC about any 2-byte padding after MAC header */ - if (len_org) - tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; - - /* Physical address of this Tx command's header (not MAC header!), - * within command buffer array. */ - txcmd_phys = pci_map_single(priv->pci_dev, - &out_cmd->hdr, len, - PCI_DMA_BIDIRECTIONAL); - pci_unmap_addr_set(out_meta, mapping, txcmd_phys); - pci_unmap_len_set(out_meta, len, len); - /* Add buffer containing Tx command and MAC(!) header to TFD's - * first entry */ - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - txcmd_phys, len, 1, 0); - - if (!ieee80211_has_morefrags(hdr->frame_control)) { - txq->need_update = 1; - if (qc) - priv->stations[sta_id].tid[tid].seq_number = seq_number; - } else { - wait_write_ptr = 1; - txq->need_update = 0; - } - - /* Set up TFD's 2nd entry to point directly to remainder of skb, - * if any (802.11 null frames have no payload). */ - secondlen = len = skb->len - hdr_len; - if (len) { - phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, - len, PCI_DMA_TODEVICE); - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - phys_addr, len, - 0, 0); - } - - scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + - offsetof(struct iwl_tx_cmd, scratch); - - len = sizeof(struct iwl_tx_cmd) + - sizeof(struct iwl_cmd_header) + hdr_len; - /* take back ownership of DMA buffer to enable update */ - pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys, - len, PCI_DMA_BIDIRECTIONAL); - tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); - tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); - - IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", - le16_to_cpu(out_cmd->hdr.sequence)); - IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); - iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); - iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); - - /* Set up entry for this TFD in Tx byte-count array */ - if (info->flags & IEEE80211_TX_CTL_AMPDU) - priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, - le16_to_cpu(tx_cmd->len)); - - pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, - len, PCI_DMA_BIDIRECTIONAL); - - trace_iwlwifi_dev_tx(priv, - &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], - sizeof(struct iwl_tfd), - &out_cmd->hdr, firstlen, - skb->data + hdr_len, secondlen); - - /* Tell device the write index *just past* this latest filled TFD */ - q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - iwl_txq_update_write_ptr(priv, txq); - spin_unlock_irqrestore(&priv->lock, flags); - - /* - * At this point the frame is "transmitted" successfully - * and we will get a TX status notification eventually, - * regardless of the value of ret. "ret" only indicates - * whether or not we should update the write pointer. - */ - - /* avoid atomic ops if it isn't an associated client */ - if (sta_priv && sta_priv->client) - atomic_inc(&sta_priv->pending_frames); - - if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { - if (wait_write_ptr) { - spin_lock_irqsave(&priv->lock, flags); - txq->need_update = 1; - iwl_txq_update_write_ptr(priv, txq); - spin_unlock_irqrestore(&priv->lock, flags); - } else { - iwl_stop_queue(priv, txq->swq_id); - } - } - - return 0; - -drop_unlock: - spin_unlock_irqrestore(&priv->lock, flags); - return -1; -} -EXPORT_SYMBOL(iwl_tx_skb); - /*************** HOST COMMAND QUEUE FUNCTIONS *****/ /** @@ -1146,61 +495,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) return idx; } -static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_sta *sta; - struct iwl_station_priv *sta_priv; - - sta = ieee80211_find_sta(priv->vif, hdr->addr1); - if (sta) { - sta_priv = (void *)sta->drv_priv; - /* avoid atomic ops if this isn't a client */ - if (sta_priv->client && - atomic_dec_return(&sta_priv->pending_frames) == 0) - ieee80211_sta_block_awake(priv->hw, sta, false); - } - - ieee80211_tx_status_irqsafe(priv->hw, skb); -} - -int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) -{ - struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct iwl_queue *q = &txq->q; - struct iwl_tx_info *tx_info; - int nfreed = 0; - struct ieee80211_hdr *hdr; - - if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { - IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " - "is out of range [0-%d] %d %d.\n", txq_id, - index, q->n_bd, q->write_ptr, q->read_ptr); - return 0; - } - - for (index = iwl_queue_inc_wrap(index, q->n_bd); - q->read_ptr != index; - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { - - tx_info = &txq->txb[txq->q.read_ptr]; - iwl_tx_status(priv, tx_info->skb[0]); - - hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; - if (hdr && ieee80211_is_data_qos(hdr->frame_control)) - nfreed++; - tx_info->skb[0] = NULL; - - if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) - priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); - - priv->cfg->ops->lib->txq_free_tfd(priv, txq); - } - return nfreed; -} -EXPORT_SYMBOL(iwl_tx_queue_reclaim); - - /** * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd * @@ -1292,329 +586,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) } EXPORT_SYMBOL(iwl_tx_cmd_complete); -/* - * Find first available (lowest unused) Tx Queue, mark it "active". - * Called only when finding queue for aggregation. - * Should never return anything < 7, because they should already - * be in use as EDCA AC (0-3), Command (4), reserved (5, 6) - */ -static int iwl_txq_ctx_activate_free(struct iwl_priv *priv) -{ - int txq_id; - - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) - if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) - return txq_id; - return -1; -} - -int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) -{ - int sta_id; - int tx_fifo; - int txq_id; - int ret; - unsigned long flags; - struct iwl_tid_data *tid_data; - - tx_fifo = get_fifo_from_tid(tid); - if (unlikely(tx_fifo < 0)) - return tx_fifo; - - IWL_WARN(priv, "%s on ra = %pM tid = %d\n", - __func__, ra, tid); - - sta_id = iwl_find_station(priv, ra); - if (sta_id == IWL_INVALID_STATION) { - IWL_ERR(priv, "Start AGG on invalid station\n"); - return -ENXIO; - } - if (unlikely(tid >= MAX_TID_COUNT)) - return -EINVAL; - - if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { - IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); - return -ENXIO; - } - - txq_id = iwl_txq_ctx_activate_free(priv); - if (txq_id == -1) { - IWL_ERR(priv, "No free aggregation queue available\n"); - return -ENXIO; - } - - spin_lock_irqsave(&priv->sta_lock, flags); - tid_data = &priv->stations[sta_id].tid[tid]; - *ssn = SEQ_TO_SN(tid_data->seq_number); - tid_data->agg.txq_id = txq_id; - priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(tx_fifo, txq_id); - spin_unlock_irqrestore(&priv->sta_lock, flags); - - ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, - sta_id, tid, *ssn); - if (ret) - return ret; - - if (tid_data->tfds_in_queue == 0) { - IWL_DEBUG_HT(priv, "HW queue is empty\n"); - tid_data->agg.state = IWL_AGG_ON; - ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid); - } else { - IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", - tid_data->tfds_in_queue); - tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; - } - return ret; -} -EXPORT_SYMBOL(iwl_tx_agg_start); - -int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) -{ - int tx_fifo_id, txq_id, sta_id, ssn = -1; - struct iwl_tid_data *tid_data; - int write_ptr, read_ptr; - unsigned long flags; - - if (!ra) { - IWL_ERR(priv, "ra = NULL\n"); - return -EINVAL; - } - - tx_fifo_id = get_fifo_from_tid(tid); - if (unlikely(tx_fifo_id < 0)) - return tx_fifo_id; - - sta_id = iwl_find_station(priv, ra); - - if (sta_id == IWL_INVALID_STATION) { - IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); - return -ENXIO; - } - - if (priv->stations[sta_id].tid[tid].agg.state == - IWL_EMPTYING_HW_QUEUE_ADDBA) { - IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); - ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); - priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; - return 0; - } - - if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) - IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); - - tid_data = &priv->stations[sta_id].tid[tid]; - ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; - txq_id = tid_data->agg.txq_id; - write_ptr = priv->txq[txq_id].q.write_ptr; - read_ptr = priv->txq[txq_id].q.read_ptr; - - /* The queue is not empty */ - if (write_ptr != read_ptr) { - IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); - priv->stations[sta_id].tid[tid].agg.state = - IWL_EMPTYING_HW_QUEUE_DELBA; - return 0; - } - - IWL_DEBUG_HT(priv, "HW queue is empty\n"); - priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; - - spin_lock_irqsave(&priv->lock, flags); - /* - * the only reason this call can fail is queue number out of range, - * which can happen if uCode is reloaded and all the station - * information are lost. if it is outside the range, there is no need - * to deactivate the uCode queue, just return "success" to allow - * mac80211 to clean up it own data. - */ - priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, - tx_fifo_id); - spin_unlock_irqrestore(&priv->lock, flags); - - ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); - - return 0; -} -EXPORT_SYMBOL(iwl_tx_agg_stop); - -int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) -{ - struct iwl_queue *q = &priv->txq[txq_id].q; - u8 *addr = priv->stations[sta_id].sta.sta.addr; - struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; - - switch (priv->stations[sta_id].tid[tid].agg.state) { - case IWL_EMPTYING_HW_QUEUE_DELBA: - /* We are reclaiming the last packet of the */ - /* aggregated HW queue */ - if ((txq_id == tid_data->agg.txq_id) && - (q->read_ptr == q->write_ptr)) { - u16 ssn = SEQ_TO_SN(tid_data->seq_number); - int tx_fifo = get_fifo_from_tid(tid); - IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); - priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, - ssn, tx_fifo); - tid_data->agg.state = IWL_AGG_OFF; - ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid); - } - break; - case IWL_EMPTYING_HW_QUEUE_ADDBA: - /* We are reclaiming the last packet of the queue */ - if (tid_data->tfds_in_queue == 0) { - IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); - tid_data->agg.state = IWL_AGG_ON; - ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid); - } - break; - } - return 0; -} -EXPORT_SYMBOL(iwl_txq_check_empty); - -/** - * iwl_tx_status_reply_compressed_ba - Update tx status from block-ack - * - * Go through block-ack's bitmap of ACK'd frames, update driver's record of - * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. - */ -static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, - struct iwl_ht_agg *agg, - struct iwl_compressed_ba_resp *ba_resp) - -{ - int i, sh, ack; - u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); - u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); - u64 bitmap; - int successes = 0; - struct ieee80211_tx_info *info; - - if (unlikely(!agg->wait_for_ba)) { - IWL_ERR(priv, "Received BA when not expected\n"); - return -EINVAL; - } - - /* Mark that the expected block-ack response arrived */ - agg->wait_for_ba = 0; - IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); - - /* Calculate shift to align block-ack bits with our Tx window bits */ - sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); - if (sh < 0) /* tbw something is wrong with indices */ - sh += 0x100; - - /* don't use 64-bit values for now */ - bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; - - if (agg->frame_count > (64 - sh)) { - IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); - return -1; - } - - /* check for success or failure according to the - * transmitted bitmap and block-ack bitmap */ - bitmap &= agg->bitmap; - - /* For each frame attempted in aggregation, - * update driver's record of tx frame's status. */ - for (i = 0; i < agg->frame_count ; i++) { - ack = bitmap & (1ULL << i); - successes += !!ack; - IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", - ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, - agg->start_idx + i); - } - - info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); - memset(&info->status, 0, sizeof(info->status)); - info->flags |= IEEE80211_TX_STAT_ACK; - info->flags |= IEEE80211_TX_STAT_AMPDU; - info->status.ampdu_ack_map = successes; - info->status.ampdu_ack_len = agg->frame_count; - iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info); - - IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); - - return 0; -} - -/** - * iwl_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA - * - * Handles block-acknowledge notification from device, which reports success - * of frames sent via aggregation. - */ -void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; - struct iwl_tx_queue *txq = NULL; - struct iwl_ht_agg *agg; - int index; - int sta_id; - int tid; - - /* "flow" corresponds to Tx queue */ - u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); - - /* "ssn" is start of block-ack Tx window, corresponds to index - * (in Tx queue's circular buffer) of first TFD/frame in window */ - u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); - - if (scd_flow >= priv->hw_params.max_txq_num) { - IWL_ERR(priv, - "BUG_ON scd_flow is bigger than number of queues\n"); - return; - } - - txq = &priv->txq[scd_flow]; - sta_id = ba_resp->sta_id; - tid = ba_resp->tid; - agg = &priv->stations[sta_id].tid[tid].agg; - - /* Find index just before block-ack window */ - index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); - - /* TODO: Need to get this copy more safely - now good for debug */ - - IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " - "sta_id = %d\n", - agg->wait_for_ba, - (u8 *) &ba_resp->sta_addr_lo32, - ba_resp->sta_id); - IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " - "%d, scd_ssn = %d\n", - ba_resp->tid, - ba_resp->seq_ctl, - (unsigned long long)le64_to_cpu(ba_resp->bitmap), - ba_resp->scd_flow, - ba_resp->scd_ssn); - IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx \n", - agg->start_idx, - (unsigned long long)agg->bitmap); - - /* Update driver's record of ACK vs. not for each frame in window */ - iwl_tx_status_reply_compressed_ba(priv, agg, ba_resp); - - /* Release all TFDs before the SSN, i.e. all TFDs in front of - * block-ack window (we assume that they've been successfully - * transmitted ... if not, it's too late anyway). */ - if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { - /* calculate mac80211 ampdu sw queue to wake */ - int freed = iwl_tx_queue_reclaim(priv, scd_flow, index); - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); - - if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && - priv->mac80211_registered && - (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) - iwl_wake_queue(priv, txq->swq_id); - - iwl_txq_check_empty(priv, sta_id, tid, scd_flow); - } -} -EXPORT_SYMBOL(iwl_rx_reply_compressed_ba); - #ifdef CONFIG_IWLWIFI_DEBUG #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x -- cgit v1.2.3 From 54b81550dd674466fe7d01629d2aab015c545a1e Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 17 Mar 2010 13:34:35 -0700 Subject: iwlwifi: move agn only rx functions from iwlcore to iwlagn Identify the rx functions only used by agn driver and move those from iwlcore to iwlagn. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 200 +++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-agn.c | 12 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 8 ++ drivers/net/wireless/iwlwifi/iwl-core.h | 5 - drivers/net/wireless/iwlwifi/iwl-rx.c | 203 ----------------------------- 5 files changed, 213 insertions(+), 215 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 6f9d52d04464..3117382cfd48 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -491,7 +491,7 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv) } else iwlagn_rx_queue_reset(priv, rxq); - iwl_rx_replenish(priv); + iwlagn_rx_replenish(priv); iwlagn_rx_init(priv, rxq); @@ -511,3 +511,201 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv) return 0; } + +/** + * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr + */ +static inline __le32 iwlagn_dma_addr2rbd_ptr(struct iwl_priv *priv, + dma_addr_t dma_addr) +{ + return cpu_to_le32((u32)(dma_addr >> 8)); +} + +/** + * iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool + * + * If there are slots in the RX queue that need to be restocked, + * and we have free pre-allocated buffers, fill the ranks as much + * as we can, pulling from rx_free. + * + * This moves the 'write' index forward to catch up with 'processed', and + * also updates the memory address in the firmware to reference the new + * target buffer. + */ +void iwlagn_rx_queue_restock(struct iwl_priv *priv) +{ + struct iwl_rx_queue *rxq = &priv->rxq; + struct list_head *element; + struct iwl_rx_mem_buffer *rxb; + unsigned long flags; + int write; + + spin_lock_irqsave(&rxq->lock, flags); + write = rxq->write & ~0x7; + while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { + /* Get next free Rx buffer, remove from free list */ + element = rxq->rx_free.next; + rxb = list_entry(element, struct iwl_rx_mem_buffer, list); + list_del(element); + + /* Point to Rx buffer via next RBD in circular buffer */ + rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(priv, + rxb->page_dma); + rxq->queue[rxq->write] = rxb; + rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; + rxq->free_count--; + } + spin_unlock_irqrestore(&rxq->lock, flags); + /* If the pre-allocated buffer pool is dropping low, schedule to + * refill it */ + if (rxq->free_count <= RX_LOW_WATERMARK) + queue_work(priv->workqueue, &priv->rx_replenish); + + + /* If we've added more space for the firmware to place data, tell it. + * Increment device's write pointer in multiples of 8. */ + if (rxq->write_actual != (rxq->write & ~0x7)) { + spin_lock_irqsave(&rxq->lock, flags); + rxq->need_update = 1; + spin_unlock_irqrestore(&rxq->lock, flags); + iwl_rx_queue_update_write_ptr(priv, rxq); + } +} + +/** + * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free + * + * When moving to rx_free an SKB is allocated for the slot. + * + * Also restock the Rx queue via iwl_rx_queue_restock. + * This is called as a scheduled work item (except for during initialization) + */ +void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) +{ + struct iwl_rx_queue *rxq = &priv->rxq; + struct list_head *element; + struct iwl_rx_mem_buffer *rxb; + struct page *page; + unsigned long flags; + gfp_t gfp_mask = priority; + + while (1) { + spin_lock_irqsave(&rxq->lock, flags); + if (list_empty(&rxq->rx_used)) { + spin_unlock_irqrestore(&rxq->lock, flags); + return; + } + spin_unlock_irqrestore(&rxq->lock, flags); + + if (rxq->free_count > RX_LOW_WATERMARK) + gfp_mask |= __GFP_NOWARN; + + if (priv->hw_params.rx_page_order > 0) + gfp_mask |= __GFP_COMP; + + /* Alloc a new receive buffer */ + page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); + if (!page) { + if (net_ratelimit()) + IWL_DEBUG_INFO(priv, "alloc_pages failed, " + "order: %d\n", + priv->hw_params.rx_page_order); + + if ((rxq->free_count <= RX_LOW_WATERMARK) && + net_ratelimit()) + IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n", + priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", + rxq->free_count); + /* We don't reschedule replenish work here -- we will + * call the restock method and if it still needs + * more buffers it will schedule replenish */ + return; + } + + spin_lock_irqsave(&rxq->lock, flags); + + if (list_empty(&rxq->rx_used)) { + spin_unlock_irqrestore(&rxq->lock, flags); + __free_pages(page, priv->hw_params.rx_page_order); + return; + } + element = rxq->rx_used.next; + rxb = list_entry(element, struct iwl_rx_mem_buffer, list); + list_del(element); + + spin_unlock_irqrestore(&rxq->lock, flags); + + rxb->page = page; + /* Get physical address of the RB */ + rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, + PAGE_SIZE << priv->hw_params.rx_page_order, + PCI_DMA_FROMDEVICE); + /* dma address must be no more than 36 bits */ + BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); + /* and also 256 byte aligned! */ + BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); + + spin_lock_irqsave(&rxq->lock, flags); + + list_add_tail(&rxb->list, &rxq->rx_free); + rxq->free_count++; + priv->alloc_rxb_page++; + + spin_unlock_irqrestore(&rxq->lock, flags); + } +} + +void iwlagn_rx_replenish(struct iwl_priv *priv) +{ + unsigned long flags; + + iwlagn_rx_allocate(priv, GFP_KERNEL); + + spin_lock_irqsave(&priv->lock, flags); + iwlagn_rx_queue_restock(priv); + spin_unlock_irqrestore(&priv->lock, flags); +} + +void iwlagn_rx_replenish_now(struct iwl_priv *priv) +{ + iwlagn_rx_allocate(priv, GFP_ATOMIC); + + iwlagn_rx_queue_restock(priv); +} + +/* Assumes that the skb field of the buffers in 'pool' is kept accurate. + * If an SKB has been detached, the POOL needs to have its SKB set to NULL + * This free routine walks the list of POOL entries and if SKB is set to + * non NULL it is unmapped and freed + */ +void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) +{ + int i; + for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { + if (rxq->pool[i].page != NULL) { + pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, + PAGE_SIZE << priv->hw_params.rx_page_order, + PCI_DMA_FROMDEVICE); + __iwl_free_pages(priv, rxq->pool[i].page); + rxq->pool[i].page = NULL; + } + } + + dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, + rxq->dma_addr); + dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), + rxq->rb_stts, rxq->rb_stts_dma); + rxq->bd = NULL; + rxq->rb_stts = NULL; +} + +int iwlagn_rxq_stop(struct iwl_priv *priv) +{ + + /* stop Rx DMA */ + iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, + FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); + + return 0; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a57933b8f6fa..d9a287b639bf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1015,7 +1015,7 @@ void iwl_rx_handle(struct iwl_priv *priv) count++; if (count >= 8) { rxq->read = i; - iwl_rx_replenish_now(priv); + iwlagn_rx_replenish_now(priv); count = 0; } } @@ -1024,9 +1024,9 @@ void iwl_rx_handle(struct iwl_priv *priv) /* Backtrack one entry */ rxq->read = i; if (fill_rx) - iwl_rx_replenish_now(priv); + iwlagn_rx_replenish_now(priv); else - iwl_rx_queue_restock(priv); + iwlagn_rx_queue_restock(priv); } /* call this function to flush any scheduled tasklet */ @@ -2250,7 +2250,7 @@ static void __iwl_down(struct iwl_priv *priv) iwl_disable_ict(priv); iwlagn_txq_ctx_stop(priv); - iwl_rxq_stop(priv); + iwlagn_rxq_stop(priv); /* Power-down device's busmaster DMA clocks */ iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); @@ -2521,7 +2521,7 @@ static void iwl_bg_rx_replenish(struct work_struct *data) return; mutex_lock(&priv->mutex); - iwl_rx_replenish(priv); + iwlagn_rx_replenish(priv); mutex_unlock(&priv->mutex); } @@ -3737,7 +3737,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) iwl_dealloc_ucode_pci(priv); if (priv->rxq.bd) - iwl_rx_queue_free(priv, &priv->rxq); + iwlagn_rx_queue_free(priv, &priv->rxq); iwlagn_hw_txq_ctx_free(priv); iwl_eeprom_free(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index c75a767872f7..48f7de0914cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -117,6 +117,14 @@ void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); int iwlagn_hw_nic_init(struct iwl_priv *priv); +/* rx */ +void iwlagn_rx_queue_restock(struct iwl_priv *priv); +void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority); +void iwlagn_rx_replenish(struct iwl_priv *priv); +void iwlagn_rx_replenish_now(struct iwl_priv *priv); +void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); +int iwlagn_rxq_stop(struct iwl_priv *priv); + /* tx */ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); int iwlagn_tx_agg_start(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 446d27bd4301..7c6ac34940fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -419,17 +419,12 @@ void iwl_rx_reply_error(struct iwl_priv *priv, /***************************************************** * RX ******************************************************/ -void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); void iwl_cmd_queue_free(struct iwl_priv *priv); int iwl_rx_queue_alloc(struct iwl_priv *priv); void iwl_rx_handle(struct iwl_priv *priv); void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q); -void iwl_rx_replenish(struct iwl_priv *priv); -void iwl_rx_replenish_now(struct iwl_priv *priv); -void iwl_rx_queue_restock(struct iwl_priv *priv); int iwl_rx_queue_space(const struct iwl_rx_queue *q); -void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); /* Handlers */ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index b75c3ccd1c43..45230c6a7899 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -162,197 +162,6 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q spin_unlock_irqrestore(&q->lock, flags); } EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); -/** - * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr - */ -static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv, - dma_addr_t dma_addr) -{ - return cpu_to_le32((u32)(dma_addr >> 8)); -} - -/** - * iwl_rx_queue_restock - refill RX queue from pre-allocated pool - * - * If there are slots in the RX queue that need to be restocked, - * and we have free pre-allocated buffers, fill the ranks as much - * as we can, pulling from rx_free. - * - * This moves the 'write' index forward to catch up with 'processed', and - * also updates the memory address in the firmware to reference the new - * target buffer. - */ -void iwl_rx_queue_restock(struct iwl_priv *priv) -{ - struct iwl_rx_queue *rxq = &priv->rxq; - struct list_head *element; - struct iwl_rx_mem_buffer *rxb; - unsigned long flags; - int write; - - spin_lock_irqsave(&rxq->lock, flags); - write = rxq->write & ~0x7; - while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { - /* Get next free Rx buffer, remove from free list */ - element = rxq->rx_free.next; - rxb = list_entry(element, struct iwl_rx_mem_buffer, list); - list_del(element); - - /* Point to Rx buffer via next RBD in circular buffer */ - rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->page_dma); - rxq->queue[rxq->write] = rxb; - rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; - rxq->free_count--; - } - spin_unlock_irqrestore(&rxq->lock, flags); - /* If the pre-allocated buffer pool is dropping low, schedule to - * refill it */ - if (rxq->free_count <= RX_LOW_WATERMARK) - queue_work(priv->workqueue, &priv->rx_replenish); - - - /* If we've added more space for the firmware to place data, tell it. - * Increment device's write pointer in multiples of 8. */ - if (rxq->write_actual != (rxq->write & ~0x7)) { - spin_lock_irqsave(&rxq->lock, flags); - rxq->need_update = 1; - spin_unlock_irqrestore(&rxq->lock, flags); - iwl_rx_queue_update_write_ptr(priv, rxq); - } -} -EXPORT_SYMBOL(iwl_rx_queue_restock); - - -/** - * iwl_rx_replenish - Move all used packet from rx_used to rx_free - * - * When moving to rx_free an SKB is allocated for the slot. - * - * Also restock the Rx queue via iwl_rx_queue_restock. - * This is called as a scheduled work item (except for during initialization) - */ -void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) -{ - struct iwl_rx_queue *rxq = &priv->rxq; - struct list_head *element; - struct iwl_rx_mem_buffer *rxb; - struct page *page; - unsigned long flags; - gfp_t gfp_mask = priority; - - while (1) { - spin_lock_irqsave(&rxq->lock, flags); - if (list_empty(&rxq->rx_used)) { - spin_unlock_irqrestore(&rxq->lock, flags); - return; - } - spin_unlock_irqrestore(&rxq->lock, flags); - - if (rxq->free_count > RX_LOW_WATERMARK) - gfp_mask |= __GFP_NOWARN; - - if (priv->hw_params.rx_page_order > 0) - gfp_mask |= __GFP_COMP; - - /* Alloc a new receive buffer */ - page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); - if (!page) { - if (net_ratelimit()) - IWL_DEBUG_INFO(priv, "alloc_pages failed, " - "order: %d\n", - priv->hw_params.rx_page_order); - - if ((rxq->free_count <= RX_LOW_WATERMARK) && - net_ratelimit()) - IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n", - priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", - rxq->free_count); - /* We don't reschedule replenish work here -- we will - * call the restock method and if it still needs - * more buffers it will schedule replenish */ - return; - } - - spin_lock_irqsave(&rxq->lock, flags); - - if (list_empty(&rxq->rx_used)) { - spin_unlock_irqrestore(&rxq->lock, flags); - __free_pages(page, priv->hw_params.rx_page_order); - return; - } - element = rxq->rx_used.next; - rxb = list_entry(element, struct iwl_rx_mem_buffer, list); - list_del(element); - - spin_unlock_irqrestore(&rxq->lock, flags); - - rxb->page = page; - /* Get physical address of the RB */ - rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, - PAGE_SIZE << priv->hw_params.rx_page_order, - PCI_DMA_FROMDEVICE); - /* dma address must be no more than 36 bits */ - BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); - /* and also 256 byte aligned! */ - BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); - - spin_lock_irqsave(&rxq->lock, flags); - - list_add_tail(&rxb->list, &rxq->rx_free); - rxq->free_count++; - priv->alloc_rxb_page++; - - spin_unlock_irqrestore(&rxq->lock, flags); - } -} - -void iwl_rx_replenish(struct iwl_priv *priv) -{ - unsigned long flags; - - iwl_rx_allocate(priv, GFP_KERNEL); - - spin_lock_irqsave(&priv->lock, flags); - iwl_rx_queue_restock(priv); - spin_unlock_irqrestore(&priv->lock, flags); -} -EXPORT_SYMBOL(iwl_rx_replenish); - -void iwl_rx_replenish_now(struct iwl_priv *priv) -{ - iwl_rx_allocate(priv, GFP_ATOMIC); - - iwl_rx_queue_restock(priv); -} -EXPORT_SYMBOL(iwl_rx_replenish_now); - - -/* Assumes that the skb field of the buffers in 'pool' is kept accurate. - * If an SKB has been detached, the POOL needs to have its SKB set to NULL - * This free routine walks the list of POOL entries and if SKB is set to - * non NULL it is unmapped and freed - */ -void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) -{ - int i; - for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { - if (rxq->pool[i].page != NULL) { - pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, - PAGE_SIZE << priv->hw_params.rx_page_order, - PCI_DMA_FROMDEVICE); - __iwl_free_pages(priv, rxq->pool[i].page); - rxq->pool[i].page = NULL; - } - } - - dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, - rxq->dma_addr); - dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), - rxq->rb_stts, rxq->rb_stts_dma); - rxq->bd = NULL; - rxq->rb_stts = NULL; -} -EXPORT_SYMBOL(iwl_rx_queue_free); int iwl_rx_queue_alloc(struct iwl_priv *priv) { @@ -395,18 +204,6 @@ err_bd: } EXPORT_SYMBOL(iwl_rx_queue_alloc); -int iwl_rxq_stop(struct iwl_priv *priv) -{ - - /* stop Rx DMA */ - iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, - FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); - - return 0; -} -EXPORT_SYMBOL(iwl_rxq_stop); - void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) -- cgit v1.2.3 From 8d801080dd8d28bf7d85cacba131f18b7653ee49 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 17 Mar 2010 13:34:36 -0700 Subject: iwlwifi: more clean up to move agn only rx functions from iwlcore to iwlagn Move more functions only used by agn driver from iwlcore to iwlagn. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-4965.c | 6 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 436 ++++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 26 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 7 + drivers/net/wireless/iwlwifi/iwl-core.c | 45 --- drivers/net/wireless/iwlwifi/iwl-core.h | 7 - drivers/net/wireless/iwlwifi/iwl-rx.c | 411 --------------------------- 8 files changed, 470 insertions(+), 472 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index cee31cdf0a22..af48d07bb29d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1881,7 +1881,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags &= ~IEEE80211_TX_CTL_AMPDU; info->flags |= iwl_tx_status_to_mac80211(status); - iwl_hwrate_to_tx_control(priv, rate_n_flags, info); + iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info); /* FIXME: code repetition end */ IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", @@ -2036,7 +2036,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, } else { info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags |= iwl_tx_status_to_mac80211(status); - iwl_hwrate_to_tx_control(priv, + iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), info); @@ -2102,7 +2102,7 @@ static int iwl4965_calc_rssi(struct iwl_priv *priv, static void iwl4965_rx_handler_setup(struct iwl_priv *priv) { /* Legacy Rx frames */ - priv->rx_handlers[REPLY_RX] = iwl_rx_reply_rx; + priv->rx_handlers[REPLY_RX] = iwlagn_rx_reply_rx; /* Tx response */ priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 3117382cfd48..226862d3d5ac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -26,7 +26,7 @@ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * *****************************************************************************/ - +#include #include #include #include @@ -80,7 +80,7 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags &= ~IEEE80211_TX_CTL_AMPDU; info->flags |= iwl_tx_status_to_mac80211(status); - iwl_hwrate_to_tx_control(priv, rate_n_flags, info); + iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info); /* FIXME: code repetition end */ @@ -225,7 +225,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags |= iwl_tx_status_to_mac80211(status); - iwl_hwrate_to_tx_control(priv, + iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), info); @@ -709,3 +709,433 @@ int iwlagn_rxq_stop(struct iwl_priv *priv) return 0; } + +int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) +{ + int idx = 0; + int band_offset = 0; + + /* HT rate format: mac80211 wants an MCS number, which is just LSB */ + if (rate_n_flags & RATE_MCS_HT_MSK) { + idx = (rate_n_flags & 0xff); + return idx; + /* Legacy rate format, search for match in table */ + } else { + if (band == IEEE80211_BAND_5GHZ) + band_offset = IWL_FIRST_OFDM_RATE; + for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) + if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) + return idx - band_offset; + } + + return -1; +} + +/* Calc max signal level (dBm) among 3 possible receivers */ +static inline int iwlagn_calc_rssi(struct iwl_priv *priv, + struct iwl_rx_phy_res *rx_resp) +{ + return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); +} + +#ifdef CONFIG_IWLWIFI_DEBUG +/** + * iwlagn_dbg_report_frame - dump frame to syslog during debug sessions + * + * You may hack this function to show different aspects of received frames, + * including selective frame dumps. + * group100 parameter selects whether to show 1 out of 100 good data frames. + * All beacon and probe response frames are printed. + */ +static void iwlagn_dbg_report_frame(struct iwl_priv *priv, + struct iwl_rx_phy_res *phy_res, u16 length, + struct ieee80211_hdr *header, int group100) +{ + u32 to_us; + u32 print_summary = 0; + u32 print_dump = 0; /* set to 1 to dump all frames' contents */ + u32 hundred = 0; + u32 dataframe = 0; + __le16 fc; + u16 seq_ctl; + u16 channel; + u16 phy_flags; + u32 rate_n_flags; + u32 tsf_low; + int rssi; + + if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) + return; + + /* MAC header */ + fc = header->frame_control; + seq_ctl = le16_to_cpu(header->seq_ctrl); + + /* metadata */ + channel = le16_to_cpu(phy_res->channel); + phy_flags = le16_to_cpu(phy_res->phy_flags); + rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); + + /* signal statistics */ + rssi = iwlagn_calc_rssi(priv, phy_res); + tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff; + + to_us = !compare_ether_addr(header->addr1, priv->mac_addr); + + /* if data frame is to us and all is good, + * (optionally) print summary for only 1 out of every 100 */ + if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == + cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { + dataframe = 1; + if (!group100) + print_summary = 1; /* print each frame */ + else if (priv->framecnt_to_us < 100) { + priv->framecnt_to_us++; + print_summary = 0; + } else { + priv->framecnt_to_us = 0; + print_summary = 1; + hundred = 1; + } + } else { + /* print summary for all other frames */ + print_summary = 1; + } + + if (print_summary) { + char *title; + int rate_idx; + u32 bitrate; + + if (hundred) + title = "100Frames"; + else if (ieee80211_has_retry(fc)) + title = "Retry"; + else if (ieee80211_is_assoc_resp(fc)) + title = "AscRsp"; + else if (ieee80211_is_reassoc_resp(fc)) + title = "RasRsp"; + else if (ieee80211_is_probe_resp(fc)) { + title = "PrbRsp"; + print_dump = 1; /* dump frame contents */ + } else if (ieee80211_is_beacon(fc)) { + title = "Beacon"; + print_dump = 1; /* dump frame contents */ + } else if (ieee80211_is_atim(fc)) + title = "ATIM"; + else if (ieee80211_is_auth(fc)) + title = "Auth"; + else if (ieee80211_is_deauth(fc)) + title = "DeAuth"; + else if (ieee80211_is_disassoc(fc)) + title = "DisAssoc"; + else + title = "Frame"; + + rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); + if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) { + bitrate = 0; + WARN_ON_ONCE(1); + } else { + bitrate = iwl_rates[rate_idx].ieee / 2; + } + + /* print frame summary. + * MAC addresses show just the last byte (for brevity), + * but you can hack it to show more, if you'd like to. */ + if (dataframe) + IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " + "len=%u, rssi=%d, chnl=%d, rate=%u, \n", + title, le16_to_cpu(fc), header->addr1[5], + length, rssi, channel, bitrate); + else { + /* src/dst addresses assume managed mode */ + IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, " + "len=%u, rssi=%d, tim=%lu usec, " + "phy=0x%02x, chnl=%d\n", + title, le16_to_cpu(fc), header->addr1[5], + header->addr3[5], length, rssi, + tsf_low - priv->scan_start_tsf, + phy_flags, channel); + } + } + if (print_dump) + iwl_print_hex_dump(priv, IWL_DL_RX, header, length); +} +#endif + +static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) +{ + u32 decrypt_out = 0; + + if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == + RX_RES_STATUS_STATION_FOUND) + decrypt_out |= (RX_RES_STATUS_STATION_FOUND | + RX_RES_STATUS_NO_STATION_INFO_MISMATCH); + + decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); + + /* packet was not encrypted */ + if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == + RX_RES_STATUS_SEC_TYPE_NONE) + return decrypt_out; + + /* packet was encrypted with unknown alg */ + if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == + RX_RES_STATUS_SEC_TYPE_ERR) + return decrypt_out; + + /* decryption was not done in HW */ + if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != + RX_MPDU_RES_STATUS_DEC_DONE_MSK) + return decrypt_out; + + switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { + + case RX_RES_STATUS_SEC_TYPE_CCMP: + /* alg is CCM: check MIC only */ + if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) + /* Bad MIC */ + decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; + else + decrypt_out |= RX_RES_STATUS_DECRYPT_OK; + + break; + + case RX_RES_STATUS_SEC_TYPE_TKIP: + if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { + /* Bad TTAK */ + decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; + break; + } + /* fall through if TTAK OK */ + default: + if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) + decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; + else + decrypt_out |= RX_RES_STATUS_DECRYPT_OK; + break; + }; + + IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", + decrypt_in, decrypt_out); + + return decrypt_out; +} + +static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, + struct ieee80211_hdr *hdr, + u16 len, + u32 ampdu_status, + struct iwl_rx_mem_buffer *rxb, + struct ieee80211_rx_status *stats) +{ + struct sk_buff *skb; + int ret = 0; + __le16 fc = hdr->frame_control; + + /* We only process data packets if the interface is open */ + if (unlikely(!priv->is_open)) { + IWL_DEBUG_DROP_LIMIT(priv, + "Dropping packet while interface is not open.\n"); + return; + } + + /* In case of HW accelerated crypto and bad decryption, drop */ + if (!priv->cfg->mod_params->sw_crypto && + iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) + return; + + skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); + if (!skb) { + IWL_ERR(priv, "alloc_skb failed\n"); + return; + } + + skb_reserve(skb, IWL_LINK_HDR_MAX); + skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); + + /* mac80211 currently doesn't support paged SKB. Convert it to + * linear SKB for management frame and data frame requires + * software decryption or software defragementation. */ + if (ieee80211_is_mgmt(fc) || + ieee80211_has_protected(fc) || + ieee80211_has_morefrags(fc) || + le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG || + (ieee80211_is_data_qos(fc) && + *ieee80211_get_qos_ctl(hdr) & + IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)) + ret = skb_linearize(skb); + else + ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? + 0 : -ENOMEM; + + if (ret) { + kfree_skb(skb); + goto out; + } + + /* + * XXX: We cannot touch the page and its virtual memory (hdr) after + * here. It might have already been freed by the above skb change. + */ + + iwl_update_stats(priv, false, fc, len); + memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); + + ieee80211_rx(priv->hw, skb); + out: + priv->alloc_rxb_page--; + rxb->page = NULL; +} + +/* Called for REPLY_RX (legacy ABG frames), or + * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ +void iwlagn_rx_reply_rx(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct ieee80211_hdr *header; + struct ieee80211_rx_status rx_status; + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_rx_phy_res *phy_res; + __le32 rx_pkt_status; + struct iwl4965_rx_mpdu_res_start *amsdu; + u32 len; + u32 ampdu_status; + u32 rate_n_flags; + + /** + * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. + * REPLY_RX: physical layer info is in this buffer + * REPLY_RX_MPDU_CMD: physical layer info was sent in separate + * command and cached in priv->last_phy_res + * + * Here we set up local variables depending on which command is + * received. + */ + if (pkt->hdr.cmd == REPLY_RX) { + phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; + header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) + + phy_res->cfg_phy_cnt); + + len = le16_to_cpu(phy_res->byte_count); + rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + + phy_res->cfg_phy_cnt + len); + ampdu_status = le32_to_cpu(rx_pkt_status); + } else { + if (!priv->last_phy_res[0]) { + IWL_ERR(priv, "MPDU frame without cached PHY data\n"); + return; + } + phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; + amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; + header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); + len = le16_to_cpu(amsdu->byte_count); + rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); + ampdu_status = iwlagn_translate_rx_status(priv, + le32_to_cpu(rx_pkt_status)); + } + + if ((unlikely(phy_res->cfg_phy_cnt > 20))) { + IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", + phy_res->cfg_phy_cnt); + return; + } + + if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || + !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { + IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", + le32_to_cpu(rx_pkt_status)); + return; + } + + /* This will be used in several places later */ + rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); + + /* rx_status carries information about the packet to mac80211 */ + rx_status.mactime = le64_to_cpu(phy_res->timestamp); + rx_status.freq = + ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel)); + rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? + IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + rx_status.rate_idx = + iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); + rx_status.flag = 0; + + /* TSF isn't reliable. In order to allow smooth user experience, + * this W/A doesn't propagate it to the mac80211 */ + /*rx_status.flag |= RX_FLAG_TSFT;*/ + + priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); + + /* Find max signal strength (dBm) among 3 antenna/receiver chains */ + rx_status.signal = iwlagn_calc_rssi(priv, phy_res); + + /* Meaningful noise values are available only from beacon statistics, + * which are gathered only when associated, and indicate noise + * only for the associated network channel ... + * Ignore these noise values while scanning (other channels) */ + if (iwl_is_associated(priv) && + !test_bit(STATUS_SCANNING, &priv->status)) { + rx_status.noise = priv->last_rx_noise; + } else { + rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; + } + + /* Reset beacon noise level if not associated. */ + if (!iwl_is_associated(priv)) + priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; + +#ifdef CONFIG_IWLWIFI_DEBUG + /* Set "1" to report good data frames in groups of 100 */ + if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) + iwlagn_dbg_report_frame(priv, phy_res, len, header, 1); +#endif + iwl_dbg_log_rx_data_frame(priv, len, header); + IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n", + rx_status.signal, rx_status.noise, + (unsigned long long)rx_status.mactime); + + /* + * "antenna number" + * + * It seems that the antenna field in the phy flags value + * is actually a bit field. This is undefined by radiotap, + * it wants an actual antenna number but I always get "7" + * for most legacy frames I receive indicating that the + * same frame was received on all three RX chains. + * + * I think this field should be removed in favor of a + * new 802.11n radiotap field "RX chains" that is defined + * as a bitmask. + */ + rx_status.antenna = + (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) + >> RX_RES_PHY_FLAGS_ANTENNA_POS; + + /* set the preamble flag if appropriate */ + if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) + rx_status.flag |= RX_FLAG_SHORTPRE; + + /* Set up the HT phy flags */ + if (rate_n_flags & RATE_MCS_HT_MSK) + rx_status.flag |= RX_FLAG_HT; + if (rate_n_flags & RATE_MCS_HT40_MSK) + rx_status.flag |= RX_FLAG_40MHZ; + if (rate_n_flags & RATE_MCS_SGI_MSK) + rx_status.flag |= RX_FLAG_SHORT_GI; + + iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status, + rxb, &rx_status); +} + +/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). + * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ +void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + priv->last_phy_res[0] = 1; + memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), + sizeof(struct iwl_rx_phy_res)); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 4e4b70d10804..257e4aff3d96 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -38,6 +38,7 @@ #include "iwl-io.h" #include "iwl-helpers.h" #include "iwl-agn-hw.h" +#include "iwl-agn.h" /* * mac80211 queues, ACs, hardware queues, FIFOs. @@ -1206,13 +1207,36 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, info->flags |= IEEE80211_TX_STAT_AMPDU; info->status.ampdu_ack_map = successes; info->status.ampdu_ack_len = agg->frame_count; - iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info); + iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); return 0; } +/** + * translate ucode response to mac80211 tx status control values + */ +void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, + struct ieee80211_tx_info *info) +{ + struct ieee80211_tx_rate *r = &info->control.rates[0]; + + info->antenna_sel_tx = + ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); + if (rate_n_flags & RATE_MCS_HT_MSK) + r->flags |= IEEE80211_TX_RC_MCS; + if (rate_n_flags & RATE_MCS_GF_MSK) + r->flags |= IEEE80211_TX_RC_GREEN_FIELD; + if (rate_n_flags & RATE_MCS_HT40_MSK) + r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + if (rate_n_flags & RATE_MCS_DUP_MSK) + r->flags |= IEEE80211_TX_RC_DUP_DATA; + if (rate_n_flags & RATE_MCS_SGI_MSK) + r->flags |= IEEE80211_TX_RC_SHORT_GI; + r->idx = iwlagn_hwrate_to_mac80211_idx(rate_n_flags, info->band); +} + /** * iwlagn_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA * diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d9a287b639bf..bc08e9bdf9ac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -884,8 +884,8 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] = iwl_rx_missed_beacon_notif; /* Rx handlers */ - priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy; - priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx; + priv->rx_handlers[REPLY_RX_PHY_CMD] = iwlagn_rx_reply_rx_phy; + priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwlagn_rx_reply_rx; /* block ack */ priv->rx_handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba; /* Set up hardware specific Rx handlers */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 48f7de0914cb..5ad14055eda3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -124,8 +124,15 @@ void iwlagn_rx_replenish(struct iwl_priv *priv); void iwlagn_rx_replenish_now(struct iwl_priv *priv); void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); int iwlagn_rxq_stop(struct iwl_priv *priv); +int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); +void iwlagn_rx_reply_rx(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb); +void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb); /* tx */ +void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, + struct ieee80211_tx_info *info); int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 0dc41d84dc15..6fe785380824 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -140,30 +140,6 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = { }; EXPORT_SYMBOL(iwl_rates); -/** - * translate ucode response to mac80211 tx status control values - */ -void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, - struct ieee80211_tx_info *info) -{ - struct ieee80211_tx_rate *r = &info->control.rates[0]; - - info->antenna_sel_tx = - ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); - if (rate_n_flags & RATE_MCS_HT_MSK) - r->flags |= IEEE80211_TX_RC_MCS; - if (rate_n_flags & RATE_MCS_GF_MSK) - r->flags |= IEEE80211_TX_RC_GREEN_FIELD; - if (rate_n_flags & RATE_MCS_HT40_MSK) - r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (rate_n_flags & RATE_MCS_DUP_MSK) - r->flags |= IEEE80211_TX_RC_DUP_DATA; - if (rate_n_flags & RATE_MCS_SGI_MSK) - r->flags |= IEEE80211_TX_RC_SHORT_GI; - r->idx = iwl_hwrate_to_mac80211_idx(rate_n_flags, info->band); -} -EXPORT_SYMBOL(iwl_hwrate_to_tx_control); - int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) { int idx = 0; @@ -195,27 +171,6 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) } EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); -int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) -{ - int idx = 0; - int band_offset = 0; - - /* HT rate format: mac80211 wants an MCS number, which is just LSB */ - if (rate_n_flags & RATE_MCS_HT_MSK) { - idx = (rate_n_flags & 0xff); - return idx; - /* Legacy rate format, search for match in table */ - } else { - if (band == IEEE80211_BAND_5GHZ) - band_offset = IWL_FIRST_OFDM_RATE; - for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) - if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) - return idx - band_offset; - } - - return -1; -} - u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant) { int i; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7c6ac34940fe..22f84f3c3c40 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -467,10 +467,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); * Rate ******************************************************************************/ -void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, - struct ieee80211_tx_info *info); int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); -int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); @@ -670,10 +667,6 @@ extern int iwl_send_statistics_request(struct iwl_priv *priv, extern int iwl_verify_ucode(struct iwl_priv *priv); extern int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_link_quality_cmd *lq, u8 flags, bool init); -extern void iwl_rx_reply_rx(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); -extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); void iwl_apm_stop(struct iwl_priv *priv); int iwl_apm_init(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 45230c6a7899..3a4313841fe7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -489,139 +489,6 @@ void iwl_reply_statistics(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_reply_statistics); -/* Calc max signal level (dBm) among 3 possible receivers */ -static inline int iwl_calc_rssi(struct iwl_priv *priv, - struct iwl_rx_phy_res *rx_resp) -{ - return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); -} - -#ifdef CONFIG_IWLWIFI_DEBUG -/** - * iwl_dbg_report_frame - dump frame to syslog during debug sessions - * - * You may hack this function to show different aspects of received frames, - * including selective frame dumps. - * group100 parameter selects whether to show 1 out of 100 good data frames. - * All beacon and probe response frames are printed. - */ -static void iwl_dbg_report_frame(struct iwl_priv *priv, - struct iwl_rx_phy_res *phy_res, u16 length, - struct ieee80211_hdr *header, int group100) -{ - u32 to_us; - u32 print_summary = 0; - u32 print_dump = 0; /* set to 1 to dump all frames' contents */ - u32 hundred = 0; - u32 dataframe = 0; - __le16 fc; - u16 seq_ctl; - u16 channel; - u16 phy_flags; - u32 rate_n_flags; - u32 tsf_low; - int rssi; - - if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) - return; - - /* MAC header */ - fc = header->frame_control; - seq_ctl = le16_to_cpu(header->seq_ctrl); - - /* metadata */ - channel = le16_to_cpu(phy_res->channel); - phy_flags = le16_to_cpu(phy_res->phy_flags); - rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); - - /* signal statistics */ - rssi = iwl_calc_rssi(priv, phy_res); - tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff; - - to_us = !compare_ether_addr(header->addr1, priv->mac_addr); - - /* if data frame is to us and all is good, - * (optionally) print summary for only 1 out of every 100 */ - if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == - cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { - dataframe = 1; - if (!group100) - print_summary = 1; /* print each frame */ - else if (priv->framecnt_to_us < 100) { - priv->framecnt_to_us++; - print_summary = 0; - } else { - priv->framecnt_to_us = 0; - print_summary = 1; - hundred = 1; - } - } else { - /* print summary for all other frames */ - print_summary = 1; - } - - if (print_summary) { - char *title; - int rate_idx; - u32 bitrate; - - if (hundred) - title = "100Frames"; - else if (ieee80211_has_retry(fc)) - title = "Retry"; - else if (ieee80211_is_assoc_resp(fc)) - title = "AscRsp"; - else if (ieee80211_is_reassoc_resp(fc)) - title = "RasRsp"; - else if (ieee80211_is_probe_resp(fc)) { - title = "PrbRsp"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_beacon(fc)) { - title = "Beacon"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_atim(fc)) - title = "ATIM"; - else if (ieee80211_is_auth(fc)) - title = "Auth"; - else if (ieee80211_is_deauth(fc)) - title = "DeAuth"; - else if (ieee80211_is_disassoc(fc)) - title = "DisAssoc"; - else - title = "Frame"; - - rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); - if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) { - bitrate = 0; - WARN_ON_ONCE(1); - } else { - bitrate = iwl_rates[rate_idx].ieee / 2; - } - - /* print frame summary. - * MAC addresses show just the last byte (for brevity), - * but you can hack it to show more, if you'd like to. */ - if (dataframe) - IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " - "len=%u, rssi=%d, chnl=%d, rate=%u, \n", - title, le16_to_cpu(fc), header->addr1[5], - length, rssi, channel, bitrate); - else { - /* src/dst addresses assume managed mode */ - IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, " - "len=%u, rssi=%d, tim=%lu usec, " - "phy=0x%02x, chnl=%d\n", - title, le16_to_cpu(fc), header->addr1[5], - header->addr3[5], length, rssi, - tsf_low - priv->scan_start_tsf, - phy_flags, channel); - } - } - if (print_dump) - iwl_print_hex_dump(priv, IWL_DL_RX, header, length); -} -#endif - /* * returns non-zero if packet should be dropped */ @@ -669,281 +536,3 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, return 0; } EXPORT_SYMBOL(iwl_set_decrypted_flag); - -static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) -{ - u32 decrypt_out = 0; - - if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == - RX_RES_STATUS_STATION_FOUND) - decrypt_out |= (RX_RES_STATUS_STATION_FOUND | - RX_RES_STATUS_NO_STATION_INFO_MISMATCH); - - decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); - - /* packet was not encrypted */ - if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == - RX_RES_STATUS_SEC_TYPE_NONE) - return decrypt_out; - - /* packet was encrypted with unknown alg */ - if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == - RX_RES_STATUS_SEC_TYPE_ERR) - return decrypt_out; - - /* decryption was not done in HW */ - if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != - RX_MPDU_RES_STATUS_DEC_DONE_MSK) - return decrypt_out; - - switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { - - case RX_RES_STATUS_SEC_TYPE_CCMP: - /* alg is CCM: check MIC only */ - if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) - /* Bad MIC */ - decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; - else - decrypt_out |= RX_RES_STATUS_DECRYPT_OK; - - break; - - case RX_RES_STATUS_SEC_TYPE_TKIP: - if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { - /* Bad TTAK */ - decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; - break; - } - /* fall through if TTAK OK */ - default: - if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) - decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; - else - decrypt_out |= RX_RES_STATUS_DECRYPT_OK; - break; - }; - - IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", - decrypt_in, decrypt_out); - - return decrypt_out; -} - -static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, - u16 len, - u32 ampdu_status, - struct iwl_rx_mem_buffer *rxb, - struct ieee80211_rx_status *stats) -{ - struct sk_buff *skb; - int ret = 0; - __le16 fc = hdr->frame_control; - - /* We only process data packets if the interface is open */ - if (unlikely(!priv->is_open)) { - IWL_DEBUG_DROP_LIMIT(priv, - "Dropping packet while interface is not open.\n"); - return; - } - - /* In case of HW accelerated crypto and bad decryption, drop */ - if (!priv->cfg->mod_params->sw_crypto && - iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) - return; - - skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); - if (!skb) { - IWL_ERR(priv, "alloc_skb failed\n"); - return; - } - - skb_reserve(skb, IWL_LINK_HDR_MAX); - skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); - - /* mac80211 currently doesn't support paged SKB. Convert it to - * linear SKB for management frame and data frame requires - * software decryption or software defragementation. */ - if (ieee80211_is_mgmt(fc) || - ieee80211_has_protected(fc) || - ieee80211_has_morefrags(fc) || - le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG || - (ieee80211_is_data_qos(fc) && - *ieee80211_get_qos_ctl(hdr) & - IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)) - ret = skb_linearize(skb); - else - ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? - 0 : -ENOMEM; - - if (ret) { - kfree_skb(skb); - goto out; - } - - /* - * XXX: We cannot touch the page and its virtual memory (hdr) after - * here. It might have already been freed by the above skb change. - */ - - iwl_update_stats(priv, false, fc, len); - memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); - - ieee80211_rx(priv->hw, skb); - out: - priv->alloc_rxb_page--; - rxb->page = NULL; -} - -/* Called for REPLY_RX (legacy ABG frames), or - * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ -void iwl_rx_reply_rx(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct ieee80211_hdr *header; - struct ieee80211_rx_status rx_status; - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_rx_phy_res *phy_res; - __le32 rx_pkt_status; - struct iwl4965_rx_mpdu_res_start *amsdu; - u32 len; - u32 ampdu_status; - u32 rate_n_flags; - - /** - * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. - * REPLY_RX: physical layer info is in this buffer - * REPLY_RX_MPDU_CMD: physical layer info was sent in separate - * command and cached in priv->last_phy_res - * - * Here we set up local variables depending on which command is - * received. - */ - if (pkt->hdr.cmd == REPLY_RX) { - phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; - header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) - + phy_res->cfg_phy_cnt); - - len = le16_to_cpu(phy_res->byte_count); - rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + - phy_res->cfg_phy_cnt + len); - ampdu_status = le32_to_cpu(rx_pkt_status); - } else { - if (!priv->last_phy_res[0]) { - IWL_ERR(priv, "MPDU frame without cached PHY data\n"); - return; - } - phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; - amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; - header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); - len = le16_to_cpu(amsdu->byte_count); - rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); - ampdu_status = iwl_translate_rx_status(priv, - le32_to_cpu(rx_pkt_status)); - } - - if ((unlikely(phy_res->cfg_phy_cnt > 20))) { - IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", - phy_res->cfg_phy_cnt); - return; - } - - if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || - !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { - IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", - le32_to_cpu(rx_pkt_status)); - return; - } - - /* This will be used in several places later */ - rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); - - /* rx_status carries information about the packet to mac80211 */ - rx_status.mactime = le64_to_cpu(phy_res->timestamp); - rx_status.freq = - ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel)); - rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? - IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; - rx_status.rate_idx = - iwl_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); - rx_status.flag = 0; - - /* TSF isn't reliable. In order to allow smooth user experience, - * this W/A doesn't propagate it to the mac80211 */ - /*rx_status.flag |= RX_FLAG_TSFT;*/ - - priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); - - /* Find max signal strength (dBm) among 3 antenna/receiver chains */ - rx_status.signal = iwl_calc_rssi(priv, phy_res); - - /* Meaningful noise values are available only from beacon statistics, - * which are gathered only when associated, and indicate noise - * only for the associated network channel ... - * Ignore these noise values while scanning (other channels) */ - if (iwl_is_associated(priv) && - !test_bit(STATUS_SCANNING, &priv->status)) { - rx_status.noise = priv->last_rx_noise; - } else { - rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; - } - - /* Reset beacon noise level if not associated. */ - if (!iwl_is_associated(priv)) - priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; - -#ifdef CONFIG_IWLWIFI_DEBUG - /* Set "1" to report good data frames in groups of 100 */ - if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) - iwl_dbg_report_frame(priv, phy_res, len, header, 1); -#endif - iwl_dbg_log_rx_data_frame(priv, len, header); - IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n", - rx_status.signal, rx_status.noise, - (unsigned long long)rx_status.mactime); - - /* - * "antenna number" - * - * It seems that the antenna field in the phy flags value - * is actually a bit field. This is undefined by radiotap, - * it wants an actual antenna number but I always get "7" - * for most legacy frames I receive indicating that the - * same frame was received on all three RX chains. - * - * I think this field should be removed in favor of a - * new 802.11n radiotap field "RX chains" that is defined - * as a bitmask. - */ - rx_status.antenna = - (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) - >> RX_RES_PHY_FLAGS_ANTENNA_POS; - - /* set the preamble flag if appropriate */ - if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) - rx_status.flag |= RX_FLAG_SHORTPRE; - - /* Set up the HT phy flags */ - if (rate_n_flags & RATE_MCS_HT_MSK) - rx_status.flag |= RX_FLAG_HT; - if (rate_n_flags & RATE_MCS_HT40_MSK) - rx_status.flag |= RX_FLAG_40MHZ; - if (rate_n_flags & RATE_MCS_SGI_MSK) - rx_status.flag |= RX_FLAG_SHORT_GI; - - iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, - rxb, &rx_status); -} -EXPORT_SYMBOL(iwl_rx_reply_rx); - -/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). - * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ -void iwl_rx_reply_rx_phy(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - priv->last_phy_res[0] = 1; - memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), - sizeof(struct iwl_rx_phy_res)); -} -EXPORT_SYMBOL(iwl_rx_reply_rx_phy); -- cgit v1.2.3 From 0b5af201b25334f7b9c991b2800693dd4cb4b5f7 Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Wed, 17 Mar 2010 16:16:12 -0700 Subject: iwlwifi: enable '6000 Series 2x2 AGN Gen2' adaptors Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-6000.c | 34 +++++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + 3 files changed, 36 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index f89e1c794388..7473518e7e0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -57,6 +57,7 @@ #define IWL6050_UCODE_API_MIN 4 #define IWL6000_FW_PRE "iwlwifi-6000-" +#define IWL6000_G2_FW_PRE "iwlwifi-6005-" #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" #define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api) @@ -362,6 +363,39 @@ static const struct iwl_ops iwl6050_ops = { /* * "i": Internal configuration, use internal Power Amplifier */ +struct iwl_cfg iwl6000i_g2_2agn_cfg = { + .name = "6000 Series 2x2 AGN Gen2", + .fw_name_pre = IWL6000_G2_FW_PRE, + .ucode_api_max = IWL6000_UCODE_API_MAX, + .ucode_api_min = IWL6000_UCODE_API_MIN, + .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, + .ops = &iwl6000_ops, + .eeprom_size = OTP_LOW_IMAGE_SIZE, + .eeprom_ver = EEPROM_6000_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, + .mod_params = &iwlagn_mod_params, + .valid_tx_ant = ANT_AB, + .valid_rx_ant = ANT_AB, + .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, + .pa_type = IWL_PA_INTERNAL, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, + .ht_greenfield_support = true, + .led_compensation = 51, + .use_rts_for_ht = true, /* use rts/cts protection */ + .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .supports_idle = true, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, +}; + struct iwl_cfg iwl6000i_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6200 AGN", .fw_name_pre = IWL6000_FW_PRE, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index bc08e9bdf9ac..3f0fd755a609 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3853,6 +3853,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)}, {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000i_g2_2agn_cfg)}, /* 6x50 WiFi/WiMax Series */ {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index e847e6197a3d..c2e97cd98f1b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -57,6 +57,7 @@ extern struct iwl_cfg iwl5100_abg_cfg; extern struct iwl_cfg iwl5150_agn_cfg; extern struct iwl_cfg iwl5150_abg_cfg; extern struct iwl_cfg iwl6000i_2agn_cfg; +extern struct iwl_cfg iwl6000i_g2_2agn_cfg; extern struct iwl_cfg iwl6000i_2abg_cfg; extern struct iwl_cfg iwl6000i_2bg_cfg; extern struct iwl_cfg iwl6000_3agn_cfg; -- cgit v1.2.3 From 510cb791ab32a6296e45ebc425a011551bed7bd1 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 16 Mar 2010 12:37:28 -0700 Subject: iwlwifi: remove non-exist extern functions and structures After re-structure the agn files layout and move all the agn shared functions out from iwl-5000.c, all those functions and data structures do not need to be declare "extern" from iwl-5000.c in iwl-dev.h. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-5000.c | 6 ++--- drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 39 ----------------------------- 3 files changed, 4 insertions(+), 42 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 6c09b2477b95..aaf7e51e6811 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -65,7 +65,7 @@ #define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api) /* NIC configuration for 5000 series */ -void iwl5000_nic_config(struct iwl_priv *priv) +static void iwl5000_nic_config(struct iwl_priv *priv) { unsigned long flags; u16 radio_cfg; @@ -164,7 +164,7 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; } -int iwl5000_hw_set_hw_params(struct iwl_priv *priv) +static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) { if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) @@ -266,7 +266,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) return iwl_send_cmd_sync(priv, &hcmd); } -struct iwl_lib_ops iwl5000_lib = { +static struct iwl_lib_ops iwl5000_lib = { .set_hw_params = iwl5000_hw_set_hw_params, .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index a0e3c1106138..6e331f502e14 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -35,6 +35,7 @@ #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-io.h" +#include "iwl-agn.h" static int iwlagn_send_rxon_assoc(struct iwl_priv *priv) { diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c2e97cd98f1b..07d865fd57ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -68,45 +68,6 @@ extern struct iwl_cfg iwl1000_bg_cfg; struct iwl_tx_queue; -/* shared structures from iwl-5000.c */ -extern struct iwl_mod_params iwl50_mod_params; -extern struct iwl_ucode_ops iwl5000_ucode; -extern struct iwl_lib_ops iwl5000_lib; -extern struct iwl_hcmd_ops iwl5000_hcmd; -extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils; - -/* shared functions from iwl-5000.c */ -extern u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len); -extern u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, - u8 *data); -extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, - __le32 *tx_flags); -extern int iwl5000_calc_rssi(struct iwl_priv *priv, - struct iwl_rx_phy_res *rx_resp); -extern void iwl5000_nic_config(struct iwl_priv *priv); -extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv); -extern const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, - size_t offset); -extern void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - u16 byte_cnt); -extern void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq); -extern int iwl5000_load_ucode(struct iwl_priv *priv); -extern void iwl5000_init_alive_start(struct iwl_priv *priv); -extern int iwl5000_alive_notify(struct iwl_priv *priv); -extern int iwl5000_hw_set_hw_params(struct iwl_priv *priv); -extern int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, - int tx_fifo, int sta_id, int tid, u16 ssn_idx); -extern int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo); -extern void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask); -extern void iwl5000_setup_deferred_work(struct iwl_priv *priv); -extern void iwl5000_rx_handler_setup(struct iwl_priv *priv); -extern int iwl5000_hw_valid_rtc_data_addr(u32 addr); -extern int iwl5000_send_tx_power(struct iwl_priv *priv); -extern void iwl5000_temperature(struct iwl_priv *priv); - /* CT-KILL constants */ #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ #define CT_KILL_THRESHOLD 114 /* in Celsius */ -- cgit v1.2.3 From 3d2b162e7e0a3e5093bccdf455f7c83f65c82db8 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 17 Mar 2010 18:57:13 -0700 Subject: iwlwifi: add missing email address information Add missing contact email address to iwl-5000.c Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index aaf7e51e6811..5ca451722d19 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -19,6 +19,7 @@ * file called LICENSE. * * Contact Information: + * Intel Linux Wireless * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * *****************************************************************************/ -- cgit v1.2.3 From ed1b6e99b5e64d2b9cdf764754a072c7fdc1c3c4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Mar 2010 09:58:27 -0700 Subject: iwlwifi: remove noise reporting We go to great lengths to calculate this value that is never used by mac80211. Additionally, it is now deprecated by mac80211 and is causing driver compilation to give warnings. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945.c | 36 +++++------------------------- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 20 ++--------------- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 -- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 -- drivers/net/wireless/iwlwifi/iwl-rx.c | 7 +++--- 5 files changed, 11 insertions(+), 56 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 21ae61dd3d51..6b7201551ca7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -622,7 +622,6 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); - int snr; u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg); u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff); u8 network_packet; @@ -662,43 +661,19 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, /* Convert 3945's rssi indicator to dBm */ rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET; - /* Set default noise value to -127 */ - if (priv->last_rx_noise == 0) - priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; - - /* 3945 provides noise info for OFDM frames only. - * sig_avg and noise_diff are measured by the 3945's digital signal - * processor (DSP), and indicate linear levels of signal level and - * distortion/noise within the packet preamble after - * automatic gain control (AGC). sig_avg should stay fairly - * constant if the radio's AGC is working well. - * Since these values are linear (not dB or dBm), linear - * signal-to-noise ratio (SNR) is (sig_avg / noise_diff). - * Convert linear SNR to dB SNR, then subtract that from rssi dBm - * to obtain noise level in dBm. - * Calculate rx_status.signal (quality indicator in %) based on SNR. */ - if (rx_stats_noise_diff) { - snr = rx_stats_sig_avg / rx_stats_noise_diff; - rx_status.noise = rx_status.signal - - iwl3945_calc_db_from_ratio(snr); - } else { - rx_status.noise = priv->last_rx_noise; - } - - - IWL_DEBUG_STATS(priv, "Rssi %d noise %d sig_avg %d noise_diff %d\n", - rx_status.signal, rx_status.noise, - rx_stats_sig_avg, rx_stats_noise_diff); + IWL_DEBUG_STATS(priv, "Rssi %d sig_avg %d noise_diff %d\n", + rx_status.signal, rx_stats_sig_avg, + rx_stats_noise_diff); header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); network_packet = iwl3945_is_network_packet(priv, header); - IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n", + IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Rate:%u\n", network_packet ? '*' : ' ', le16_to_cpu(rx_hdr->channel), rx_status.signal, rx_status.signal, - rx_status.noise, rx_status.rate_idx); + rx_status.rate_idx); /* Set "1" to report good data frames in groups of 100 */ iwl3945_dbg_report_frame(priv, pkt, header, 1); @@ -709,7 +684,6 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, le32_to_cpu(rx_end->beacon_timestamp); priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp); priv->_3945.last_rx_rssi = rx_status.signal; - priv->last_rx_noise = rx_status.noise; } iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 226862d3d5ac..e8e3118ec0ad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1071,30 +1071,14 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, /* Find max signal strength (dBm) among 3 antenna/receiver chains */ rx_status.signal = iwlagn_calc_rssi(priv, phy_res); - /* Meaningful noise values are available only from beacon statistics, - * which are gathered only when associated, and indicate noise - * only for the associated network channel ... - * Ignore these noise values while scanning (other channels) */ - if (iwl_is_associated(priv) && - !test_bit(STATUS_SCANNING, &priv->status)) { - rx_status.noise = priv->last_rx_noise; - } else { - rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; - } - - /* Reset beacon noise level if not associated. */ - if (!iwl_is_associated(priv)) - priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; - #ifdef CONFIG_IWLWIFI_DEBUG /* Set "1" to report good data frames in groups of 100 */ if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) iwlagn_dbg_report_frame(priv, phy_res, len, header, 1); #endif iwl_dbg_log_rx_data_frame(priv, len, header); - IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n", - rx_status.signal, rx_status.noise, - (unsigned long long)rx_status.mactime); + IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n", + rx_status.signal, (unsigned long long)rx_status.mactime); /* * "antenna number" diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 5155b1a027eb..bcae6a088106 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2940,8 +2940,6 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, desc += sprintf(buff+desc, "Bit Rate= %d Mb/s\n", iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); - desc += sprintf(buff+desc, "Noise Level= %d dBm\n", - priv->last_rx_noise); ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 07d865fd57ed..bff182ffeac9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1167,8 +1167,6 @@ struct iwl_priv { unsigned long status; - int last_rx_noise; /* From beacon statistics */ - /* counts mgmt, ctl, and data packets */ struct traffic_stats tx_stats; struct traffic_stats rx_stats; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 3a4313841fe7..1dff14a67b2c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -259,6 +259,7 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; int bcn_silence_c = le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; + int last_rx_noise; if (bcn_silence_a) { total_silence += bcn_silence_a; @@ -275,13 +276,13 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) /* Average among active antennas */ if (num_active_rx) - priv->last_rx_noise = (total_silence / num_active_rx) - 107; + last_rx_noise = (total_silence / num_active_rx) - 107; else - priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; + last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n", bcn_silence_a, bcn_silence_b, bcn_silence_c, - priv->last_rx_noise); + last_rx_noise); } #ifdef CONFIG_IWLWIFI_DEBUG -- cgit v1.2.3 From 2f3f7f9c23287c742af1d435b6fe8b9c9c7b7bd9 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 18 Mar 2010 10:56:32 -0700 Subject: iwlwifi: Generic approach to measure temperature In stead of checking for 4965 and do KELVIN_TO_CELSIUS conversation, add .cfg parameter for more generic approach. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-power.c | 8 ++++---- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index af48d07bb29d..1b5ced5159b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2258,6 +2258,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .monitor_recover_period = IWL_MONITORING_PERIOD, + .temperature_kelvin = true, }; /* Module firmware */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 22f84f3c3c40..e9b0411de845 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -305,6 +305,7 @@ struct iwl_cfg { s32 chain_noise_scale; /* timer period for monitor the driver queues */ u32 monitor_recover_period; + bool temperature_kelvin; }; /*************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 1a1a9f081cc7..e0581a771aab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -383,10 +383,10 @@ EXPORT_SYMBOL(iwl_ht_enabled); bool iwl_within_ct_kill_margin(struct iwl_priv *priv) { - s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */ + s32 temp = priv->temperature; /* degrees CELSIUS except specified */ bool within_margin = false; - if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) + if (priv->cfg->temperature_kelvin) temp = KELVIN_TO_CELSIUS(priv->temperature); if (!priv->thermal_throttle.advanced_tt) @@ -839,12 +839,12 @@ EXPORT_SYMBOL(iwl_tt_exit_ct_kill); static void iwl_bg_tt_work(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); - s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */ + s32 temp = priv->temperature; /* degrees CELSIUS except specified */ if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) + if (priv->cfg->temperature_kelvin) temp = KELVIN_TO_CELSIUS(priv->temperature); if (!priv->thermal_throttle.advanced_tt) -- cgit v1.2.3 From 6c69d121676761b2a85282df796af9c3f8c99b64 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 18 Mar 2010 15:37:49 -0700 Subject: iwlwifi: remove "\n" from module parameter description Remove the "\n" from following module parameter description: - enable wifi/bluetooth co-exist - led mode: 0=blinking, 1=On(RF On)/Off(RF Off), (default 0) to be consistence with the rest of iwlagn/iwlcore module parameters format. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-led.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 6fe785380824..d152198f144c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -65,7 +65,7 @@ MODULE_LICENSE("GPL"); */ static bool bt_coex_active = true; module_param(bt_coex_active, bool, S_IRUGO); -MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist\n"); +MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist"); static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index a6f9c918aabc..db5bfcb036ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -46,7 +46,7 @@ static int led_mode; module_param(led_mode, int, S_IRUGO); MODULE_PARM_DESC(led_mode, "led mode: 0=blinking, 1=On(RF On)/Off(RF Off), " - "(default 0)\n"); + "(default 0)"); static const struct { -- cgit v1.2.3 From 6e8cc38d5b05bb812f89a35bd9bf52405e67d0df Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 19 Mar 2010 10:36:09 -0700 Subject: iwlwifi: change spin_lock to spin_lock_irqsave Use spin_lock_irqsave() in interrupt handler to disable interrupts locally and provide the spinlock on SMP. This covers both interrupt and SMP concurrency. With this changes, also fix the sparse warning issues. Signed-off-by: Wey-Yi Guy Acked-by: Zhu Yi Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-ict.c | 14 ++++++++------ drivers/net/wireless/iwlwifi/iwl-core.c | 7 ++++--- 2 files changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c index 4c5395eae956..a273e373b7b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c @@ -141,13 +141,14 @@ static irqreturn_t iwl_isr(int irq, void *data) { struct iwl_priv *priv = data; u32 inta, inta_mask; + unsigned long flags; #ifdef CONFIG_IWLWIFI_DEBUG u32 inta_fh; #endif if (!priv) return IRQ_NONE; - spin_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, flags); /* Disable (but don't clear!) interrupts here to avoid * back-to-back ISRs and sporadic interrupts from our NIC. @@ -190,7 +191,7 @@ static irqreturn_t iwl_isr(int irq, void *data) iwl_enable_interrupts(priv); unplugged: - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_HANDLED; none: @@ -199,7 +200,7 @@ static irqreturn_t iwl_isr(int irq, void *data) if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) iwl_enable_interrupts(priv); - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_NONE; } @@ -216,6 +217,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) struct iwl_priv *priv = data; u32 inta, inta_mask; u32 val = 0; + unsigned long flags; if (!priv) return IRQ_NONE; @@ -226,7 +228,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) if (!priv->_agn.use_ict) return iwl_isr(irq, data); - spin_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, flags); /* Disable (but don't clear!) interrupts here to avoid * back-to-back ISRs and sporadic interrupts from our NIC. @@ -290,7 +292,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) iwl_enable_interrupts(priv); } - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_HANDLED; none: @@ -300,6 +302,6 @@ irqreturn_t iwl_isr_ict(int irq, void *data) if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) iwl_enable_interrupts(priv); - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_NONE; } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d152198f144c..9e4835240815 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1531,10 +1531,11 @@ irqreturn_t iwl_isr_legacy(int irq, void *data) struct iwl_priv *priv = data; u32 inta, inta_mask; u32 inta_fh; + unsigned long flags; if (!priv) return IRQ_NONE; - spin_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, flags); /* Disable (but don't clear!) interrupts here to avoid * back-to-back ISRs and sporadic interrupts from our NIC. @@ -1572,7 +1573,7 @@ irqreturn_t iwl_isr_legacy(int irq, void *data) tasklet_schedule(&priv->irq_tasklet); unplugged: - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_HANDLED; none: @@ -1580,7 +1581,7 @@ irqreturn_t iwl_isr_legacy(int irq, void *data) /* only Re-enable if diabled by irq */ if (test_bit(STATUS_INT_ENABLED, &priv->status)) iwl_enable_interrupts(priv); - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_NONE; } EXPORT_SYMBOL(iwl_isr_legacy); -- cgit v1.2.3 From d28667f871991e0eea983b398421b8db2c8bdf8c Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 19 Mar 2010 11:54:49 -0700 Subject: iwlwifi: avoid device type checking in generic code Avoid checking for specified device type to perform certain function, switch to .cfg approach as more generic and better implementation method. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-scan.c | 7 ++++--- 4 files changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 1b5ced5159b8..1808c976e504 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2259,6 +2259,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .monitor_recover_period = IWL_MONITORING_PERIOD, .temperature_kelvin = true, + .off_channel_workaround = true, }; /* Module firmware */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 9e4835240815..1b4408a31bff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -992,12 +992,12 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; /* copied from 'iwl_bg_request_scan()' */ - /* Force use of chains B and C (0x6) for Rx for 4965 - * Avoid A (0x1) because of its off-channel reception on A-band. + /* Force use of chains B and C (0x6) for Rx + * Avoid A (0x1) for the device has off-channel reception on A-band. * MIMO is not used here, but value is required */ if (iwl_is_monitor_mode(priv) && !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) && - ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)) { + priv->cfg->off_channel_workaround) { rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS; rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS; rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index e9b0411de845..9d7a68f07882 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -306,6 +306,7 @@ struct iwl_cfg { /* timer period for monitor the driver queues */ u32 monitor_recover_period; bool temperature_kelvin; + bool off_channel_workaround; }; /*************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 1544d751a42e..5ecfc7f6ff43 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -830,10 +830,11 @@ static void iwl_bg_request_scan(struct work_struct *data) */ scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; - /* Force use of chains B and C (0x6) for scan Rx for 4965 - * Avoid A (0x1) because of its off-channel reception on A-band. + /* Force use of chains B and C (0x6) for scan Rx + * Avoid A (0x1) for the device has off-channel reception + * on A-band. */ - if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) + if (priv->cfg->off_channel_workaround) rx_ant = ANT_BC; } else { IWL_WARN(priv, "Invalid scan band count\n"); -- cgit v1.2.3 From 4a89852c3533c0190cbe6b04b8b5d7bf4f9beea9 Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Wed, 24 Mar 2010 19:46:33 +0100 Subject: wireless/prism54: remove trailing space in messages Signed-off-by: Frans Pop Cc: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/p54/txrx.c | 2 +- drivers/net/wireless/prism54/islpci_dev.c | 16 ++++++++-------- drivers/net/wireless/prism54/islpci_eth.c | 8 ++++---- drivers/net/wireless/prism54/islpci_mgt.c | 8 ++++---- drivers/net/wireless/prism54/oid_mgt.c | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 66057999a93c..2ceff5480355 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -38,7 +38,7 @@ static void p54_dump_tx_queue(struct p54_common *priv) u32 largest_hole = 0, free; spin_lock_irqsave(&priv->tx_queue.lock, flags); - printk(KERN_DEBUG "%s: / --- tx queue dump (%d entries) --- \n", + printk(KERN_DEBUG "%s: / --- tx queue dump (%d entries) ---\n", wiphy_name(priv->hw->wiphy), skb_queue_len(&priv->tx_queue)); prev_addr = priv->rx_start; diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index a3ba3539db02..7c82e432cca7 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -227,14 +227,14 @@ islpci_interrupt(int irq, void *config) #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, - "IRQ: Identification register 0x%p 0x%x \n", device, reg); + "IRQ: Identification register 0x%p 0x%x\n", device, reg); #endif /* check for each bit in the register separately */ if (reg & ISL38XX_INT_IDENT_UPDATE) { #if VERBOSE > SHOW_ERROR_MESSAGES /* Queue has been updated */ - DEBUG(SHOW_TRACING, "IRQ: Update flag \n"); + DEBUG(SHOW_TRACING, "IRQ: Update flag\n"); DEBUG(SHOW_QUEUE_INDEXES, "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n", @@ -300,7 +300,7 @@ islpci_interrupt(int irq, void *config) ISL38XX_CB_RX_DATA_LQ) != 0) { #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, - "Received frame in Data Low Queue \n"); + "Received frame in Data Low Queue\n"); #endif islpci_eth_receive(priv); } @@ -325,7 +325,7 @@ islpci_interrupt(int irq, void *config) /* Device has been initialized */ #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, - "IRQ: Init flag, device initialized \n"); + "IRQ: Init flag, device initialized\n"); #endif wake_up(&priv->reset_done); } @@ -333,7 +333,7 @@ islpci_interrupt(int irq, void *config) if (reg & ISL38XX_INT_IDENT_SLEEP) { /* Device intends to move to powersave state */ #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "IRQ: Sleep flag \n"); + DEBUG(SHOW_TRACING, "IRQ: Sleep flag\n"); #endif isl38xx_handle_sleep_request(priv->control_block, &powerstate, @@ -343,7 +343,7 @@ islpci_interrupt(int irq, void *config) if (reg & ISL38XX_INT_IDENT_WAKEUP) { /* Device has been woken up to active state */ #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "IRQ: Wakeup flag \n"); + DEBUG(SHOW_TRACING, "IRQ: Wakeup flag\n"); #endif isl38xx_handle_wakeup(priv->control_block, @@ -634,7 +634,7 @@ islpci_alloc_memory(islpci_private *priv) ioremap(pci_resource_start(priv->pdev, 0), ISL38XX_PCI_MEM_SIZE))) { /* error in remapping the PCI device memory address range */ - printk(KERN_ERR "PCI memory remapping failed \n"); + printk(KERN_ERR "PCI memory remapping failed\n"); return -1; } @@ -901,7 +901,7 @@ islpci_setup(struct pci_dev *pdev) if (register_netdev(ndev)) { DEBUG(SHOW_ERROR_MESSAGES, - "ERROR: register_netdev() failed \n"); + "ERROR: register_netdev() failed\n"); goto do_islpci_free_memory; } diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 872b64783e78..af9e7fbd7640 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -89,7 +89,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) u32 curr_frag; #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit \n"); + DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit\n"); #endif /* lock the driver code */ @@ -140,7 +140,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) } #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "memmove %p %p %i \n", skb->data, + DEBUG(SHOW_TRACING, "memmove %p %p %i\n", skb->data, src, skb->len); #endif } else { @@ -319,7 +319,7 @@ islpci_eth_receive(islpci_private *priv) int discard = 0; #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_receive \n"); + DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_receive\n"); #endif /* the device has written an Ethernet frame in the data area @@ -431,7 +431,7 @@ islpci_eth_receive(islpci_private *priv) skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2); if (unlikely(skb == NULL)) { /* error allocating an sk_buff structure elements */ - DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb \n"); + DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb\n"); break; } skb_reserve(skb, (4 - (long) skb->data) & 0x03); diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c index 69d2f882fd06..89b0278eb7e8 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.c +++ b/drivers/net/wireless/prism54/islpci_mgt.c @@ -113,7 +113,7 @@ islpci_mgmt_rx_fill(struct net_device *ndev) u32 curr = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ]); #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgmt_rx_fill \n"); + DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgmt_rx_fill\n"); #endif while (curr - priv->index_mgmt_rx < ISL38XX_CB_MGMT_QSIZE) { @@ -211,7 +211,7 @@ islpci_mgt_transmit(struct net_device *ndev, int operation, unsigned long oid, { pimfor_header_t *h = buf.mem; DEBUG(SHOW_PIMFOR_FRAMES, - "PIMFOR: op %i, oid 0x%08lx, device %i, flags 0x%x length 0x%x \n", + "PIMFOR: op %i, oid 0x%08lx, device %i, flags 0x%x length 0x%x\n", h->operation, oid, h->device_id, h->flags, length); /* display the buffer contents for debugging */ @@ -279,7 +279,7 @@ islpci_mgt_receive(struct net_device *ndev) u32 curr_frag; #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive \n"); + DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive\n"); #endif /* Only once per interrupt, determine fragment range to @@ -338,7 +338,7 @@ islpci_mgt_receive(struct net_device *ndev) #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_PIMFOR_FRAMES, - "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x \n", + "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x\n", header->operation, header->oid, header->device_id, header->flags, header->length); diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c index 1187e6112a64..07df70a10071 100644 --- a/drivers/net/wireless/prism54/oid_mgt.c +++ b/drivers/net/wireless/prism54/oid_mgt.c @@ -819,7 +819,7 @@ mgt_response_to_str(enum oid_num_t n, union oid_res_t *r, char *str) k = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", list->nr); for (i = 0; i < list->nr; i++) k += snprintf(str + k, PRIV_STR_SIZE - k, - "bss[%u] : \nage=%u\nchannel=%u\n" + "bss[%u] :\nage=%u\nchannel=%u\n" "capinfo=0x%X\nrates=0x%X\n" "basic_rates=0x%X\n", i, list->bsslist[i].age, -- cgit v1.2.3 From cb01b09c6914ab04dc836941dc92a1dd42714e19 Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Wed, 24 Mar 2010 19:46:34 +0100 Subject: wireless/raylink: remove trailing space in messages Signed-off-by: Frans Pop Cc: Corey Thomas Signed-off-by: John W. Linville --- drivers/net/wireless/ray_cs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 4f5bdb528ef7..f1e916a31668 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -556,7 +556,7 @@ static int ray_init(struct net_device *dev) local->fw_ver = local->startup_res.firmware_version[0]; local->fw_bld = local->startup_res.firmware_version[1]; local->fw_var = local->startup_res.firmware_version[2]; - dev_dbg(&link->dev, "ray_init firmware version %d.%d \n", local->fw_ver, + dev_dbg(&link->dev, "ray_init firmware version %d.%d\n", local->fw_ver, local->fw_bld); local->tib_length = 0x20; @@ -2234,7 +2234,7 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + FCS_LEN)) { pr_debug( - "ray_cs invalid packet length %d received \n", + "ray_cs invalid packet length %d received\n", rx_len); return; } @@ -2245,7 +2245,7 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + FCS_LEN)) { pr_debug( - "ray_cs invalid packet length %d received \n", + "ray_cs invalid packet length %d received\n", rx_len); return; } @@ -2753,11 +2753,11 @@ static int ray_cs_proc_show(struct seq_file *m, void *v) seq_printf(m, "Hop dwell = %d Kus\n", pfh->dwell_time[0] + 256 * pfh->dwell_time[1]); - seq_printf(m, "Hop set = %d \n", + seq_printf(m, "Hop set = %d\n", pfh->hop_set); - seq_printf(m, "Hop pattern = %d \n", + seq_printf(m, "Hop pattern = %d\n", pfh->hop_pattern); - seq_printf(m, "Hop index = %d \n", + seq_printf(m, "Hop index = %d\n", pfh->hop_index); p += p[1] + 2; } else { -- cgit v1.2.3 From 0e354fd01e4513cea25d66e9c6d9e76f7228accc Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Wed, 24 Mar 2010 19:46:35 +0100 Subject: wireless/libertas: remove trailing space in debugfs header Signed-off-by: Frans Pop Cc: libertas-dev@lists.infradead.org Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 587b0cb0088d..9c3c2f82f033 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -74,7 +74,7 @@ static ssize_t lbs_getscantable(struct file *file, char __user *userbuf, return -ENOMEM; pos += snprintf(buf+pos, len-pos, - "# | ch | rssi | bssid | cap | Qual | SSID \n"); + "# | ch | rssi | bssid | cap | Qual | SSID\n"); mutex_lock(&priv->lock); list_for_each_entry (iter_bss, &priv->network_list, list) { -- cgit v1.2.3 From 1063b176c072b936c43d0e6270168b19881ecb72 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Thu, 25 Mar 2010 14:49:03 +0900 Subject: ath5k: remove static calibration interval variable Remove static variable ath5k_calinterval which was used as a constant. Use a #define instead. Also we don't need ah_cal_intval. Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 4 +--- drivers/net/wireless/ath/ath5k/base.c | 4 ---- drivers/net/wireless/ath/ath5k/phy.c | 2 +- 3 files changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 1d7491c85460..a3019ee4f2fa 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -202,6 +202,7 @@ #define AR5K_TUNE_MAX_TXPOWER 63 #define AR5K_TUNE_DEFAULT_TXPOWER 25 #define AR5K_TUNE_TPC_TXPOWER false +#define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL 10000 /* 10 sec */ #define AR5K_INIT_CARR_SENSE_EN 1 @@ -1101,9 +1102,6 @@ struct ath5k_hw { /* Calibration timestamp */ unsigned long ah_cal_tstamp; - /* Calibration interval (secs) */ - u8 ah_cal_intval; - /* Software interrupt mask */ u8 ah_swi_mask; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index b142a78ed1e5..39d580017259 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -59,7 +59,6 @@ #include "reg.h" #include "debug.h" -static u8 ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -2497,9 +2496,6 @@ ath5k_init(struct ath5k_softc *sc) */ ath5k_stop_locked(sc); - /* Set PHY calibration interval */ - ah->ah_cal_intval = ath5k_calinterval; - /* * The basic interface to setting the hardware in a good * state is ``reset''. On return the hardware is known to diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 384347b0c9f0..01b3f29ec13d 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1108,7 +1108,7 @@ ath5k_hw_calibration_poll(struct ath5k_hw *ah) /* Calibration interval in jiffies */ unsigned long cal_intval; - cal_intval = msecs_to_jiffies(ah->ah_cal_intval * 1000); + cal_intval = msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); /* Initialize timestamp if needed */ if (!ah->ah_cal_tstamp) -- cgit v1.2.3 From e65e1d7713da89d98f01c3f4267b2c9ecb03c16f Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Thu, 25 Mar 2010 14:49:09 +0900 Subject: ath5k: remove the use of SWI interrupt We don't need to generate a software interrupt (SWI) just to schedule a tasklet - we can just schedule the tasklet directly. Rename constants, names, etc to reflect the fact that we don't use SWI any more. Also move the flag handling into the tasklet and prepare it to behave correctly when there are multiple flags present. Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 12 ++++++------ drivers/net/wireless/ath/ath5k/base.c | 11 +++-------- drivers/net/wireless/ath/ath5k/phy.c | 3 +-- 3 files changed, 10 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index a3019ee4f2fa..d84ccde11171 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -890,10 +890,10 @@ enum ath5k_int { AR5K_INT_NOCARD = 0xffffffff }; -/* Software interrupts used for calibration */ -enum ath5k_software_interrupt { - AR5K_SWI_FULL_CALIBRATION = 0x01, - AR5K_SWI_SHORT_CALIBRATION = 0x02, +/* mask which calibration is active at the moment */ +enum ath5k_calibration_mask { + AR5K_CALIBRATION_FULL = 0x01, + AR5K_CALIBRATION_SHORT = 0x02, }; /* @@ -1102,8 +1102,8 @@ struct ath5k_hw { /* Calibration timestamp */ unsigned long ah_cal_tstamp; - /* Software interrupt mask */ - u8 ah_swi_mask; + /* Calibration mask */ + u8 ah_cal_mask; /* * Function pointers diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 39d580017259..539a6d5415fd 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2507,7 +2507,7 @@ ath5k_init(struct ath5k_softc *sc) sc->curband = &sc->sbands[sc->curchan->band]; sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | - AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_SWI; + AR5K_INT_FATAL | AR5K_INT_GLOBAL; ret = ath5k_reset(sc, NULL); if (ret) goto done; @@ -2673,9 +2673,6 @@ ath5k_intr(int irq, void *dev_id) if (status & AR5K_INT_BMISS) { /* TODO */ } - if (status & AR5K_INT_SWI) { - tasklet_schedule(&sc->calib); - } if (status & AR5K_INT_MIB) { /* * These stats are also used for ANI i think @@ -2716,8 +2713,7 @@ ath5k_tasklet_calibrate(unsigned long data) struct ath5k_hw *ah = sc->ah; /* Only full calibration for now */ - if (ah->ah_swi_mask != AR5K_SWI_FULL_CALIBRATION) - return; + ah->ah_cal_mask |= AR5K_CALIBRATION_FULL; /* Stop queues so that calibration * doesn't interfere with tx */ @@ -2740,11 +2736,10 @@ ath5k_tasklet_calibrate(unsigned long data) ieee80211_frequency_to_channel( sc->curchan->center_freq)); - ah->ah_swi_mask = 0; - /* Wake queues */ ieee80211_wake_queues(sc->hw); + ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; } diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 01b3f29ec13d..075873f98428 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1119,8 +1119,7 @@ ath5k_hw_calibration_poll(struct ath5k_hw *ah) * interrupt (bit gets auto-cleared) */ if (time_is_before_eq_jiffies(ah->ah_cal_tstamp + cal_intval)) { ah->ah_cal_tstamp = jiffies; - ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION; - AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); + tasklet_schedule(&ah->ah_sc->calib); } } -- cgit v1.2.3 From a9167f96428b832bf94c89908e000e16c4eb7d5b Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Thu, 25 Mar 2010 14:49:14 +0900 Subject: ath5k: optimize ath5k_hw_calibration_poll Optimize ath5k_hw_calibration_poll() since it is called on every singe interrupt. Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 2 +- drivers/net/wireless/ath/ath5k/phy.c | 20 ++++++-------------- 2 files changed, 7 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index d84ccde11171..3f56d9ee21de 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1100,7 +1100,7 @@ struct ath5k_hw { s32 ah_noise_floor; /* Calibration timestamp */ - unsigned long ah_cal_tstamp; + unsigned long ah_cal_next_full; /* Calibration mask */ u8 ah_cal_mask; diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 075873f98428..69053bfebbb9 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1105,22 +1105,14 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) void ath5k_hw_calibration_poll(struct ath5k_hw *ah) { - /* Calibration interval in jiffies */ - unsigned long cal_intval; - - cal_intval = msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); - - /* Initialize timestamp if needed */ - if (!ah->ah_cal_tstamp) - ah->ah_cal_tstamp = jiffies; - - /* For now we always do full calibration - * Mark software interrupt mask and fire software - * interrupt (bit gets auto-cleared) */ - if (time_is_before_eq_jiffies(ah->ah_cal_tstamp + cal_intval)) { - ah->ah_cal_tstamp = jiffies; + if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { + ah->ah_cal_next_full = jiffies + + msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); tasklet_schedule(&ah->ah_sc->calib); } + /* we could use SWI to generate enough interrupts to meet our + * calibration interval requirements, if necessary: + * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ } static int sign_extend(int val, const int nbits) -- cgit v1.2.3 From 6a8a3f6b2ac02fb8542f2b36b0ecd9c48f7d9a7e Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Thu, 25 Mar 2010 14:49:19 +0900 Subject: ath5k: move ath5k_hw_calibration_poll to base.c It's not a phy related funtion; It has more to do with the interrupt handler and tasklet scheduling, so it belongs to base.c. Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 1 - drivers/net/wireless/ath/ath5k/base.c | 15 ++++++++++++++- drivers/net/wireless/ath/ath5k/phy.c | 13 ------------- 3 files changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 3f56d9ee21de..6334294f5f13 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1254,7 +1254,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); -void ath5k_hw_calibration_poll(struct ath5k_hw *ah); /* Spur mitigation */ bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, struct ieee80211_channel *channel); diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 539a6d5415fd..f60d84f9c55f 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2625,6 +2625,19 @@ ath5k_stop_hw(struct ath5k_softc *sc) return ret; } +static void +ath5k_intr_calibration_poll(struct ath5k_hw *ah) +{ + if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { + ah->ah_cal_next_full = jiffies + + msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); + tasklet_schedule(&ah->ah_sc->calib); + } + /* we could use SWI to generate enough interrupts to meet our + * calibration interval requirements, if necessary: + * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ +} + static irqreturn_t ath5k_intr(int irq, void *dev_id) { @@ -2689,7 +2702,7 @@ ath5k_intr(int irq, void *dev_id) if (unlikely(!counter)) ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); - ath5k_hw_calibration_poll(ah); + ath5k_intr_calibration_poll(ah); return IRQ_HANDLED; } diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 69053bfebbb9..cb569dbffa63 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1102,19 +1102,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) PHY calibration \*****************/ -void -ath5k_hw_calibration_poll(struct ath5k_hw *ah) -{ - if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { - ah->ah_cal_next_full = jiffies + - msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); - tasklet_schedule(&ah->ah_sc->calib); - } - /* we could use SWI to generate enough interrupts to meet our - * calibration interval requirements, if necessary: - * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ -} - static int sign_extend(int val, const int nbits) { int order = BIT(nbits-1); -- cgit v1.2.3 From b4ea449df90684035985a77763fd1d2ff0eb9dad Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Thu, 25 Mar 2010 14:49:25 +0900 Subject: ath5k: keep beacon RSSI average Keep an exponentially weighted moving average of the beacon RSSI in our BSS. It will be used by the ANI implementation. The averaging algorithm is copied from rt2x00, Thanks :) Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 35 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath5k/base.c | 21 ++++++++++++++++++++ 2 files changed, 56 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 6334294f5f13..cefd28d5deee 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -992,6 +992,15 @@ struct ath5k_nfcal_hist s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */ }; +/** + * struct avg_val - Helper structure for average calculation + * @avg: contains the actual average value + * @avg_weight: is used internally during calculation to prevent rounding errors + */ +struct ath5k_avg_val { + int avg; + int avg_weight; +}; /***************************************\ HARDWARE ABSTRACTION LAYER STRUCTURE @@ -1096,6 +1105,9 @@ struct ath5k_hw { struct ath5k_nfcal_hist ah_nfcal_hist; + /* average beacon RSSI in our BSS (used by ANI) */ + struct ath5k_avg_val ah_beacon_rssi_avg; + /* noise floor from last periodic calibration */ s32 ah_noise_floor; @@ -1305,4 +1317,27 @@ static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) return retval; } +#define AVG_SAMPLES 8 +#define AVG_FACTOR 1000 + +/** + * ath5k_moving_average - Exponentially weighted moving average + * @avg: average structure + * @val: current value + * + * This implementation make use of a struct ath5k_avg_val to prevent rounding + * errors. + */ +static inline struct ath5k_avg_val +ath5k_moving_average(const struct ath5k_avg_val avg, const int val) +{ + struct ath5k_avg_val new; + new.avg_weight = avg.avg_weight ? + (((avg.avg_weight * ((AVG_SAMPLES) - 1)) + + (val * (AVG_FACTOR))) / (AVG_SAMPLES)) : + (val * (AVG_FACTOR)); + new.avg = new.avg_weight / (AVG_FACTOR); + return new; +} + #endif diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index f60d84f9c55f..ba2fad23a7a5 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1803,6 +1803,25 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, } } +static void +ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi) +{ + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; + struct ath5k_hw *ah = sc->ah; + struct ath_common *common = ath5k_hw_common(ah); + + /* only beacons from our BSSID */ + if (!ieee80211_is_beacon(mgmt->frame_control) || + memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0) + return; + + ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg, + rssi); + + /* in IBSS mode we should keep RSSI statistics per neighbour */ + /* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */ +} + /* * Compute padding position. skb must contains an IEEE 802.11 frame */ @@ -2022,6 +2041,8 @@ accept: ath5k_debug_dump_skb(sc, skb, "RX ", 0); + ath5k_update_beacon_rssi(sc, skb, rs.rs_rssi); + /* check beacons in IBSS mode */ if (sc->opmode == NL80211_IFTYPE_ADHOC) ath5k_check_ibss_tsf(sc, skb, rxs); -- cgit v1.2.3 From 9d332c82b4cf2e4538450e4af40f073cc5e599ec Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Thu, 25 Mar 2010 14:49:31 +0900 Subject: ath5k: initialize default noise floor Initialize noise floor variable with a default of -95. This was used uninitialized in the signal strength (RSSI -> dBm) conversion until the first noise floor calibration was completed. Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/attach.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index dd4099a2ff15..f80d3d52c536 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -123,6 +123,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; ah->ah_software_retry = false; ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; + ah->ah_noise_floor = -95; /* until first NF calibration is run */ /* * Find the mac version -- cgit v1.2.3 From 495391d715a310a7cbf622850e372d40ac86ef6e Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Thu, 25 Mar 2010 14:49:36 +0900 Subject: ath5k: simplify MIB counters Let's keep MIB counter statistics in our own statistics structure and only convert it to ieee80211_low_level_stats when needed by mac80211. Also we don't need to read profile count registers in the MIB interrupt (they don't trigger MIB interrupts). Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 3 +-- drivers/net/wireless/ath/ath5k/base.c | 16 ++++++-------- drivers/net/wireless/ath/ath5k/base.h | 13 ++++++++++-- drivers/net/wireless/ath/ath5k/pcu.c | 39 ++++++++++++---------------------- 4 files changed, 32 insertions(+), 39 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index cefd28d5deee..ec626905655b 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1173,8 +1173,7 @@ int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask); -void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, - struct ieee80211_low_level_stats *stats); +void ath5k_hw_update_mib_counters(struct ath5k_hw *ah); /* EEPROM access functions */ int ath5k_eeprom_init(struct ath5k_hw *ah); diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index ba2fad23a7a5..ea33b993b28e 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2114,7 +2114,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) info->status.rates[ts.ts_final_idx].count++; if (unlikely(ts.ts_status)) { - sc->ll_stats.dot11ACKFailureCount++; + sc->stats.ack_fail++; if (ts.ts_status & AR5K_TXERR_FILT) { info->flags |= IEEE80211_TX_STAT_TX_FILTERED; sc->stats.txerr_filt++; @@ -2708,11 +2708,7 @@ ath5k_intr(int irq, void *dev_id) /* TODO */ } if (status & AR5K_INT_MIB) { - /* - * These stats are also used for ANI i think - * so how about updating them more often ? - */ - ath5k_hw_update_mib_counters(ah, &sc->ll_stats); + ath5k_hw_update_mib_counters(ah); } if (status & AR5K_INT_GPIO) tasklet_schedule(&sc->rf_kill.toggleq); @@ -3234,12 +3230,14 @@ ath5k_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; /* Force update */ - ath5k_hw_update_mib_counters(ah, &sc->ll_stats); + ath5k_hw_update_mib_counters(sc->ah); - memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats)); + stats->dot11ACKFailureCount = sc->stats.ack_fail; + stats->dot11RTSFailureCount = sc->stats.rts_fail; + stats->dot11RTSSuccessCount = sc->stats.rts_ok; + stats->dot11FCSErrorCount = sc->stats.fcs_error; return 0; } diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 33f1d8b87ee1..fe5dae517545 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -105,10 +105,13 @@ struct ath5k_rfkill { struct tasklet_struct toggleq; }; -/* statistics (only used for debugging now) */ +/* statistics */ struct ath5k_statistics { + /* antenna use */ unsigned int antenna_rx[5]; /* frames count per antenna RX */ unsigned int antenna_tx[5]; /* frames count per antenna TX */ + + /* frame errors */ unsigned int rx_all_count; /* all RX frames, including errors */ unsigned int tx_all_count; /* all TX frames, including errors */ unsigned int rxerr_crc; @@ -121,6 +124,13 @@ struct ath5k_statistics { unsigned int txerr_retry; unsigned int txerr_fifo; unsigned int txerr_filt; + + /* MIB counters */ + unsigned int ack_fail; + unsigned int rts_fail; + unsigned int rts_ok; + unsigned int fcs_error; + unsigned int beacons; }; #if CHAN_DEBUG @@ -135,7 +145,6 @@ struct ath5k_softc { struct pci_dev *pdev; /* for dma mapping */ void __iomem *iobase; /* address of the device */ struct mutex lock; /* dev-level lock */ - struct ieee80211_low_level_stats ll_stats; struct ieee80211_hw *hw; /* IEEE 802.11 common */ struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; struct ieee80211_channel channels[ATH_CHAN_MAX]; diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 1b9fcb842167..c7c1fe023724 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -113,39 +113,26 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) } /** - * ath5k_hw_update - Update mib counters (mac layer statistics) + * ath5k_hw_update - Update MIB counters (mac layer statistics) * * @ah: The &struct ath5k_hw - * @stats: The &struct ieee80211_low_level_stats we use to track - * statistics on the driver * - * Reads MIB counters from PCU and updates sw statistics. Must be - * called after a MIB interrupt. + * Reads MIB counters from PCU and updates sw statistics. Is called after a + * MIB interrupt, because one of these counters might have reached their maximum + * and triggered the MIB interrupt, to let us read and clear the counter. + * + * Is called in interrupt context! */ -void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, - struct ieee80211_low_level_stats *stats) +void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) { - ATH5K_TRACE(ah->ah_sc); + struct ath5k_statistics *stats = &ah->ah_sc->stats; /* Read-And-Clear */ - stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); - stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); - stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); - stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); - - /* XXX: Should we use this to track beacon count ? - * -we read it anyway to clear the register */ - ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); - - /* Reset profile count registers on 5212*/ - if (ah->ah_version == AR5K_AR5212) { - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); - } - - /* TODO: Handle ANI stats */ + stats->ack_fail += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); + stats->rts_fail += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); + stats->rts_ok += ath5k_hw_reg_read(ah, AR5K_RTS_OK); + stats->fcs_error += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); + stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); } /** -- cgit v1.2.3 From da35111ad970081bdf6e848d1861c7d16e71079b Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Thu, 25 Mar 2010 14:49:42 +0900 Subject: ath5k: update phy errors codes Update PHY error codes from the HAL, and keep them in statistics for debugging via the 'frameerrors' file. This will also be used by ANI. Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 2 ++ drivers/net/wireless/ath/ath5k/base.h | 1 + drivers/net/wireless/ath/ath5k/debug.c | 8 ++++++++ drivers/net/wireless/ath/ath5k/desc.h | 35 +++++++++++++++++++++++++--------- 4 files changed, 37 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index ea33b993b28e..a1c0dcb4926e 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1940,6 +1940,8 @@ ath5k_tasklet_rx(unsigned long data) sc->stats.rxerr_fifo++; if (rs.rs_status & AR5K_RXERR_PHY) { sc->stats.rxerr_phy++; + if (rs.rs_phyerr > 0 && rs.rs_phyerr < 32) + sc->stats.rxerr_phy_code[rs.rs_phyerr]++; goto next; } if (rs.rs_status & AR5K_RXERR_DECRYPT) { diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index fe5dae517545..a572a4844800 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -116,6 +116,7 @@ struct ath5k_statistics { unsigned int tx_all_count; /* all TX frames, including errors */ unsigned int rxerr_crc; unsigned int rxerr_phy; + unsigned int rxerr_phy_code[32]; unsigned int rxerr_fifo; unsigned int rxerr_decrypt; unsigned int rxerr_mic; diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index bccd4a78027e..90247dc74198 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -474,6 +474,7 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, struct ath5k_statistics *st = &sc->stats; char buf[700]; unsigned int len = 0; + int i; len += snprintf(buf+len, sizeof(buf)-len, "RX\n---------------------\n"); @@ -485,6 +486,13 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, st->rxerr_phy, st->rx_all_count > 0 ? st->rxerr_phy*100/st->rx_all_count : 0); + for (i = 0; i < 32; i++) { + if (st->rxerr_phy_code[i]) + len += snprintf(buf+len, sizeof(buf)-len, + " phy_err[%d]\t%d\n", + i, st->rxerr_phy_code[i]); + } + len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", st->rxerr_fifo, st->rx_all_count > 0 ? diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h index 56158c804e3e..64538fbe4167 100644 --- a/drivers/net/wireless/ath/ath5k/desc.h +++ b/drivers/net/wireless/ath/ath5k/desc.h @@ -112,15 +112,32 @@ struct ath5k_hw_rx_error { #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 -/* PHY Error codes */ -#define AR5K_DESC_RX_PHY_ERROR_NONE 0x00 -#define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20 -#define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40 -#define AR5K_DESC_RX_PHY_ERROR_RATE 0x60 -#define AR5K_DESC_RX_PHY_ERROR_LENGTH 0x80 -#define AR5K_DESC_RX_PHY_ERROR_64QAM 0xa0 -#define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0 -#define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0 +/** + * enum ath5k_phy_error_code - PHY Error codes + */ +enum ath5k_phy_error_code { + AR5K_RX_PHY_ERROR_UNDERRUN = 0, /* Transmit underrun */ + AR5K_RX_PHY_ERROR_TIMING = 1, /* Timing error */ + AR5K_RX_PHY_ERROR_PARITY = 2, /* Illegal parity */ + AR5K_RX_PHY_ERROR_RATE = 3, /* Illegal rate */ + AR5K_RX_PHY_ERROR_LENGTH = 4, /* Illegal length */ + AR5K_RX_PHY_ERROR_RADAR = 5, /* Radar detect */ + AR5K_RX_PHY_ERROR_SERVICE = 6, /* Illegal service */ + AR5K_RX_PHY_ERROR_TOR = 7, /* Transmit override receive */ + /* these are specific to the 5212 */ + AR5K_RX_PHY_ERROR_OFDM_TIMING = 17, + AR5K_RX_PHY_ERROR_OFDM_SIGNAL_PARITY = 18, + AR5K_RX_PHY_ERROR_OFDM_RATE_ILLEGAL = 19, + AR5K_RX_PHY_ERROR_OFDM_LENGTH_ILLEGAL = 20, + AR5K_RX_PHY_ERROR_OFDM_POWER_DROP = 21, + AR5K_RX_PHY_ERROR_OFDM_SERVICE = 22, + AR5K_RX_PHY_ERROR_OFDM_RESTART = 23, + AR5K_RX_PHY_ERROR_CCK_TIMING = 25, + AR5K_RX_PHY_ERROR_CCK_HEADER_CRC = 26, + AR5K_RX_PHY_ERROR_CCK_RATE_ILLEGAL = 27, + AR5K_RX_PHY_ERROR_CCK_SERVICE = 30, + AR5K_RX_PHY_ERROR_CCK_RESTART = 31, +}; /* * 5210/5211 hardware 2-word TX control descriptor -- cgit v1.2.3 From a8c944f8a00dcc4ac6900efcddab1a0cf300c791 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Thu, 25 Mar 2010 14:49:47 +0900 Subject: ath5k: add capability flag for phyerror counters Chipsets since revision AR5213A (0x59) have hardware counters for PHY errors which we can read directly from the registers. Older hardware has to use the RX descriptor status to get a count of PHY errors. This will be used in several places in the ANI implementation, so a flag is useful. Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 2 ++ drivers/net/wireless/ath/ath5k/caps.c | 6 ++++++ 2 files changed, 8 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index ec626905655b..f578c1ed7f88 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -982,6 +982,8 @@ struct ath5k_capabilities { struct { u8 q_tx_num; } cap_queues; + + bool cap_has_phyerr_counters; }; /* size of noise floor history (keep it a power of two) */ diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index e618e71b1ce6..74f007126f41 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c @@ -109,6 +109,12 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) else ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; + /* newer hardware has PHY error counters */ + if (ah->ah_mac_srev >= AR5K_SREV_AR5213A) + ah->ah_capabilities.cap_has_phyerr_counters = true; + else + ah->ah_capabilities.cap_has_phyerr_counters = false; + return 0; } -- cgit v1.2.3 From 7fdd50d07fed198b2c6ccdca96ab5537014597d8 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 26 Mar 2010 12:53:10 +0200 Subject: wl1271: fix wl1271_spi driver name When forward porting some patches to upstream, there was a mistake and the wl1271_spi driver name remained, erroneously, as "wl1271". This patch fixes that. Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index f44b05a32b0d..db6c9f5d5779 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c @@ -442,7 +442,7 @@ static int __devexit wl1271_remove(struct spi_device *spi) static struct spi_driver wl1271_spi_driver = { .driver = { - .name = "wl1271", + .name = "wl1271_spi", .bus = &spi_bus_type, .owner = THIS_MODULE, }, -- cgit v1.2.3 From f876bb9aafc71d8ea395eec99666faaffec5df49 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:11 +0200 Subject: wl1271: Clean up RX rate reporting Clean up the code to convert a firmware rate class index into an index for the rate configuration table. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_conf.h | 26 ++++++++++ drivers/net/wireless/wl12xx/wl1271_main.c | 85 +++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1271_rx.c | 76 +-------------------------- drivers/net/wireless/wl12xx/wl1271_rx.h | 2 +- 4 files changed, 114 insertions(+), 75 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 7fcfe06b1412..f63dd5ed998e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -65,6 +65,32 @@ enum { CONF_HW_RATE_INDEX_MAX = CONF_HW_RATE_INDEX_54MBPS, }; +enum { + CONF_HW_RXTX_RATE_MCS7 = 0, + CONF_HW_RXTX_RATE_MCS6, + CONF_HW_RXTX_RATE_MCS5, + CONF_HW_RXTX_RATE_MCS4, + CONF_HW_RXTX_RATE_MCS3, + CONF_HW_RXTX_RATE_MCS2, + CONF_HW_RXTX_RATE_MCS1, + CONF_HW_RXTX_RATE_MCS0, + CONF_HW_RXTX_RATE_54, + CONF_HW_RXTX_RATE_48, + CONF_HW_RXTX_RATE_36, + CONF_HW_RXTX_RATE_24, + CONF_HW_RXTX_RATE_22, + CONF_HW_RXTX_RATE_18, + CONF_HW_RXTX_RATE_12, + CONF_HW_RXTX_RATE_11, + CONF_HW_RXTX_RATE_9, + CONF_HW_RXTX_RATE_6, + CONF_HW_RXTX_RATE_5_5, + CONF_HW_RXTX_RATE_2, + CONF_HW_RXTX_RATE_1, + CONF_HW_RXTX_RATE_MAX, + CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff +}; + enum { CONF_SG_DISABLE = 0, CONF_SG_PROTECTIVE, diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 3daba6c0c77f..49779e588e30 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1816,6 +1816,36 @@ static struct ieee80211_channel wl1271_channels[] = { { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, }; +/* mapping to indexes for wl1271_rates */ +const static u8 wl1271_rate_to_idx_2ghz[] = { + /* MCS rates are used only with 11n */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ + + 11, /* CONF_HW_RXTX_RATE_54 */ + 10, /* CONF_HW_RXTX_RATE_48 */ + 9, /* CONF_HW_RXTX_RATE_36 */ + 8, /* CONF_HW_RXTX_RATE_24 */ + + /* TI-specific rate */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ + + 7, /* CONF_HW_RXTX_RATE_18 */ + 6, /* CONF_HW_RXTX_RATE_12 */ + 3, /* CONF_HW_RXTX_RATE_11 */ + 5, /* CONF_HW_RXTX_RATE_9 */ + 4, /* CONF_HW_RXTX_RATE_6 */ + 2, /* CONF_HW_RXTX_RATE_5_5 */ + 1, /* CONF_HW_RXTX_RATE_2 */ + 0 /* CONF_HW_RXTX_RATE_1 */ +}; + /* can't be const, mac80211 writes to this */ static struct ieee80211_supported_band wl1271_band_2ghz = { .channels = wl1271_channels, @@ -1898,6 +1928,35 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = { { .hw_value = 165, .center_freq = 5825}, }; +/* mapping to indexes for wl1271_rates_5ghz */ +const static u8 wl1271_rate_to_idx_5ghz[] = { + /* MCS rates are used only with 11n */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ + + 7, /* CONF_HW_RXTX_RATE_54 */ + 6, /* CONF_HW_RXTX_RATE_48 */ + 5, /* CONF_HW_RXTX_RATE_36 */ + 4, /* CONF_HW_RXTX_RATE_24 */ + + /* TI-specific rate */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ + + 3, /* CONF_HW_RXTX_RATE_18 */ + 2, /* CONF_HW_RXTX_RATE_12 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_11 */ + 1, /* CONF_HW_RXTX_RATE_9 */ + 0, /* CONF_HW_RXTX_RATE_6 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_5_5 */ + CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_2 */ + CONF_HW_RXTX_RATE_UNSUPPORTED /* CONF_HW_RXTX_RATE_1 */ +}; static struct ieee80211_supported_band wl1271_band_5ghz = { .channels = wl1271_channels_5ghz, @@ -1906,6 +1965,11 @@ static struct ieee80211_supported_band wl1271_band_5ghz = { .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), }; +const static u8 *wl1271_band_rate_to_idx[] = { + [IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz, + [IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz +}; + static const struct ieee80211_ops wl1271_ops = { .start = wl1271_op_start, .stop = wl1271_op_stop, @@ -1923,6 +1987,27 @@ static const struct ieee80211_ops wl1271_ops = { CFG80211_TESTMODE_CMD(wl1271_tm_cmd) }; + +u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate) +{ + u8 idx; + + BUG_ON(wl->band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *)); + + if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) { + wl1271_error("Illegal RX rate from HW: %d", rate); + return 0; + } + + idx = wl1271_band_rate_to_idx[wl->band][rate]; + if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) { + wl1271_error("Unsupported RX rate from HW: %d", rate); + return 0; + } + + return idx; +} + static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index b824c6cc2cc5..a1a7953e475a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c @@ -41,66 +41,6 @@ static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status, RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; } -/* The values of this table must match the wl1271_rates[] array */ -static u8 wl1271_rx_rate_to_idx[] = { - /* MCS rates are used only with 11n */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */ - - 11, /* WL1271_RATE_54 */ - 10, /* WL1271_RATE_48 */ - 9, /* WL1271_RATE_36 */ - 8, /* WL1271_RATE_24 */ - - /* TI-specific rate */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */ - - 7, /* WL1271_RATE_18 */ - 6, /* WL1271_RATE_12 */ - 3, /* WL1271_RATE_11 */ - 5, /* WL1271_RATE_9 */ - 4, /* WL1271_RATE_6 */ - 2, /* WL1271_RATE_5_5 */ - 1, /* WL1271_RATE_2 */ - 0 /* WL1271_RATE_1 */ -}; - -/* The values of this table must match the wl1271_rates[] array */ -static u8 wl1271_5_ghz_rx_rate_to_idx[] = { - /* MCS rates are used only with 11n */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */ - - 7, /* WL1271_RATE_54 */ - 6, /* WL1271_RATE_48 */ - 5, /* WL1271_RATE_36 */ - 4, /* WL1271_RATE_24 */ - - /* TI-specific rate */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */ - - 3, /* WL1271_RATE_18 */ - 2, /* WL1271_RATE_12 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_11 */ - 1, /* WL1271_RATE_9 */ - 0, /* WL1271_RATE_6 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_5_5 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_2 */ - WL1271_RX_RATE_UNSUPPORTED /* WL1271_RATE_1 */ -}; - static void wl1271_rx_status(struct wl1271 *wl, struct wl1271_rx_descriptor *desc, struct ieee80211_rx_status *status, @@ -108,20 +48,8 @@ static void wl1271_rx_status(struct wl1271 *wl, { memset(status, 0, sizeof(struct ieee80211_rx_status)); - if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == - WL1271_RX_DESC_BAND_BG) { - status->band = IEEE80211_BAND_2GHZ; - status->rate_idx = wl1271_rx_rate_to_idx[desc->rate]; - } else if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == - WL1271_RX_DESC_BAND_A) { - status->band = IEEE80211_BAND_5GHZ; - status->rate_idx = wl1271_5_ghz_rx_rate_to_idx[desc->rate]; - } else - wl1271_warning("unsupported band 0x%x", - desc->flags & WL1271_RX_DESC_BAND_MASK); - - if (unlikely(status->rate_idx == WL1271_RX_RATE_UNSUPPORTED)) - wl1271_warning("unsupported rate"); + status->band = wl->band; + status->rate_idx = wl1271_rate_to_idx(wl, desc->rate); /* * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.h b/drivers/net/wireless/wl12xx/wl1271_rx.h index 1ae6d1783ed4..b89be4758e78 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.h +++ b/drivers/net/wireless/wl12xx/wl1271_rx.h @@ -43,7 +43,6 @@ #define RX_MAX_PACKET_ID 3 #define NUM_RX_PKT_DESC_MOD_MASK 7 -#define WL1271_RX_RATE_UNSUPPORTED 0xFF #define RX_DESC_VALID_FCS 0x0001 #define RX_DESC_MATCH_RXADDR1 0x0002 @@ -117,5 +116,6 @@ struct wl1271_rx_descriptor { } __attribute__ ((packed)); void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); +u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); #endif -- cgit v1.2.3 From 31627dc59b4a87c4198b4245a7de1b8ccf4424fa Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:12 +0200 Subject: wl1271: Add TX rate reporting Add reporting of the used TX rate to mac80211 in the tx_status. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 1 + drivers/net/wireless/wl12xx/wl1271_tx.c | 27 +++++++++++++++------------ drivers/net/wireless/wl12xx/wl1271_tx.h | 1 + 3 files changed, 17 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 49779e588e30..864503048257 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -2127,6 +2127,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; wl->hw->queues = 4; + wl->hw->max_rates = 1; SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 6d109df9a0a0..5712489f5ddb 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -304,6 +304,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, struct ieee80211_tx_info *info; struct sk_buff *skb; int id = result->id; + int rate = -1; + u8 retries = 0; /* check for id legality */ if (unlikely(id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL)) { @@ -314,19 +316,22 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, skb = wl->tx_frames[id]; info = IEEE80211_SKB_CB(skb); - /* update packet status */ - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { - if (result->status == TX_SUCCESS) + /* update the TX status info */ + if (result->status == TX_SUCCESS) { + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) info->flags |= IEEE80211_TX_STAT_ACK; - if (result->status & TX_RETRY_EXCEEDED) { - /* FIXME */ - /* info->status.excessive_retries = 1; */ - wl->stats.excessive_retries++; - } + rate = wl1271_rate_to_idx(wl, result->rate_class_index); + retries = result->ack_failures; + } else if (result->status == TX_RETRY_EXCEEDED) { + wl->stats.excessive_retries++; + retries = result->ack_failures; } - /* FIXME */ - /* info->status.retry_count = result->ack_failures; */ + info->status.rates[0].idx = rate; + info->status.rates[0].count = retries; + info->status.rates[0].flags = 0; + info->status.ack_signal = -1; + wl->stats.retry_count += result->ack_failures; /* update security sequence number */ @@ -350,8 +355,6 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, result->id, skb, result->ack_failures, result->rate_class_index, result->status); - /* FIXME: do we need to tell the stack about the used rate? */ - /* return the packet to the stack */ ieee80211_tx_status(wl->hw, skb); wl->tx_frames[result->id] = NULL; diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 5e6c27a57415..b03c95d9673f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h @@ -159,5 +159,6 @@ static inline int wl1271_tx_ac_to_tid(int ac) void wl1271_tx_work(struct work_struct *work); void wl1271_tx_complete(struct wl1271 *wl); void wl1271_tx_flush(struct wl1271 *wl); +u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); #endif -- cgit v1.2.3 From f83cce3551a6238f6c86495ed949b31303c21a6d Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:13 +0200 Subject: wl1271: Fix memory leaks in SPI initialization This patch fixes two memory leaks in the SPI initialization code. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_spi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index db6c9f5d5779..39b7dea6358e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c @@ -104,6 +104,7 @@ static void wl1271_spi_reset(struct wl1271 *wl) spi_message_add_tail(&t, &m); spi_sync(wl_to_spi(wl), &m); + kfree(cmd); wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); } @@ -158,6 +159,7 @@ static void wl1271_spi_init(struct wl1271 *wl) spi_message_add_tail(&t, &m); spi_sync(wl_to_spi(wl), &m); + kfree(cmd); wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); } -- cgit v1.2.3 From 9cea461fb0a37dae9ef0a83714c5fcdc4b2074c8 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:14 +0200 Subject: wl1271: Fix memory leak in scan command handling This patch fixes a memory leak in the scan command handling code. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index d005729e0312..dbed0606771f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -665,6 +665,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, out: kfree(params); + kfree(trigger); return ret; } -- cgit v1.2.3 From 9d4e5bb3dec8c4b9245035bf29628071801041a8 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:15 +0200 Subject: wl1271: Configure clock-request drive mode to open-drain This patch configures the wl1271 chipset clock-request line to be driver in open-drain mode instead of push-pull. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_boot.c | 8 ++++++-- drivers/net/wireless/wl12xx/wl1271_boot.h | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 41c6affbee29..4195298b5abc 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -451,11 +451,15 @@ int wl1271_boot(struct wl1271 *wl) if (REF_CLOCK != 0) { u16 val; - /* Set clock type */ + /* Set clock type (open drain) */ val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); val &= FREF_CLK_TYPE_BITS; - val |= CLK_REQ_PRCM; wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val); + + /* Set clock pull mode (no pull) */ + val = wl1271_top_reg_read(wl, OCP_REG_CLK_PULL); + val |= NO_PULL; + wl1271_top_reg_write(wl, OCP_REG_CLK_PULL, val); } else { u16 val; /* Set clock polarity */ diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h index 412443ee655a..95ecc5241959 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.h +++ b/drivers/net/wireless/wl12xx/wl1271_boot.h @@ -53,10 +53,13 @@ struct wl1271_static_data { #define OCP_REG_POLARITY 0x0064 #define OCP_REG_CLK_TYPE 0x0448 #define OCP_REG_CLK_POLARITY 0x0cb2 +#define OCP_REG_CLK_PULL 0x0cb4 -#define CMD_MBOX_ADDRESS 0x407B4 -#define POLARITY_LOW BIT(1) +#define CMD_MBOX_ADDRESS 0x407B4 + +#define POLARITY_LOW BIT(1) +#define NO_PULL (BIT(14) | BIT(15)) #define FREF_CLK_TYPE_BITS 0xfffffe7f #define CLK_REQ_PRCM 0x100 -- cgit v1.2.3 From 99e50314d588673353bf94978938bd1c2437037d Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Fri, 26 Mar 2010 12:53:16 +0200 Subject: wl1271: Warnings caused by wrong format specifiers fixed There were wrong format specifiers in wl1271_sdio.c in some debug outputs. This has been causing warnings on some platforms. Signed-off-by: Teemu Paasikivi Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_sdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index 3c03de74dbfc..abfe75b68601 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c @@ -117,7 +117,7 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, else ret = sdio_memcpy_fromio(func, buf, addr, len); - wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %d bytes", + wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %zu bytes", addr, len); wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); } @@ -138,7 +138,7 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", addr, ((u8 *)buf)[0]); } else { - wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %d bytes", + wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %zu bytes", addr, len); wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); -- cgit v1.2.3 From 1b00f2b560028a68cdbc57a0352163afd79822dd Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:17 +0200 Subject: wl1271: Fix memory leak in cmd_data_path Fix a trivial memory leak in cmd_data_path. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index dbed0606771f..efd94f2c3168 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -454,7 +454,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) if (ret < 0) { wl1271_error("tx %s cmd for channel %d failed", enable ? "start" : "stop", cmd->channel); - return ret; + goto out; } wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", -- cgit v1.2.3 From 259da430b198fc7e6f21e33be3a2d6dd27200953 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:18 +0200 Subject: wl1271: Update busyword checking mechanism After the busy-words, if the firmware did not complete by the end of the first (fixed) busy-word, a flip of the CS line is required to enable clocking out the actual read data. This patch changes the mechanism such that the CS line is flipped after each busyword. Also, the busy-word mechanism is finally enabled, and the number of fixed busywords reduced to the minimum. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 9 +---- drivers/net/wireless/wl12xx/wl1271_spi.c | 67 +++++++++++--------------------- 2 files changed, 24 insertions(+), 52 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 8f11506f8310..c93968092fc1 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -147,14 +147,7 @@ struct wl1271_nvs_file { */ #undef WL1271_80211A_ENABLED -/* - * FIXME: for the wl1271, a busy word count of 1 here will result in a more - * optimal SPI interface. There is some SPI bug however, causing RXS time outs - * with this mode occasionally on boot, so lets have three for now. A value of - * three should make sure, that the chipset will always be ready, though this - * will impact throughput and latencies slightly. - */ -#define WL1271_BUSY_WORD_CNT 3 +#define WL1271_BUSY_WORD_CNT 1 #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) #define WL1271_ELP_HW_STATE_ASLEEP 0 diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 39b7dea6358e..7a7db011a797 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c @@ -166,41 +166,17 @@ static void wl1271_spi_init(struct wl1271 *wl) #define WL1271_BUSY_WORD_TIMEOUT 1000 -/* FIXME: Check busy words, removed due to SPI bug */ -#if 0 -static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) +static int wl1271_spi_read_busy(struct wl1271 *wl) { struct spi_transfer t[1]; struct spi_message m; u32 *busy_buf; int num_busy_bytes = 0; - wl1271_info("spi read BUSY!"); - - /* - * Look for the non-busy word in the read buffer, and if found, - * read in the remaining data into the buffer. - */ - busy_buf = (u32 *)buf; - for (; (u32)busy_buf < (u32)buf + len; busy_buf++) { - num_busy_bytes += sizeof(u32); - if (*busy_buf & 0x1) { - spi_message_init(&m); - memset(t, 0, sizeof(t)); - memmove(buf, busy_buf, len - num_busy_bytes); - t[0].rx_buf = buf + (len - num_busy_bytes); - t[0].len = num_busy_bytes; - spi_message_add_tail(&t[0], &m); - spi_sync(wl_to_spi(wl), &m); - return; - } - } - /* * Read further busy words from SPI until a non-busy word is * encountered, then read the data itself into the buffer. */ - wl1271_info("spi read BUSY-polling needed!"); num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT; busy_buf = wl->buffer_busyword; @@ -210,28 +186,21 @@ static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) memset(t, 0, sizeof(t)); t[0].rx_buf = busy_buf; t[0].len = sizeof(u32); + t[0].cs_change = true; spi_message_add_tail(&t[0], &m); spi_sync(wl_to_spi(wl), &m); - if (*busy_buf & 0x1) { - spi_message_init(&m); - memset(t, 0, sizeof(t)); - t[0].rx_buf = buf; - t[0].len = len; - spi_message_add_tail(&t[0], &m); - spi_sync(wl_to_spi(wl), &m); - return; - } + if (*busy_buf & 0x1) + return 0; } /* The SPI bus is unresponsive, the read failed. */ - memset(buf, 0, len); wl1271_error("SPI read busy-word timeout!\n"); + return -ETIMEDOUT; } -#endif static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed) + size_t len, bool fixed) { struct spi_transfer t[3]; struct spi_message m; @@ -254,22 +223,32 @@ static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, t[0].tx_buf = cmd; t[0].len = 4; + t[0].cs_change = true; spi_message_add_tail(&t[0], &m); /* Busy and non busy words read */ t[1].rx_buf = busy_buf; t[1].len = WL1271_BUSY_WORD_LEN; + t[1].cs_change = true; spi_message_add_tail(&t[1], &m); - t[2].rx_buf = buf; - t[2].len = len; - spi_message_add_tail(&t[2], &m); - spi_sync(wl_to_spi(wl), &m); - /* FIXME: Check busy words, removed due to SPI bug */ - /* if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1)) - wl1271_spi_read_busy(wl, buf, len); */ + if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && + wl1271_spi_read_busy(wl)) { + memset(buf, 0, len); + return; + } + + spi_message_init(&m); + memset(t, 0, sizeof(t)); + + t[0].rx_buf = buf; + t[0].len = len; + t[0].cs_change = true; + spi_message_add_tail(&t[0], &m); + + spi_sync(wl_to_spi(wl), &m); wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); -- cgit v1.2.3 From 9560134ff929a037f0c967ae47089586f4b34390 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:19 +0200 Subject: wl1271: Remove device MAC-address randomization This patch removes the MAC address randomization from the driver. This removes a nasty Nokia-OUI dependency from the driver. With this patch, unless an address is explicitly configured to the driver by the user, only a zero address will be configured, and the driver will be unable to start. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 864503048257..4a2f1d772adc 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -2143,7 +2143,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) struct platform_device *plat_dev = NULL; struct wl1271 *wl; int i, ret; - static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); if (!hw) { @@ -2195,13 +2194,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->state = WL1271_STATE_OFF; mutex_init(&wl->mutex); - /* - * FIXME: we should use a zero MAC address here, but for now we - * generate a random Nokia address. - */ - memcpy(wl->mac_addr, nokia_oui, 3); - get_random_bytes(wl->mac_addr + 3, 3); - /* Apply default driver configuration. */ wl1271_conf_init(wl); -- cgit v1.2.3 From 99d84c1de8fdf5f9b09f07fdbc628857a040bf8b Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 26 Mar 2010 12:53:20 +0200 Subject: wl1271: wait for join command complete event Poll for join command completion instead of waiting blindly for 10 msecs. There is a timeout of 100 msecs, if the command doesn't complete by then, we return an error code. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_boot.c | 3 ++- drivers/net/wireless/wl12xx/wl1271_cmd.c | 38 +++++++++++++++++++++++++++---- drivers/net/wireless/wl12xx/wl1271_cmd.h | 1 + 3 files changed, 36 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 4195298b5abc..2c7e5612d5ba 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -410,7 +410,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) /* unmask required mbox events */ wl->event_mask = BSS_LOSE_EVENT_ID | SCAN_COMPLETE_EVENT_ID | - PS_REPORT_EVENT_ID; + PS_REPORT_EVENT_ID | + JOIN_EVENT_COMPLETE_ID; ret = wl1271_event_unmask(wl); if (ret < 0) { diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index efd94f2c3168..e677f979ca6b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -34,6 +34,7 @@ #include "wl1271_acx.h" #include "wl12xx_80211.h" #include "wl1271_cmd.h" +#include "wl1271_event.h" /* * send command to firmware @@ -248,6 +249,35 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) return ret; } +/* + * Poll the mailbox event field until any of the bits in the mask is set or a + * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) + */ +static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) +{ + u32 events_vector, event; + unsigned long timeout; + + timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); + + do { + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; + + msleep(1); + + /* read from both event fields */ + wl1271_read(wl, wl->mbox_ptr[0], &events_vector, + sizeof(events_vector), false); + event = events_vector & mask; + wl1271_read(wl, wl->mbox_ptr[1], &events_vector, + sizeof(events_vector), false); + event |= events_vector & mask; + } while (!event); + + return 0; +} + int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) { static bool do_cal = true; @@ -318,11 +348,9 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) goto out_free; } - /* - * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to - * simplify locking we just sleep instead, for now - */ - msleep(10); + ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID); + if (ret < 0) + wl1271_error("cmd join event completion error"); out_free: kfree(join); diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 6324bbf36843..bdd7a3d8ece6 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -123,6 +123,7 @@ enum cmd_templ { /* unit ms */ #define WL1271_COMMAND_TIMEOUT 2000 #define WL1271_CMD_TEMPL_MAX_SIZE 252 +#define WL1271_EVENT_TIMEOUT 100 struct wl1271_cmd_header { __le16 id; -- cgit v1.2.3 From 2f826f55404ca43efced94d548356182820e764f Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 26 Mar 2010 12:53:21 +0200 Subject: wl1271: wait for disconnect command complete event Wait for the DISCONNECT_EVENT_COMPLETE_ID event after sending a disconnect command. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_boot.c | 5 +++-- drivers/net/wireless/wl12xx/wl1271_cmd.c | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 2c7e5612d5ba..7acef88df1fe 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -1,7 +1,7 @@ /* * This file is part of wl1271 * - * Copyright (C) 2008-2009 Nokia Corporation + * Copyright (C) 2008-2010 Nokia Corporation * * Contact: Luciano Coelho * @@ -411,7 +411,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) wl->event_mask = BSS_LOSE_EVENT_ID | SCAN_COMPLETE_EVENT_ID | PS_REPORT_EVENT_ID | - JOIN_EVENT_COMPLETE_ID; + JOIN_EVENT_COMPLETE_ID | + DISCONNECT_EVENT_COMPLETE_ID; ret = wl1271_event_unmask(wl); if (ret < 0) { diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index e677f979ca6b..0aa2422982d3 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -1,7 +1,7 @@ /* * This file is part of wl1271 * - * Copyright (C) 2009 Nokia Corporation + * Copyright (C) 2009-2010 Nokia Corporation * * Contact: Luciano Coelho * @@ -942,6 +942,10 @@ int wl1271_cmd_disconnect(struct wl1271 *wl) goto out_free; } + ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); + if (ret < 0) + wl1271_error("cmd disconnect event completion error"); + out_free: kfree(cmd); -- cgit v1.2.3 From e7942235f2496587cb4af86168e54d588ffcbd4f Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 26 Mar 2010 12:53:22 +0200 Subject: wl1271: remove deprecated usage of RX status noise The noise element in the ieee80211_rx_status struct has been deprecated in commit "mac80211: deprecate RX status noise". Remove the usage of this element from wl1271_rx.c to avoid warnings. Signed-off-by: Luciano Coelho Reviewed-by: Teemu Paasikivi Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_rx.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index a1a7953e475a..ca442703d1ab 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c @@ -59,13 +59,6 @@ static void wl1271_rx_status(struct wl1271 *wl, */ status->signal = desc->rssi; - /* - * FIXME: In wl1251, the SNR should be divided by two. In wl1271 we - * need to divide by two for now, but TI has been discussing about - * changing it. This needs to be rechecked. - */ - status->noise = desc->rssi - (desc->snr >> 1); - status->freq = ieee80211_channel_to_frequency(desc->channel); if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { -- cgit v1.2.3 From 6ccbb92ead9379d7de2cc25cd950d15a8d22e0c9 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:23 +0200 Subject: wl1271: Disable connection monitoring while not associated The wl1271 does not support disabling the connection monitor feature. Perform the next best thing by increasing the beacon-loss threshold and BSS_LOSE event timeout to the maximum values. This is needed, because we really don't want any random probe-requests during scanning or especially while in ad-hoc mode and not beaconing. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.c | 18 ++++++++++++++---- drivers/net/wireless/wl12xx/wl1271_acx.h | 2 +- drivers/net/wireless/wl12xx/wl1271_init.c | 2 +- drivers/net/wireless/wl12xx/wl1271_main.c | 12 +++++++++++- 4 files changed, 27 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 7e337cea9905..e7d11811a907 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -504,12 +504,17 @@ out: return ret; } -int wl1271_acx_conn_monit_params(struct wl1271 *wl) +#define ACX_CONN_MONIT_DISABLE_VALUE 0xffffffff + +int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable) { struct acx_conn_monit_params *acx; + u32 threshold = ACX_CONN_MONIT_DISABLE_VALUE; + u32 timeout = ACX_CONN_MONIT_DISABLE_VALUE; int ret; - wl1271_debug(DEBUG_ACX, "acx connection monitor parameters"); + wl1271_debug(DEBUG_ACX, "acx connection monitor parameters: %s", + enable ? "enabled" : "disabled"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); if (!acx) { @@ -517,8 +522,13 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl) goto out; } - acx->synch_fail_thold = cpu_to_le32(wl->conf.conn.synch_fail_thold); - acx->bss_lose_timeout = cpu_to_le32(wl->conf.conn.bss_lose_timeout); + if (enable) { + threshold = wl->conf.conn.synch_fail_thold; + timeout = wl->conf.conn.bss_lose_timeout; + } + + acx->synch_fail_thold = cpu_to_le32(threshold); + acx->bss_lose_timeout = cpu_to_le32(timeout); ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS, acx, sizeof(*acx)); diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 8e5870fa9609..b6eb0c1b6c78 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -1004,7 +1004,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); int wl1271_acx_dco_itrim_params(struct wl1271 *wl); int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); int wl1271_acx_beacon_filter_table(struct wl1271 *wl); -int wl1271_acx_conn_monit_params(struct wl1271 *wl); +int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); int wl1271_acx_sg_cfg(struct wl1271 *wl); int wl1271_acx_cca_threshold(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index d9335fc2a575..987978c3bce0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -236,7 +236,7 @@ int wl1271_hw_init(struct wl1271 *wl) goto out_free_memmap; /* Initialize connection monitoring thresholds */ - ret = wl1271_acx_conn_monit_params(wl); + ret = wl1271_acx_conn_monit_params(wl, false); if (ret < 0) goto out_free_memmap; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 4a2f1d772adc..00e856c4a611 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -348,7 +348,7 @@ static int wl1271_plt_init(struct wl1271 *wl) goto out_free_memmap; /* Initialize connection monitoring thresholds */ - ret = wl1271_acx_conn_monit_params(wl); + ret = wl1271_acx_conn_monit_params(wl, false); if (ret < 0) goto out_free_memmap; @@ -1651,6 +1651,11 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (ret < 0) goto out_sleep; + /* enable the connection monitoring feature */ + ret = wl1271_acx_conn_monit_params(wl, true); + if (ret < 0) + goto out_sleep; + /* If we want to go in PSM but we're not there yet */ if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && !test_bit(WL1271_FLAG_PSM, &wl->flags)) { @@ -1663,6 +1668,11 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, /* use defaults when not associated */ clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); wl->aid = 0; + + /* disable connection monitor features */ + ret = wl1271_acx_conn_monit_params(wl, false); + if (ret < 0) + goto out_sleep; } } -- cgit v1.2.3 From 5da11dcde3d2a91688e02f032062fa26877eacb0 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:24 +0200 Subject: wl1271: Fix ad-hoc mode handling Fix the driver to better reflect the ad-hoc related configuration from the mac80211. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 2 ++ drivers/net/wireless/wl12xx/wl1271_main.c | 33 ++++++++++++++++++++----------- 2 files changed, 24 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index c93968092fc1..37ad5cd0b82f 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -55,6 +55,7 @@ enum { DEBUG_ACX = BIT(13), DEBUG_SDIO = BIT(14), DEBUG_FILTERS = BIT(15), + DEBUG_ADHOC = BIT(16), DEBUG_ALL = ~0, }; @@ -389,6 +390,7 @@ struct wl1271 { u8 bssid[ETH_ALEN]; u8 mac_addr[ETH_ALEN]; u8 bss_type; + u8 set_bss_type; u8 ssid[IW_ESSID_MAX_SIZE + 1]; u8 ssid_len; int channel; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 00e856c4a611..49f37b0183ac 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -958,9 +958,11 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, switch (vif->type) { case NL80211_IFTYPE_STATION: wl->bss_type = BSS_TYPE_STA_BSS; + wl->set_bss_type = BSS_TYPE_STA_BSS; break; case NL80211_IFTYPE_ADHOC: wl->bss_type = BSS_TYPE_IBSS; + wl->set_bss_type = BSS_TYPE_STA_BSS; break; default: ret = -EOPNOTSUPP; @@ -1065,6 +1067,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); wl->ssid_len = 0; wl->bss_type = MAX_BSS_TYPE; + wl->set_bss_type = MAX_BSS_TYPE; wl->band = IEEE80211_BAND_2GHZ; wl->rx_counter = 0; @@ -1137,10 +1140,7 @@ static int wl1271_join_channel(struct wl1271 *wl, int channel) /* pass through frames from all BSS */ wl1271_configure_filters(wl, FIF_OTHER_BSS); - /* the dummy join is performed always with STATION BSS type to allow - also ad-hoc mode to listen to the surroundings without sending any - beacons yet. */ - ret = wl1271_cmd_join(wl, BSS_TYPE_STA_BSS); + ret = wl1271_cmd_join(wl, wl->set_bss_type); if (ret < 0) goto out; @@ -1211,7 +1211,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) test_bit(WL1271_FLAG_JOINED, &wl->flags)) { wl->channel = channel; /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ - ret = wl1271_cmd_join(wl, wl->bss_type); + ret = wl1271_cmd_join(wl, wl->set_bss_type); if (ret < 0) wl1271_warning("cmd join to update channel failed %d", ret); @@ -1575,13 +1575,12 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (ret < 0) goto out; - if (wl->bss_type == BSS_TYPE_IBSS) { - /* FIXME: This implements rudimentary ad-hoc support - - proper templates are on the wish list and notification - on when they change. This patch will update the templates - on every call to this function. */ + if ((changed && BSS_CHANGED_BEACON) && + (wl->bss_type == BSS_TYPE_IBSS)) { struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon updated"); + if (beacon) { struct ieee80211_hdr *hdr; @@ -1613,6 +1612,18 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } } + if ((changed & BSS_CHANGED_BEACON_ENABLED) && + (wl->bss_type == BSS_TYPE_IBSS)) { + wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", + bss_conf->enable_beacon ? "enabled" : "disabled"); + + if (bss_conf->enable_beacon) + wl->set_bss_type = BSS_TYPE_IBSS; + else + wl->set_bss_type = BSS_TYPE_STA_BSS; + do_join = true; + } + if ((changed & BSS_CHANGED_BSSID) && /* * Now we know the correct bssid, so we send a new join command @@ -1707,7 +1718,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } if (do_join) { - ret = wl1271_cmd_join(wl, wl->bss_type); + ret = wl1271_cmd_join(wl, wl->set_bss_type); if (ret < 0) { wl1271_warning("cmd join failed %d", ret); goto out_sleep; -- cgit v1.2.3 From 60e84c2ebb7b04361cf1ba0d325cc93366bd04a6 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:25 +0200 Subject: wl1271: Update beacon interval properly for ad-hoc Configure the hardware beacon interval to whatever requested by the mac80211. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 3 +++ drivers/net/wireless/wl12xx/wl1271_cmd.c | 2 +- drivers/net/wireless/wl12xx/wl1271_main.c | 10 ++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 37ad5cd0b82f..c5559efcf5a7 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -452,6 +452,9 @@ struct wl1271 { /* The current band */ enum ieee80211_band band; + /* Beaconing interval (needed for ad-hoc) */ + u32 beacon_int; + /* Default key (for WEP) */ u32 default_key; diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 0aa2422982d3..0dcb3c2afe07 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -323,7 +323,7 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) CONF_HW_BIT_RATE_24MBPS); } - join->beacon_interval = cpu_to_le16(WL1271_DEFAULT_BEACON_INT); + join->beacon_interval = cpu_to_le16(wl->beacon_int); join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; join->channel = wl->channel; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 49f37b0183ac..523e051d62dd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1575,6 +1575,15 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (ret < 0) goto out; + if ((changed && BSS_CHANGED_BEACON_INT) && + (wl->bss_type == BSS_TYPE_IBSS)) { + wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d", + bss_conf->beacon_int); + + wl->beacon_int = bss_conf->beacon_int; + do_join = true; + } + if ((changed && BSS_CHANGED_BEACON) && (wl->bss_type == BSS_TYPE_IBSS)) { struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); @@ -2193,6 +2202,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); wl->channel = WL1271_DEFAULT_CHANNEL; + wl->beacon_int = WL1271_DEFAULT_BEACON_INT; wl->default_key = 0; wl->rx_counter = 0; wl->rx_config = WL1271_DEFAULT_RX_CONFIG; -- cgit v1.2.3 From 64e29e447ec01d2130b4c68f3459cfaa94fa138b Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Fri, 26 Mar 2010 12:53:26 +0200 Subject: wl1271: Removed checking of PSM from handling BSS_LOST_EVENT Change the driver to call ieee80211_beacon_loss function always when BSS_LOST_EVENT is received. Reason for the change is that entering PSM might fail before driver receives BSS_LOST_EVENT. In such case the driver would disable PSM and the stack would not be notified about beacon loss and connection loss detection would be delayed by tens of seconds. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_event.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 4d35af96c597..a5c1910a0247 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -173,9 +173,12 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon * filtering) is enabled. Without PSM, the stack will receive all * beacons and can detect beacon loss by itself. + * + * As there's possibility that the driver disables PSM before receiving + * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. + * */ - if (vector & BSS_LOSE_EVENT_ID && - test_bit(WL1271_FLAG_PSM, &wl->flags)) { + if (vector & BSS_LOSE_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); /* indicate to the stack, that beacons have been lost */ -- cgit v1.2.3 From cbf7f3058ea17d9413a6889c3a229e8eac7a7c78 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:27 +0200 Subject: wl1271: Fix memory leak in firmware crash scenario The driver tx-queue flush operation leaks broadcast-frames. This leak occurs if the driver is shut down while there are frames in TX buffers (such as in a firmware crash scenario.) Fix the leak. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_tx.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 5712489f5ddb..66b48b70444e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -426,8 +426,10 @@ void wl1271_tx_flush(struct wl1271 *wl) wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); - if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) - continue; + if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { + kfree_skb(skb); + continue; + } ieee80211_tx_status(wl->hw, skb); } @@ -437,8 +439,10 @@ void wl1271_tx_flush(struct wl1271 *wl) skb = wl->tx_frames[i]; info = IEEE80211_SKB_CB(skb); - if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) + if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { + kfree_skb(skb); continue; + } ieee80211_tx_status(wl->hw, skb); wl->tx_frames[i] = NULL; -- cgit v1.2.3 From c2b2d99bb0b5a9445ff8b845f6acd5046ef5815e Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:28 +0200 Subject: wl1271: Configure probe-request template when associated Configure a probe-request template to the wl1271 when associated - the wl1271 will use this to attempt to recover a connection when beacon loss is detected. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_event.c | 12 ------------ drivers/net/wireless/wl12xx/wl1271_main.c | 9 +++++++++ 2 files changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index a5c1910a0247..0e0808fa4e32 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -31,14 +31,11 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, struct event_mailbox *mbox) { - int size = sizeof(struct wl12xx_probe_req_template); wl1271_debug(DEBUG_EVENT, "status: 0x%x", mbox->scheduled_scan_status); if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { - wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, - NULL, size); /* 2.4 GHz band scanned, scan 5 GHz band, pretend * to the wl1271_cmd_scan function that we are not * scanning as it checks that. @@ -52,15 +49,6 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, WL1271_SCAN_BAND_5_GHZ, wl->scan.probe_requests); } else { - if (wl->scan.state == WL1271_SCAN_BAND_2_4_GHZ) - wl1271_cmd_template_set(wl, - CMD_TEMPL_CFG_PROBE_REQ_2_4, - NULL, size); - else - wl1271_cmd_template_set(wl, - CMD_TEMPL_CFG_PROBE_REQ_5, - NULL, size); - mutex_unlock(&wl->mutex); ieee80211_scan_completed(wl->hw, false); mutex_lock(&wl->mutex); diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 523e051d62dd..849c4ac6e01b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1667,6 +1667,15 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (ret < 0) goto out_sleep; + /* + * The SSID is intentionally set to NULL here - the + * firmware will set the probe request with a + * broadcast SSID regardless of what we set in the + * template. + */ + ret = wl1271_cmd_build_probe_req(wl, NULL, 0, + NULL, 0, wl->band); + ret = wl1271_acx_aid(wl, wl->aid); if (ret < 0) goto out_sleep; -- cgit v1.2.3 From d60772f646f70ba0a72c9a300935df8fad256ff9 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:29 +0200 Subject: wl1271: Disconnect if PSM entry fails If PSM entry fails despite of retries, assume that the AP has been lost, and indicate connection loss to the mac80211. This is much safer than remaining in active mode. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_event.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 0e0808fa4e32..4fc212a02a64 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -82,15 +82,8 @@ static int wl1271_event_ps_report(struct wl1271 *wl, true); } else { wl1271_error("PSM entry failed, giving up.\n"); - /* FIXME: this may need to be reconsidered. for now it - is not possible to indicate to the mac80211 - afterwards that PSM entry failed. To maximize - functionality (receiving data and remaining - associated) make sure that we are in sync with the - AP in regard of PSM mode. */ - ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, - false); wl->psm_entry_retry = 0; + *beacon_loss = true; } break; case EVENT_ENTER_POWER_SAVE_SUCCESS: @@ -180,16 +173,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) return ret; } - if (wl->vif && beacon_loss) { - /* Obviously, it's dangerous to release the mutex while - we are holding many of the variables in the wl struct. - That's why it's done last in the function, and care must - be taken that nothing more is done after this function - returns. */ - mutex_unlock(&wl->mutex); - ieee80211_beacon_loss(wl->vif); - mutex_lock(&wl->mutex); - } + if (wl->vif && beacon_loss) + ieee80211_connection_loss(wl->vif); return 0; } -- cgit v1.2.3 From a9af092b524614dd3fc7b52bde7c87f8b82cd2a6 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:30 +0200 Subject: wl1271: Configure HW connection monitor This patch configures the mac80211 to not perform connection monitoring (periodic probe-requests) and instead rely on the hardware to do it. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 849c4ac6e01b..2df00adcf903 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -2155,7 +2155,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl) IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_UAPSD | - IEEE80211_HW_HAS_RATE_CONTROL; + IEEE80211_HW_HAS_RATE_CONTROL | + IEEE80211_HW_CONNECTION_MONITOR; wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); -- cgit v1.2.3 From bfb24c9e16921f0e57fcec5180ffa20929832545 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:31 +0200 Subject: wl1271: Add keep-alive frame template support Add support for keep-alive templates, which are indexed. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 35 +++++++++++++++++++++++++------ drivers/net/wireless/wl12xx/wl1271_cmd.h | 8 ++++++- drivers/net/wireless/wl12xx/wl1271_init.c | 31 +++++++++++++++++++-------- drivers/net/wireless/wl12xx/wl1271_main.c | 4 ++-- 4 files changed, 60 insertions(+), 18 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 0dcb3c2afe07..0cb4cbb00395 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -698,7 +698,7 @@ out: } int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, - void *buf, size_t buf_len) + void *buf, size_t buf_len, int index) { struct wl1271_cmd_template_set *cmd; int ret = 0; @@ -719,6 +719,7 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, cmd->enabled_rates = cpu_to_le32(wl->conf.tx.rc_conf.enabled_rates); cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit; cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit; + cmd->index = index; if (buf) memcpy(cmd->template_data, buf, buf_len); @@ -755,7 +756,7 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl) ptr = skb->data; } - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size); + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0); out: dev_kfree_skb(skb); @@ -766,6 +767,28 @@ out: } +int wl1271_cmd_build_klv_null_data(struct wl1271 *wl) +{ + struct sk_buff *skb = NULL; + int ret = -ENOMEM; + + skb = ieee80211_nullfunc_get(wl->hw, wl->vif); + if (!skb) + goto out; + + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, + skb->data, skb->len, + CMD_TEMPL_KLV_IDX_NULL_DATA); + +out: + dev_kfree_skb(skb); + if (ret) + wl1271_warning("cmd build klv null data failed %d", ret); + + return ret; + +} + int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) { struct sk_buff *skb; @@ -776,7 +799,7 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) goto out; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, - skb->len); + skb->len, 0); out: dev_kfree_skb(skb); @@ -801,10 +824,10 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, if (band == IEEE80211_BAND_2GHZ) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, - skb->data, skb->len); + skb->data, skb->len, 0); else ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, - skb->data, skb->len); + skb->data, skb->len, 0); out: dev_kfree_skb(skb); @@ -829,7 +852,7 @@ int wl1271_build_qos_null_data(struct wl1271 *wl) template.qos_ctrl = cpu_to_le16(0); return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, - sizeof(template)); + sizeof(template), 0); } int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index bdd7a3d8ece6..e1131bc0d15c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -45,13 +45,14 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, u8 active_scan, u8 high_prio, u8 band, u8 probe_requests); int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, - void *buf, size_t buf_len); + void *buf, size_t buf_len, int index); int wl1271_cmd_build_null_data(struct wl1271 *wl); int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); int wl1271_cmd_build_probe_req(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, u8 band); int wl1271_build_qos_null_data(struct wl1271 *wl); +int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, const u8 *addr, @@ -101,6 +102,11 @@ enum wl1271_commands { #define MAX_CMD_PARAMS 572 +enum { + CMD_TEMPL_KLV_IDX_NULL_DATA = 0, + CMD_TEMPL_KLV_IDX_MAX = 4 +}; + enum cmd_templ { CMD_TEMPL_NULL_DATA = 0, CMD_TEMPL_BEACON, diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 987978c3bce0..0106663bc45b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -51,50 +51,63 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl) int wl1271_init_templates_config(struct wl1271 *wl) { - int ret; + int ret, i; /* send empty templates for fw memory reservation */ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, - sizeof(struct wl12xx_probe_req_template)); + sizeof(struct wl12xx_probe_req_template), + 0); if (ret < 0) return ret; if (wl1271_11a_enabled()) { + size_t size = sizeof(struct wl12xx_probe_req_template); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, - NULL, - sizeof(struct wl12xx_probe_req_template)); + NULL, size, 0); if (ret < 0) return ret; } ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, - sizeof(struct wl12xx_null_data_template)); + sizeof(struct wl12xx_null_data_template), + 0); if (ret < 0) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL, - sizeof(struct wl12xx_ps_poll_template)); + sizeof(struct wl12xx_ps_poll_template), + 0); if (ret < 0) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, sizeof - (struct wl12xx_qos_null_data_template)); + (struct wl12xx_qos_null_data_template), + 0); if (ret < 0) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, sizeof - (struct wl12xx_probe_resp_template)); + (struct wl12xx_probe_resp_template), + 0); if (ret < 0) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, sizeof - (struct wl12xx_beacon_template)); + (struct wl12xx_beacon_template), + 0); if (ret < 0) return ret; + for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, + WL1271_CMD_TEMPL_MAX_SIZE, i); + if (ret < 0) + return ret; + } + return 0; } diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 2df00adcf903..afab52bec134 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1596,7 +1596,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, wl1271_ssid_set(wl, beacon); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, beacon->data, - beacon->len); + beacon->len, 0); if (ret < 0) { dev_kfree_skb(beacon); @@ -1611,7 +1611,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, beacon->data, - beacon->len); + beacon->len, 0); dev_kfree_skb(beacon); if (ret < 0) goto out_sleep; -- cgit v1.2.3 From c18995540cc4d2c84d130581b8b6720b22ca16b5 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Mar 2010 12:53:32 +0200 Subject: wl1271: Enable hardware keep alive messages This patch will enable the hardware keep-alive mode, configure the required template, configure keep-alive parameters, and re-order JOIN's and ACX_AID in such a way that the keep-alive is activated. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.c | 55 +++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1271_acx.h | 31 ++++++++++++++++- drivers/net/wireless/wl12xx/wl1271_conf.h | 9 +++++ drivers/net/wireless/wl12xx/wl1271_init.c | 13 ++++++++ drivers/net/wireless/wl12xx/wl1271_main.c | 33 +++++++++++++++++-- 5 files changed, 138 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index e7d11811a907..8f0bd5bee6f9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -1139,3 +1139,58 @@ out: kfree(acx); return ret; } + +int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable) +{ + struct wl1271_acx_keep_alive_mode *acx = NULL; + int ret = 0; + + wl1271_debug(DEBUG_ACX, "acx keep alive mode: %d", enable); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) { + ret = -ENOMEM; + goto out; + } + + acx->enabled = enable; + + ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("acx keep alive mode failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} +int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) +{ + struct wl1271_acx_keep_alive_config *acx = NULL; + int ret = 0; + + wl1271_debug(DEBUG_ACX, "acx keep alive config"); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) { + ret = -ENOMEM; + goto out; + } + + acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval); + acx->index = index; + acx->tpl_validation = tpl_valid; + acx->trigger = ACX_KEEP_ALIVE_NO_TX; + + ret = wl1271_cmd_configure(wl, ACX_SET_KEEP_ALIVE_CONFIG, + acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("acx keep alive config failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index b6eb0c1b6c78..15cc56192de9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -915,6 +915,33 @@ struct wl1271_acx_pm_config { u8 padding[3]; } __attribute__ ((packed)); +struct wl1271_acx_keep_alive_mode { + struct acx_header header; + + u8 enabled; + u8 padding[3]; +} __attribute__ ((packed)); + +enum { + ACX_KEEP_ALIVE_NO_TX = 0, + ACX_KEEP_ALIVE_PERIOD_ONLY +}; + +enum { + ACX_KEEP_ALIVE_TPL_INVALID = 0, + ACX_KEEP_ALIVE_TPL_VALID +}; + +struct wl1271_acx_keep_alive_config { + struct acx_header header; + + __le32 period; + u8 index; + u8 tpl_validation; + u8 trigger; + u8 padding; +} __attribute__ ((packed)); + enum { ACX_WAKE_UP_CONDITIONS = 0x0002, ACX_MEM_CFG = 0x0003, @@ -964,7 +991,7 @@ enum { ACX_BET_ENABLE = 0x0050, ACX_RSSI_SNR_TRIGGER = 0x0051, ACX_RSSI_SNR_WEIGHTS = 0x0051, - ACX_KEEP_ALIVE_MODE = 0x0052, + ACX_KEEP_ALIVE_MODE = 0x0053, ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, ACX_BA_SESSION_INITIATOR_POLICY = 0x0056, @@ -1031,5 +1058,7 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, u8 version); int wl1271_acx_pm_config(struct wl1271 *wl); +int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); +int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); #endif /* __WL1271_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index f63dd5ed998e..82b5dabb6e8d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -955,6 +955,15 @@ struct conf_conn_settings { * Range 0 - 255 */ u8 psm_entry_retries; + + /* + * + * Specifies the interval of the connection keep-alive null-func + * frame in ms. + * + * Range: 1000 - 3600000 + */ + u32 keep_alive_interval; }; enum { diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 0106663bc45b..8ec94ac84093 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -337,6 +337,19 @@ int wl1271_hw_init(struct wl1271 *wl) if (ret < 0) goto out_free_memmap; + /* disable all keep-alive templates */ + for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { + ret = wl1271_acx_keep_alive_config(wl, i, + ACX_KEEP_ALIVE_TPL_INVALID); + if (ret < 0) + goto out_free_memmap; + } + + /* disable the keep-alive feature */ + ret = wl1271_acx_keep_alive_mode(wl, false); + if (ret < 0) + goto out_free_memmap; + return 0; out_free_memmap: diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index afab52bec134..033cef01fd43 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -264,7 +264,8 @@ static struct conf_drv_settings default_conf = { }, .bet_enable = CONF_BET_MODE_ENABLE, .bet_max_consecutive = 10, - .psm_entry_retries = 3 + .psm_entry_retries = 3, + .keep_alive_interval = 55000 }, .init = { .radioparam = { @@ -1203,6 +1204,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->sta_rate_set = 0; wl1271_acx_rate_policies(wl); + wl1271_acx_keep_alive_config( + wl, CMD_TEMPL_KLV_IDX_NULL_DATA, + ACX_KEEP_ALIVE_TPL_INVALID); } } @@ -1676,7 +1680,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, ret = wl1271_cmd_build_probe_req(wl, NULL, 0, NULL, 0, wl->band); - ret = wl1271_acx_aid(wl, wl->aid); + /* Enable the keep-alive feature */ + ret = wl1271_acx_keep_alive_mode(wl, true); if (ret < 0) goto out_sleep; @@ -1700,6 +1705,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, /* disable connection monitor features */ ret = wl1271_acx_conn_monit_params(wl, false); + + /* Disable the keep-alive feature */ + ret = wl1271_acx_keep_alive_mode(wl, false); + if (ret < 0) goto out_sleep; } @@ -1744,6 +1753,26 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, set_bit(WL1271_FLAG_JOINED, &wl->flags); } + /* + * The JOIN operation shuts down the firmware keep-alive as a side + * effect, and the ACX_AID will start the keep-alive as a side effect. + * Hence, for non-IBSS, the ACX_AID must always happen *after* the + * JOIN operation, and the template config after the ACX_AID. + */ + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { + ret = wl1271_acx_aid(wl, wl->aid); + if (ret < 0) + goto out_sleep; + ret = wl1271_cmd_build_klv_null_data(wl); + if (ret < 0) + goto out_sleep; + ret = wl1271_acx_keep_alive_config( + wl, CMD_TEMPL_KLV_IDX_NULL_DATA, + ACX_KEEP_ALIVE_TPL_VALID); + if (ret < 0) + goto out_sleep; + } + out_sleep: wl1271_ps_elp_sleep(wl); -- cgit v1.2.3 From bc0f03ea579d78f845a44a0c611806da64057b03 Mon Sep 17 00:00:00 2001 From: Saravanan Dhanabal Date: Fri, 26 Mar 2010 12:53:33 +0200 Subject: wl1271: Fix msleep() delay while waiting for completion After last transmission, the device goes to sleep earlier than the configured dynamic power save timeout. If timeout is set to 400ms, device enters into sleep mode at around 330ms since from last TX. This patch removes the msleep(1), which causes the delay after ELP wakeup. Replaced with udelay(10), the variation is around 7-10ms. Signed-off-by: Saravanan Dhanabal Reviewed-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 0cb4cbb00395..f11f9f47ffd5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -36,6 +36,8 @@ #include "wl1271_cmd.h" #include "wl1271_event.h" +#define WL1271_CMD_POLL_COUNT 5 + /* * send command to firmware * @@ -52,6 +54,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, u32 intr; int ret = 0; u16 status; + u16 poll_count = 0; cmd = buf; cmd->id = cpu_to_le16(id); @@ -73,7 +76,11 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, goto out; } - msleep(1); + udelay(10); + poll_count++; + if (poll_count == WL1271_CMD_POLL_COUNT) + wl1271_info("cmd polling took over %d cycles", + poll_count); intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); } -- cgit v1.2.3 From fc3f14873d38a5c8a280ff4b8c8abde0244fb79b Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Sun, 28 Mar 2010 15:52:43 +0200 Subject: wireless: rt2x00: rt2800usb: identify ids-chips Taken from ralink linux drivers: RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x0B05,0x1784)}, /* Asus 3072 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x13D3,0x3305)}, /* AzureWave 3070*/ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x07D1,0x3C16)}, /* D-Link 3070 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x203D,0x14A9)}, /* Encore 3070*/ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x1740,0x9707)}, /* EnGenius 3070 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x1740,0x9708)}, /* EnGenius 3071 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x1740,0x9709)}, /* EnGenius 3072 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x04BB,0x0947)}, /* I-O DATA 3070 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x04BB,0x0948)}, /* I-O DATA 3072 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x0DB0,0x3822)}, /* MSI 3070 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x0DB0,0x3821)}, /* Ralink 3070 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x0DB0,0x3870)}, /* MSI 3070*/ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x0DB0,0x3871)}, /* MSI 3070 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x0DB0,0x821A)}, /* Ralink 3070 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x0DB0,0x822A)}, /* MSI 3070 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x0DB0,0x870A)}, /* MSI 3070*/ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x0DB0,0x871A)}, /* MSI 3070 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x0DB0,0x899A)}, /* MSI 3070*/ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x20B8,0x8888)}, /* PARA INDUSTRIAL 3070 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x0DF6,0x0048)}, /* Sitecom 3070 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x0DF6,0x0047)}, /* Sitecom 3071 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x083A,0xA701)}, /* SMC 3070 */ RT3070_LinuxSTA_V2.3.0.1_20100208/common/rtusb_dev_id.c: {USB_DEVICE(0x083A,0xA702)}, /* SMC 3072 */ Signed-off-by: Xose Vazquez Perez Acked-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 52 ++++++++++++++++----------------- 1 file changed, 25 insertions(+), 27 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 5e4ee2023fcf..7b2fe98fb3df 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -905,8 +905,11 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, /* AirTies */ { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* ASUS */ + { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, /* AzureWave */ { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Conceptronic */ { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Corega */ @@ -916,20 +919,38 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Edimax */ { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Encore */ { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, /* EnGenius */ { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Gigabyte */ { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, /* I-O DATA */ { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, /* MSI */ { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Para */ + { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Pegatron */ { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -945,8 +966,12 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Sitecom */ { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, /* SMC */ { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zinwell */ { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -990,13 +1015,11 @@ static struct usb_device_id rt2800usb_device_table[] = { /* ASUS */ { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) }, /* AzureWave */ { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Belkin */ { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Buffalo */ @@ -1015,14 +1038,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Encore */ { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* EnGenius */ - { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Gemtek */ { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Gigabyte */ @@ -1030,9 +1047,6 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Hawking */ { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* I-O DATA */ - { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, /* LevelOne */ { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -1042,20 +1056,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Motorola */ { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* MSI */ - { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Ovislink */ { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Para */ - { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Pegatron */ { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -1069,14 +1071,10 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) }, /* SMC */ { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sweex */ -- cgit v1.2.3 From 27427013504d98f86f9baebfb8a44db3ce61f65e Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Sun, 28 Mar 2010 16:57:32 +0200 Subject: wireless: rt2x00: rt2800usb: delete id It was removed in the windows inf file by ralink. And it isn't on ralink linux drivers. Signed-off-by: Xose Vazquez Perez Acked-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 7b2fe98fb3df..82aac6b74def 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1010,8 +1010,6 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Amigo */ { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Askey */ - { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, /* ASUS */ { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, -- cgit v1.2.3 From 6424bf700c1851fc7e86b83959a8578a401d80c1 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Sun, 28 Mar 2010 17:48:05 +0200 Subject: wireless: rt2x00: rt2800pci: new id Taken from latest ralink linux driver, it's a RT3593 PCI/PCIe. Signed-off-by: Xose Vazquez Perez Acked-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index b1f5643f83fc..ce7e88ecbb00 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1212,6 +1212,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3593), PCI_DEVICE_DATA(&rt2800pci_ops) }, #endif { 0, } }; -- cgit v1.2.3 From f01a0229b0343d56b2e084f1472ff3edc1a2090b Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Sun, 28 Mar 2010 20:02:41 +0200 Subject: wireless: rt2x00: rt2800usb: new ids Taken from latest ralink linux driver(RT3070_LinuxSTA_V2.3.0.1_20100208) All of them are RT3070 devices. Signed-off-by: Xose Vazquez Perez Acked-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 82aac6b74def..39877880869a 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -910,6 +910,8 @@ static struct usb_device_id rt2800usb_device_table[] = { /* AzureWave */ { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Conceptronic */ { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Corega */ @@ -920,6 +922,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Draytek */ + { USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Edimax */ { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Encore */ @@ -938,6 +942,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Logitec */ + { USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) }, /* MSI */ { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -946,8 +952,12 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Para */ { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -972,6 +982,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zinwell */ { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, -- cgit v1.2.3 From d817f4e18cf54ae7d662cf2f33e51685e81ad254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 29 Mar 2010 00:53:12 +0200 Subject: b43: N-PHY: some dummy PHY rev 3 calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 6fd140ac7f9e..05866675015e 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -253,6 +253,16 @@ static void b43_radio_init2055(struct b43_wldev *dev) b43_radio_init2055_post(dev); } +/* + * Initialize a Broadcom 2056 N-radio + * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init + */ +static void b43_radio_init2056(struct b43_wldev *dev) +{ + /* TODO */ +} + + /* * Upload the N-PHY tables. * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables @@ -3473,6 +3483,8 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, bool blocked) { + struct b43_phy_n *nphy = dev->phy.n; + if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) b43err(dev->wl, "MAC not suspended\n"); @@ -3498,8 +3510,8 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, } } else { if (dev->phy.rev >= 3) { - /* TODO: b43_radio_init2056(dev); */ - /* TODO: PHY Set Channel Spec (dev, radio_chanspec) */ + b43_radio_init2056(dev); + b43_nphy_set_chanspec(dev, nphy->radio_chanspec); } else { b43_radio_init2055(dev); } -- cgit v1.2.3 From b15b3039919c7357c2851ec66843ff92f8ff86aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 29 Mar 2010 00:53:13 +0200 Subject: b43: N-PHY: use b43_phy_n_sfo_cfg rather than duplicating same fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 6 +++--- drivers/net/wireless/b43/tables_nphy.c | 12 ++++++------ drivers/net/wireless/b43/tables_nphy.h | 15 +++++---------- 3 files changed, 14 insertions(+), 19 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 05866675015e..052119b84da4 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -141,7 +141,7 @@ static void b43_chantab_radio_upload(struct b43_wldev *dev, } static void b43_chantab_phy_upload(struct b43_wldev *dev, - const struct b43_nphy_channeltab_entry *e) + const struct b43_phy_n_sfo_cfg *e) { b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a); b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2); @@ -3270,7 +3270,7 @@ int b43_phy_initn(struct b43_wldev *dev) /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ static void b43_nphy_chanspec_setup(struct b43_wldev *dev, - const struct b43_nphy_channeltab_entry *e, + const struct b43_phy_n_sfo_cfg *e, struct b43_chanspec chanspec) { struct b43_phy *phy = &dev->phy; @@ -3373,7 +3373,7 @@ static int b43_nphy_set_chanspec(struct b43_wldev *dev, tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050; b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp); b43_radio_2055_setup(dev, tabent); - b43_nphy_chanspec_setup(dev, tabent, chanspec); + b43_nphy_chanspec_setup(dev, &(tabent->phy_regs), chanspec); } return 0; diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index a00d509150f7..237426d64ad4 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -318,12 +318,12 @@ void b2055_upload_inittab(struct b43_wldev *dev, .radio_c2_tx_mxbgtrim = r21 #define PHYREGS(r0, r1, r2, r3, r4, r5) \ - .phy_bw1a = r0, \ - .phy_bw2 = r1, \ - .phy_bw3 = r2, \ - .phy_bw4 = r3, \ - .phy_bw5 = r4, \ - .phy_bw6 = r5 + .phy_regs.phy_bw1a = r0, \ + .phy_regs.phy_bw2 = r1, \ + .phy_regs.phy_bw3 = r2, \ + .phy_regs.phy_bw4 = r3, \ + .phy_regs.phy_bw5 = r4, \ + .phy_regs.phy_bw6 = r5 static const struct b43_nphy_channeltab_entry b43_nphy_channeltab[] = { { .channel = 184, diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index b23036f7dc19..84dea356d856 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -16,6 +16,10 @@ struct b43_phy_n_sfo_cfg { struct b43_nphy_channeltab_entry { /* The channel number */ u8 channel; + /* The channel frequency in MHz */ + u16 freq; + /* An unknown value */ + u16 unk2; /* Radio register values on channelswitch */ u8 radio_pll_ref; u8 radio_rf_pllmod0; @@ -40,16 +44,7 @@ struct b43_nphy_channeltab_entry { u8 radio_c2_tx_pgapadtn; u8 radio_c2_tx_mxbgtrim; /* PHY register values on channelswitch */ - u16 phy_bw1a; - u16 phy_bw2; - u16 phy_bw3; - u16 phy_bw4; - u16 phy_bw5; - u16 phy_bw6; - /* The channel frequency in MHz */ - u16 freq; - /* An unknown value */ - u16 unk2; + struct b43_phy_n_sfo_cfg phy_regs; }; -- cgit v1.2.3 From ffd2d9bdac1a0a5d3184e085ea1bd3060b4166fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 29 Mar 2010 00:53:14 +0200 Subject: b43: N-PHY: find table entry earlier for setting chanspec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We do not want to partially change chanspec just to find out there is not entry in table for given channel. Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 052119b84da4..d9e47ba5e157 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -3343,6 +3343,10 @@ static int b43_nphy_set_chanspec(struct b43_wldev *dev, if (dev->phy.rev >= 3) { /* TODO */ + } else { + tabent = b43_nphy_get_chantabent(dev, channel); + if (!tabent) + return -ESRCH; } nphy->radio_chanspec = chanspec; @@ -3366,10 +3370,6 @@ static int b43_nphy_set_chanspec(struct b43_wldev *dev, /* TODO: PHY Radio2056 Setup (chan_info_ptr[i]) */ /* TODO: N PHY Chanspec Setup (chan_info_ptr[i]) */ } else { - tabent = b43_nphy_get_chantabent(dev, channel); - if (!tabent) - return -ESRCH; - tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050; b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp); b43_radio_2055_setup(dev, tabent); -- cgit v1.2.3 From f19ebe7d772a3b48743fa798ad979a4ee3cb64e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 29 Mar 2010 00:53:15 +0200 Subject: b43: N-PHY: prepare for rev3+ channel tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 22 +++++++++++++--------- drivers/net/wireless/b43/tables_nphy.c | 8 ++++---- drivers/net/wireless/b43/tables_nphy.h | 17 ++++++++++++++--- 3 files changed, 31 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index d9e47ba5e157..34f80c452f72 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -104,7 +104,7 @@ static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev, } static void b43_chantab_radio_upload(struct b43_wldev *dev, - const struct b43_nphy_channeltab_entry *e) + const struct b43_nphy_channeltab_entry_rev2 *e) { b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref); b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); @@ -159,7 +159,7 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) /* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */ static void b43_radio_2055_setup(struct b43_wldev *dev, - const struct b43_nphy_channeltab_entry *e) + const struct b43_nphy_channeltab_entry_rev2 *e) { B43_WARN_ON(dev->phy.rev >= 3); @@ -3336,16 +3336,20 @@ static int b43_nphy_set_chanspec(struct b43_wldev *dev, { struct b43_phy_n *nphy = dev->phy.n; - const struct b43_nphy_channeltab_entry *tabent; + const struct b43_nphy_channeltab_entry_rev2 *tabent_r2; + const struct b43_nphy_channeltab_entry_rev3 *tabent_r3; u8 tmp; u8 channel = chanspec.channel; if (dev->phy.rev >= 3) { /* TODO */ + tabent_r3 = NULL; + if (!tabent_r3) + return -ESRCH; } else { - tabent = b43_nphy_get_chantabent(dev, channel); - if (!tabent) + tabent_r2 = b43_nphy_get_chantabent_rev2(dev, channel); + if (!tabent_r2) return -ESRCH; } @@ -3367,13 +3371,13 @@ static int b43_nphy_set_chanspec(struct b43_wldev *dev, if (dev->phy.rev >= 3) { tmp = (chanspec.b_freq == 1) ? 4 : 0; b43_radio_maskset(dev, 0x08, 0xFFFB, tmp); - /* TODO: PHY Radio2056 Setup (chan_info_ptr[i]) */ - /* TODO: N PHY Chanspec Setup (chan_info_ptr[i]) */ + /* TODO: PHY Radio2056 Setup (dev, tabent_r3); */ + b43_nphy_chanspec_setup(dev, &(tabent_r3->phy_regs), chanspec); } else { tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050; b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp); - b43_radio_2055_setup(dev, tabent); - b43_nphy_chanspec_setup(dev, &(tabent->phy_regs), chanspec); + b43_radio_2055_setup(dev, tabent_r2); + b43_nphy_chanspec_setup(dev, &(tabent_r2->phy_regs), chanspec); } return 0; diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index 237426d64ad4..d96e870ab8fe 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -325,7 +325,7 @@ void b2055_upload_inittab(struct b43_wldev *dev, .phy_regs.phy_bw5 = r4, \ .phy_regs.phy_bw6 = r5 -static const struct b43_nphy_channeltab_entry b43_nphy_channeltab[] = { +static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab[] = { { .channel = 184, .freq = 4920, /* MHz */ .unk2 = 3280, @@ -1320,10 +1320,10 @@ static const struct b43_nphy_channeltab_entry b43_nphy_channeltab[] = { }, }; -const struct b43_nphy_channeltab_entry * -b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel) +const struct b43_nphy_channeltab_entry_rev2 * +b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel) { - const struct b43_nphy_channeltab_entry *e; + const struct b43_nphy_channeltab_entry_rev2 *e; unsigned int i; for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab); i++) { diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 84dea356d856..8fc1da9f8fe5 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -13,7 +13,7 @@ struct b43_phy_n_sfo_cfg { u16 phy_bw6; }; -struct b43_nphy_channeltab_entry { +struct b43_nphy_channeltab_entry_rev2 { /* The channel number */ u8 channel; /* The channel frequency in MHz */ @@ -47,6 +47,17 @@ struct b43_nphy_channeltab_entry { struct b43_phy_n_sfo_cfg phy_regs; }; +struct b43_nphy_channeltab_entry_rev3 { + /* The channel number */ + u8 channel; + /* The channel frequency in MHz */ + u16 freq; + /* Radio register values on channelswitch */ + /* TODO */ + /* PHY register values on channelswitch */ + struct b43_phy_n_sfo_cfg phy_regs; +}; + struct b43_wldev; @@ -81,8 +92,8 @@ void b2055_upload_inittab(struct b43_wldev *dev, /* Get the NPHY Channel Switch Table entry for a channel number. * Returns NULL on failure to find an entry. */ -const struct b43_nphy_channeltab_entry * -b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel); +const struct b43_nphy_channeltab_entry_rev2 * +b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel); /* The N-PHY tables. */ -- cgit v1.2.3 From e58b1253f1e850b4469964d7b92cf230196223c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 29 Mar 2010 00:53:16 +0200 Subject: b43: N-PHY: fix value written on 2055 radio setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 34f80c452f72..1ae232c25093 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -165,10 +165,10 @@ static void b43_radio_2055_setup(struct b43_wldev *dev, b43_chantab_radio_upload(dev, e); udelay(50); - b43_radio_write(dev, B2055_VCO_CAL10, 5); - b43_radio_write(dev, B2055_VCO_CAL10, 45); + b43_radio_write(dev, B2055_VCO_CAL10, 0x05); + b43_radio_write(dev, B2055_VCO_CAL10, 0x45); b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ - b43_radio_write(dev, B2055_VCO_CAL10, 65); + b43_radio_write(dev, B2055_VCO_CAL10, 0x65); udelay(300); } -- cgit v1.2.3 From ecdf94b81237d272b1514b76f27a5d22782bcaa6 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 29 Mar 2010 16:42:26 +0800 Subject: iwlwifi: remove skb_linearize for rx frames Remove skb_linearize() in the iwlwifi drivers since mac80211 supports paged rx SKBs now. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 29 ++------------------------- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 32 ++---------------------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 7 ------- 3 files changed, 4 insertions(+), 64 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 6b7201551ca7..2c16c5c10bc5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -548,7 +548,6 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); u16 len = le16_to_cpu(rx_hdr->len); struct sk_buff *skb; - int ret; __le16 fc = hdr->frame_control; /* We received data from the HW, so stop the watchdog */ @@ -565,9 +564,9 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, return; } - skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); + skb = dev_alloc_skb(128); if (!skb) { - IWL_ERR(priv, "alloc_skb failed\n"); + IWL_ERR(priv, "dev_alloc_skb failed\n"); return; } @@ -576,37 +575,13 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, (struct ieee80211_hdr *)rxb_addr(rxb), le32_to_cpu(rx_end->status), stats); - skb_reserve(skb, IWL_LINK_HDR_MAX); skb_add_rx_frag(skb, 0, rxb->page, (void *)rx_hdr->payload - (void *)pkt, len); - /* mac80211 currently doesn't support paged SKB. Convert it to - * linear SKB for management frame and data frame requires - * software decryption or software defragementation. */ - if (ieee80211_is_mgmt(fc) || - ieee80211_has_protected(fc) || - ieee80211_has_morefrags(fc) || - le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) - ret = skb_linearize(skb); - else - ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? - 0 : -ENOMEM; - - if (ret) { - kfree_skb(skb); - goto out; - } - - /* - * XXX: We cannot touch the page and its virtual memory (pkt) after - * here. It might have already been freed by the above skb change. - */ - iwl_update_stats(priv, false, fc, len); memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); ieee80211_rx(priv->hw, skb); - out: priv->alloc_rxb_page--; rxb->page = NULL; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index e8e3118ec0ad..1d2e84c1fad5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -931,7 +931,6 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, struct ieee80211_rx_status *stats) { struct sk_buff *skb; - int ret = 0; __le16 fc = hdr->frame_control; /* We only process data packets if the interface is open */ @@ -946,45 +945,18 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) return; - skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); + skb = dev_alloc_skb(128); if (!skb) { - IWL_ERR(priv, "alloc_skb failed\n"); + IWL_ERR(priv, "dev_alloc_skb failed\n"); return; } - skb_reserve(skb, IWL_LINK_HDR_MAX); skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); - /* mac80211 currently doesn't support paged SKB. Convert it to - * linear SKB for management frame and data frame requires - * software decryption or software defragementation. */ - if (ieee80211_is_mgmt(fc) || - ieee80211_has_protected(fc) || - ieee80211_has_morefrags(fc) || - le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG || - (ieee80211_is_data_qos(fc) && - *ieee80211_get_qos_ctl(hdr) & - IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)) - ret = skb_linearize(skb); - else - ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? - 0 : -ENOMEM; - - if (ret) { - kfree_skb(skb); - goto out; - } - - /* - * XXX: We cannot touch the page and its virtual memory (hdr) after - * here. It might have already been freed by the above skb change. - */ - iwl_update_stats(priv, false, fc, len); memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); ieee80211_rx(priv->hw, skb); - out: priv->alloc_rxb_page--; rxb->page = NULL; } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index bff182ffeac9..46a574080160 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -325,13 +325,6 @@ enum { #define DEF_CMD_PAYLOAD_SIZE 320 -/* - * IWL_LINK_HDR_MAX should include ieee80211_hdr, radiotap header, - * SNAP header and alignment. It should also be big enough for 802.11 - * control frames. - */ -#define IWL_LINK_HDR_MAX 64 - /** * struct iwl_device_cmd * -- cgit v1.2.3 From e61146e36b40fd9d346118c40285913236c329f3 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 29 Mar 2010 12:18:35 +0200 Subject: iwlwifi: manage QoS by mac stack We activate/deactivate QoS and setup default queue parameters in iwlwifi driver. Mac stack do the same, so we do not need repeat that work here. Stack also will tell when disable QoS, this will fix driver when working with older APs, that do not have QoS implemented. Patch make "force = true" in iwl_active_qos() assuming we always want to do with QoS what mac stack wish. Patch also remove unused qos_cap bits, do not initialize qos_active = 0, as we have it initialized to zero by kzalloc. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 15 --- drivers/net/wireless/iwlwifi/iwl-core.c | 142 ++++------------------------ drivers/net/wireless/iwlwifi/iwl-core.h | 3 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 21 ---- drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 -- 5 files changed, 17 insertions(+), 171 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3f0fd755a609..b431e9254c06 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2531,7 +2531,6 @@ void iwl_post_associate(struct iwl_priv *priv) { struct ieee80211_conf *conf = NULL; int ret = 0; - unsigned long flags; if (priv->iw_mode == NL80211_IFTYPE_AP) { IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); @@ -2612,10 +2611,6 @@ void iwl_post_associate(struct iwl_priv *priv) break; } - spin_lock_irqsave(&priv->lock, flags); - iwl_activate_qos(priv, 0); - spin_unlock_irqrestore(&priv->lock, flags); - /* the chain noise calibration will enabled PM upon completion * If chain noise has already been run, then we need to enable * power management here */ @@ -2792,7 +2787,6 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) void iwl_config_ap(struct iwl_priv *priv) { int ret = 0; - unsigned long flags; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -2844,10 +2838,6 @@ void iwl_config_ap(struct iwl_priv *priv) /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv); - iwl_reset_qos(priv); - spin_lock_irqsave(&priv->lock, flags); - iwl_activate_qos(priv, 1); - spin_unlock_irqrestore(&priv->lock, flags); iwl_add_bcast_station(priv); } iwl_send_beacon_cmd(priv); @@ -3382,11 +3372,6 @@ static int iwl_init_drv(struct iwl_priv *priv) iwl_init_scan_params(priv); - iwl_reset_qos(priv); - - priv->qos_data.qos_active = 0; - priv->qos_data.qos_cap.val = 0; - /* Set the tx_power_user_lmt to the lowest power level * this value will get overwritten by channel max power avg * from eeprom */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 1b4408a31bff..38d19c11c47e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -223,17 +223,13 @@ EXPORT_SYMBOL(iwl_hw_detect); /* * QoS support */ -void iwl_activate_qos(struct iwl_priv *priv, u8 force) +static void iwl_update_qos(struct iwl_priv *priv) { if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; priv->qos_data.def_qos_parm.qos_flags = 0; - if (priv->qos_data.qos_cap.q_AP.queue_request && - !priv->qos_data.qos_cap.q_AP.txop_request) - priv->qos_data.def_qos_parm.qos_flags |= - QOS_PARAM_FLG_TXOP_TYPE_MSK; if (priv->qos_data.qos_active) priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_UPDATE_EDCA_MSK; @@ -241,118 +237,14 @@ void iwl_activate_qos(struct iwl_priv *priv, u8 force) if (priv->current_ht_config.is_ht) priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; - if (force || iwl_is_associated(priv)) { - IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", - priv->qos_data.qos_active, - priv->qos_data.def_qos_parm.qos_flags); + IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", + priv->qos_data.qos_active, + priv->qos_data.def_qos_parm.qos_flags); - iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM, - sizeof(struct iwl_qosparam_cmd), - &priv->qos_data.def_qos_parm, NULL); - } + iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM, + sizeof(struct iwl_qosparam_cmd), + &priv->qos_data.def_qos_parm, NULL); } -EXPORT_SYMBOL(iwl_activate_qos); - -/* - * AC CWmin CW max AIFSN TXOP Limit TXOP Limit - * (802.11b) (802.11a/g) - * AC_BK 15 1023 7 0 0 - * AC_BE 15 1023 3 0 0 - * AC_VI 7 15 2 6.016ms 3.008ms - * AC_VO 3 7 2 3.264ms 1.504ms - */ -void iwl_reset_qos(struct iwl_priv *priv) -{ - u16 cw_min = 15; - u16 cw_max = 1023; - u8 aifs = 2; - bool is_legacy = false; - unsigned long flags; - int i; - - spin_lock_irqsave(&priv->lock, flags); - /* QoS always active in AP and ADHOC mode - * In STA mode wait for association - */ - if (priv->iw_mode == NL80211_IFTYPE_ADHOC || - priv->iw_mode == NL80211_IFTYPE_AP) - priv->qos_data.qos_active = 1; - else - priv->qos_data.qos_active = 0; - - /* check for legacy mode */ - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC && - (priv->active_rate & IWL_OFDM_RATES_MASK) == 0) || - (priv->iw_mode == NL80211_IFTYPE_STATION && - (priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK) == 0)) { - cw_min = 31; - is_legacy = 1; - } - - if (priv->qos_data.qos_active) - aifs = 3; - - /* AC_BE */ - priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min); - priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max); - priv->qos_data.def_qos_parm.ac[0].aifsn = aifs; - priv->qos_data.def_qos_parm.ac[0].edca_txop = 0; - priv->qos_data.def_qos_parm.ac[0].reserved1 = 0; - - if (priv->qos_data.qos_active) { - /* AC_BK */ - i = 1; - priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min); - priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max); - priv->qos_data.def_qos_parm.ac[i].aifsn = 7; - priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - - /* AC_VI */ - i = 2; - priv->qos_data.def_qos_parm.ac[i].cw_min = - cpu_to_le16((cw_min + 1) / 2 - 1); - priv->qos_data.def_qos_parm.ac[i].cw_max = - cpu_to_le16(cw_min); - priv->qos_data.def_qos_parm.ac[i].aifsn = 2; - if (is_legacy) - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(6016); - else - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(3008); - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - - /* AC_VO */ - i = 3; - priv->qos_data.def_qos_parm.ac[i].cw_min = - cpu_to_le16((cw_min + 1) / 4 - 1); - priv->qos_data.def_qos_parm.ac[i].cw_max = - cpu_to_le16((cw_min + 1) / 2 - 1); - priv->qos_data.def_qos_parm.ac[i].aifsn = 2; - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - if (is_legacy) - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(3264); - else - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(1504); - } else { - for (i = 1; i < 4; i++) { - priv->qos_data.def_qos_parm.ac[i].cw_min = - cpu_to_le16(cw_min); - priv->qos_data.def_qos_parm.ac[i].cw_max = - cpu_to_le16(cw_max); - priv->qos_data.def_qos_parm.ac[i].aifsn = aifs; - priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - } - } - IWL_DEBUG_QOS(priv, "set QoS to default \n"); - - spin_unlock_irqrestore(&priv->lock, flags); -} -EXPORT_SYMBOL(iwl_reset_qos); #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ @@ -1894,12 +1786,6 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, cpu_to_le16((params->txop * 32)); priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; - priv->qos_data.qos_active = 1; - - if (priv->iw_mode == NL80211_IFTYPE_AP) - iwl_activate_qos(priv, 1); - else if (priv->assoc_id && iwl_is_associated(priv)) - iwl_activate_qos(priv, 0); spin_unlock_irqrestore(&priv->lock, flags); @@ -2170,11 +2056,8 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) IWL_DEBUG_MAC80211(priv, "leave\n"); spin_unlock_irqrestore(&priv->lock, flags); - iwl_reset_qos(priv); - priv->cfg->ops->lib->post_associate(priv); - return 0; } EXPORT_SYMBOL(iwl_mac_beacon_update); @@ -2396,6 +2279,15 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) iwl_set_tx_power(priv, conf->power_level, false); } + if (changed & IEEE80211_CONF_CHANGE_QOS) { + bool qos_active = !!(conf->flags & IEEE80211_CONF_QOS); + + spin_lock_irqsave(&priv->lock, flags); + priv->qos_data.qos_active = qos_active; + iwl_update_qos(priv); + spin_unlock_irqrestore(&priv->lock, flags); + } + if (!iwl_is_ready(priv)) { IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); goto out; @@ -2430,8 +2322,6 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config)); spin_unlock_irqrestore(&priv->lock, flags); - iwl_reset_qos(priv); - spin_lock_irqsave(&priv->lock, flags); priv->assoc_id = 0; priv->assoc_capability = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 9d7a68f07882..bc04b43cad36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -316,8 +316,7 @@ struct iwl_cfg { struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, struct ieee80211_ops *hw_ops); void iwl_hw_detect(struct iwl_priv *priv); -void iwl_reset_qos(struct iwl_priv *priv); -void iwl_activate_qos(struct iwl_priv *priv, u8 force); +void iwl_activate_qos(struct iwl_priv *priv); int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 46a574080160..7f38d2d9b575 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -476,30 +476,9 @@ struct iwl_ht_config { u8 non_GF_STA_present; }; -union iwl_qos_capabity { - struct { - u8 edca_count:4; /* bit 0-3 */ - u8 q_ack:1; /* bit 4 */ - u8 queue_request:1; /* bit 5 */ - u8 txop_request:1; /* bit 6 */ - u8 reserved:1; /* bit 7 */ - } q_AP; - struct { - u8 acvo_APSD:1; /* bit 0 */ - u8 acvi_APSD:1; /* bit 1 */ - u8 ac_bk_APSD:1; /* bit 2 */ - u8 ac_be_APSD:1; /* bit 3 */ - u8 q_ack:1; /* bit 4 */ - u8 max_len:2; /* bit 5-6 */ - u8 more_data_ack:1; /* bit 7 */ - } q_STA; - u8 val; -}; - /* QoS structures */ struct iwl_qos_info { int qos_active; - union iwl_qos_capabity qos_cap; struct iwl_qosparam_cmd def_qos_parm; }; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4995134d7e4a..24c240d53f5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3140,8 +3140,6 @@ void iwl3945_post_associate(struct iwl_priv *priv) break; } - iwl_activate_qos(priv, 0); - /* we have just associated, don't start scan too early */ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; } @@ -3889,11 +3887,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) priv->iw_mode = NL80211_IFTYPE_STATION; priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; - iwl_reset_qos(priv); - - priv->qos_data.qos_active = 0; - priv->qos_data.qos_cap.val = 0; - priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { -- cgit v1.2.3 From 0995d110118b35c0dc5195e3ddddcc0dec263830 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 29 Mar 2010 16:07:09 +0530 Subject: ath9k_common: Move RX filter code to ath9k_htc The calculation of RX filter is fairly different between ath9k and ath9k_htc, trying to make this common between the two drivers would result in code churn. While at it, remove the handling of PSPOLL filter, it can be added when(if) AP support is added to ath9k_htc. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/common.c | 82 --------------------------- drivers/net/wireless/ath/ath9k/common.h | 4 -- drivers/net/wireless/ath/ath9k/htc.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 76 ++++++++++++++++++++++++- 5 files changed, 77 insertions(+), 88 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 7902d287f671..cf768f2811eb 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -303,88 +303,6 @@ int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) } EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); -/* - * Calculate the RX filter to be set in the HW. - */ -u32 ath9k_cmn_calcrxfilter(struct ieee80211_hw *hw, struct ath_hw *ah, - unsigned int rxfilter) -{ -#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) - - u32 rfilt; - - rfilt = (ath9k_hw_getrxfilter(ah) & RX_FILTER_PRESERVE) - | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST - | ATH9K_RX_FILTER_MCAST; - - /* If not a STA, enable processing of Probe Requests */ - if (ah->opmode != NL80211_IFTYPE_STATION) - rfilt |= ATH9K_RX_FILTER_PROBEREQ; - - /* - * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station - * mode interface or when in monitor mode. AP mode does not need this - * since it receives all in-BSS frames anyway. - */ - if (((ah->opmode != NL80211_IFTYPE_AP) && - (rxfilter & FIF_PROMISC_IN_BSS)) || - (ah->opmode == NL80211_IFTYPE_MONITOR)) - rfilt |= ATH9K_RX_FILTER_PROM; - - if (rxfilter & FIF_CONTROL) - rfilt |= ATH9K_RX_FILTER_CONTROL; - - if ((ah->opmode == NL80211_IFTYPE_STATION) && - !(rxfilter & FIF_BCN_PRBRESP_PROMISC)) - rfilt |= ATH9K_RX_FILTER_MYBEACON; - else - rfilt |= ATH9K_RX_FILTER_BEACON; - - if ((AR_SREV_9280_10_OR_LATER(ah) || - AR_SREV_9285_10_OR_LATER(ah)) && - (ah->opmode == NL80211_IFTYPE_AP) && - (rxfilter & FIF_PSPOLL)) - rfilt |= ATH9K_RX_FILTER_PSPOLL; - - if (conf_is_ht(&hw->conf)) - rfilt |= ATH9K_RX_FILTER_COMP_BAR; - - return rfilt; - -#undef RX_FILTER_PRESERVE -} -EXPORT_SYMBOL(ath9k_cmn_calcrxfilter); - -/* - * Recv initialization for opmode change. - */ -void ath9k_cmn_opmode_init(struct ieee80211_hw *hw, struct ath_hw *ah, - unsigned int rxfilter) -{ - struct ath_common *common = ath9k_hw_common(ah); - - u32 rfilt, mfilt[2]; - - /* configure rx filter */ - rfilt = ath9k_cmn_calcrxfilter(hw, ah, rxfilter); - ath9k_hw_setrxfilter(ah, rfilt); - - /* configure bssid mask */ - if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) - ath_hw_setbssidmask(common); - - /* configure operational mode */ - ath9k_hw_setopmode(ah); - - /* Handle any link-level address change. */ - ath9k_hw_setmac(ah, common->macaddr); - - /* calculate and install multicast filter */ - mfilt[0] = mfilt[1] = ~0; - ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); -} -EXPORT_SYMBOL(ath9k_cmn_opmode_init); - static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) { diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index bbcc57f6eba3..72a835d9e97f 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -128,10 +128,6 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, int ath9k_cmn_padpos(__le16 frame_control); int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); -u32 ath9k_cmn_calcrxfilter(struct ieee80211_hw *hw, struct ath_hw *ah, - unsigned int rxfilter); -void ath9k_cmn_opmode_init(struct ieee80211_hw *hw, struct ath_hw *ah, - unsigned int rxfilter); void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, struct ath9k_channel *ichan); struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 777064945fca..698e6f1a506a 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -415,6 +415,7 @@ int ath9k_rx_init(struct ath9k_htc_priv *priv); void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); void ath9k_host_rx_init(struct ath9k_htc_priv *priv); void ath9k_rx_tasklet(unsigned long data); +u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv); void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); void ath9k_init_leds(struct ath9k_htc_priv *priv); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 20a2c1341e20..e5f78c7b2b1f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1299,7 +1299,7 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, *total_flags &= SUPPORTED_FILTERS; priv->rxfilter = *total_flags; - rfilt = ath9k_cmn_calcrxfilter(hw, priv->ah, priv->rxfilter); + rfilt = ath9k_htc_calcrxfilter(priv); ath9k_hw_setrxfilter(priv->ah, rfilt); ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index ac66cf0b2d53..94e299fabbb2 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -290,10 +290,84 @@ bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, /* RX */ /******/ +/* + * Calculate the RX filter to be set in the HW. + */ +u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) +{ +#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) + + struct ath_hw *ah = priv->ah; + u32 rfilt; + + rfilt = (ath9k_hw_getrxfilter(ah) & RX_FILTER_PRESERVE) + | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST + | ATH9K_RX_FILTER_MCAST; + + /* If not a STA, enable processing of Probe Requests */ + if (ah->opmode != NL80211_IFTYPE_STATION) + rfilt |= ATH9K_RX_FILTER_PROBEREQ; + + /* + * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station + * mode interface or when in monitor mode. AP mode does not need this + * since it receives all in-BSS frames anyway. + */ + if (((ah->opmode != NL80211_IFTYPE_AP) && + (priv->rxfilter & FIF_PROMISC_IN_BSS)) || + (ah->opmode == NL80211_IFTYPE_MONITOR)) + rfilt |= ATH9K_RX_FILTER_PROM; + + if (priv->rxfilter & FIF_CONTROL) + rfilt |= ATH9K_RX_FILTER_CONTROL; + + if ((ah->opmode == NL80211_IFTYPE_STATION) && + !(priv->rxfilter & FIF_BCN_PRBRESP_PROMISC)) + rfilt |= ATH9K_RX_FILTER_MYBEACON; + else + rfilt |= ATH9K_RX_FILTER_BEACON; + + if (conf_is_ht(&priv->hw->conf)) + rfilt |= ATH9K_RX_FILTER_COMP_BAR; + + return rfilt; + +#undef RX_FILTER_PRESERVE +} + +/* + * Recv initialization for opmode change. + */ +static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv) +{ + struct ath_hw *ah = priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + + u32 rfilt, mfilt[2]; + + /* configure rx filter */ + rfilt = ath9k_htc_calcrxfilter(priv); + ath9k_hw_setrxfilter(ah, rfilt); + + /* configure bssid mask */ + if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) + ath_hw_setbssidmask(common); + + /* configure operational mode */ + ath9k_hw_setopmode(ah); + + /* Handle any link-level address change. */ + ath9k_hw_setmac(ah, common->macaddr); + + /* calculate and install multicast filter */ + mfilt[0] = mfilt[1] = ~0; + ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); +} + void ath9k_host_rx_init(struct ath9k_htc_priv *priv) { ath9k_hw_rxena(priv->ah); - ath9k_cmn_opmode_init(priv->hw, priv->ah, priv->rxfilter); + ath9k_htc_opmode_init(priv); ath9k_hw_startpcureceive(priv->ah); priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER; } -- cgit v1.2.3 From ef98c3cd9b68ed27eeb94b833f74860fa1a734b7 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 29 Mar 2010 16:07:11 +0530 Subject: ath9k_htc: Fix bug in aggregation initiation Accessing the sta pointer in TX completion without approprate RCU protection is wrong. Fix this. Also, RCU protection is needed when the station's aggregation state is updated. Handle this properly. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 25 ++++++++++++------------- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index e5f78c7b2b1f..90b13ed1ae4c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -412,32 +412,31 @@ static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, if (tid > ATH9K_HTC_MAX_TID) return -EINVAL; + memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); + rcu_read_lock(); + + /* Check if we are able to retrieve the station */ sta = ieee80211_find_sta(vif, sta_addr); - if (sta) { - ista = (struct ath9k_htc_sta *) sta->drv_priv; - } else { + if (!sta) { rcu_read_unlock(); return -EINVAL; } - if (!ista) { - rcu_read_unlock(); - return -EINVAL; - } + ista = (struct ath9k_htc_sta *) sta->drv_priv; - memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); + if (oper) + ista->tid_state[tid] = AGGR_START; + else + ista->tid_state[tid] = AGGR_STOP; aggr.sta_index = ista->index; + rcu_read_unlock(); + aggr.tidno = tid; aggr.aggr_enable = oper; - if (oper) - ista->tid_state[tid] = AGGR_START; - else - ista->tid_state[tid] = AGGR_STOP; - WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); if (ret) ath_print(common, ATH_DBG_CONFIG, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 94e299fabbb2..838365607aa5 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -188,10 +188,20 @@ void ath9k_tx_tasklet(unsigned long data) hdr = (struct ieee80211_hdr *) skb->data; fc = hdr->frame_control; tx_info = IEEE80211_SKB_CB(skb); - sta = tx_info->control.sta; + + memset(&tx_info->status, 0, sizeof(tx_info->status)); rcu_read_lock(); + sta = ieee80211_find_sta(priv->vif, hdr->addr1); + if (!sta) { + rcu_read_unlock(); + ieee80211_tx_status(priv->hw, skb); + continue; + } + + /* Check if we need to start aggregation */ + if (sta && conf_is_ht(&priv->hw->conf) && (priv->op_flags & OP_TXAGGR) && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { @@ -213,7 +223,7 @@ void ath9k_tx_tasklet(unsigned long data) rcu_read_unlock(); - memset(&tx_info->status, 0, sizeof(tx_info->status)); + /* Send status to mac80211 */ ieee80211_tx_status(priv->hw, skb); } } -- cgit v1.2.3 From d5a4c5e3afb9697c8f627b2563f4b8583ef88498 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 29 Mar 2010 16:07:14 +0530 Subject: ath9k_htc: Fix watchdog pattern parsing Skip beyond the watchdog pattern properly. This fixes occasional failure of the driver to load. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_hst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 9a48999d0979..30f608bfc567 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -377,7 +377,7 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) { if (be32_to_cpu(*(u32 *) skb->data) == 0x00C60000) /* Move past the Watchdog pattern */ - htc_hdr = (struct htc_frame_hdr *) skb->data + 4; + htc_hdr = (struct htc_frame_hdr *)(skb->data + 4); } /* Get the message ID */ -- cgit v1.2.3 From 6335ed0ff8670e6378da41191ab8bda33d1b7ac8 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 29 Mar 2010 16:07:15 +0530 Subject: ath9k_htc: Simplify RX URB management This patch introduces the usage of URB anchors, thus reducing a large amount of code dealing with URB maintenance within the driver. The RX callback now takes care of freeing the SKB associated with each URB. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 125 ++++++++++++------------------- drivers/net/wireless/ath/ath9k/hif_usb.h | 7 +- 2 files changed, 50 insertions(+), 82 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index fc4f6e8c9ef3..e584a2912993 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -299,6 +299,8 @@ static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb, ret = hif_usb_send_regout(hif_dev, skb); break; default: + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Invalid TX pipe: %d\n", pipe_id); ret = -EINVAL; break; } @@ -408,14 +410,11 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, } } else { RX_STAT_INC(skb_dropped); - dev_kfree_skb_any(skb); return; } } err: - dev_kfree_skb_any(skb); - for (i = 0; i < pool_index; i++) { ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i], skb_pool[i]->len, USB_WLAN_RX_PIPE); @@ -426,11 +425,13 @@ err: static void ath9k_hif_usb_rx_cb(struct urb *urb) { struct sk_buff *skb = (struct sk_buff *) urb->context; - struct sk_buff *nskb; struct hif_device_usb *hif_dev = (struct hif_device_usb *) usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); int ret; + if (!skb) + return; + if (!hif_dev) goto free; @@ -448,34 +449,19 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb) if (likely(urb->actual_length != 0)) { skb_put(skb, urb->actual_length); - - nskb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_ATOMIC); - if (!nskb) - goto resubmit; - - usb_fill_bulk_urb(urb, hif_dev->udev, - usb_rcvbulkpipe(hif_dev->udev, - USB_WLAN_RX_PIPE), - nskb->data, MAX_RX_BUF_SIZE, - ath9k_hif_usb_rx_cb, nskb); - - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) { - dev_kfree_skb_any(nskb); - goto free; - } - ath9k_hif_usb_rx_stream(hif_dev, skb); - return; } resubmit: skb_reset_tail_pointer(skb); skb_trim(skb, 0); + usb_anchor_urb(urb, &hif_dev->rx_submitted); ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) + if (ret) { + usb_unanchor_urb(urb); goto free; + } return; free: @@ -490,6 +476,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); int ret; + if (!skb) + return; + if (!hif_dev) goto free; @@ -540,6 +529,7 @@ resubmit: return; free: dev_kfree_skb_any(skb); + urb->context = NULL; } static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) @@ -609,78 +599,59 @@ err: return -ENOMEM; } -static void ath9k_hif_usb_dealloc_rx_skbs(struct hif_device_usb *hif_dev) -{ - int i; - - for (i = 0; i < MAX_RX_URB_NUM; i++) { - if (hif_dev->wlan_rx_data_urb[i]) { - if (hif_dev->wlan_rx_data_urb[i]->transfer_buffer) - dev_kfree_skb_any((void *) - hif_dev->wlan_rx_data_urb[i]->context); - } - } -} - static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev) { - int i; - - for (i = 0; i < MAX_RX_URB_NUM; i++) { - if (hif_dev->wlan_rx_data_urb[i]) { - usb_kill_urb(hif_dev->wlan_rx_data_urb[i]); - usb_free_urb(hif_dev->wlan_rx_data_urb[i]); - hif_dev->wlan_rx_data_urb[i] = NULL; - } - } -} - -static int ath9k_hif_usb_prep_rx_urb(struct hif_device_usb *hif_dev, - struct urb *urb) -{ - struct sk_buff *skb; - - skb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL); - if (!skb) - return -ENOMEM; - - usb_fill_bulk_urb(urb, hif_dev->udev, - usb_rcvbulkpipe(hif_dev->udev, USB_WLAN_RX_PIPE), - skb->data, MAX_RX_BUF_SIZE, - ath9k_hif_usb_rx_cb, skb); - return 0; + usb_kill_anchored_urbs(&hif_dev->rx_submitted); } static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) { + struct urb *urb = NULL; + struct sk_buff *skb = NULL; int i, ret; + init_usb_anchor(&hif_dev->rx_submitted); + for (i = 0; i < MAX_RX_URB_NUM; i++) { /* Allocate URB */ - hif_dev->wlan_rx_data_urb[i] = usb_alloc_urb(0, GFP_KERNEL); - if (hif_dev->wlan_rx_data_urb[i] == NULL) { + urb = usb_alloc_urb(0, GFP_KERNEL); + if (urb == NULL) { ret = -ENOMEM; - goto err_rx_urb; + goto err_urb; } /* Allocate buffer */ - ret = ath9k_hif_usb_prep_rx_urb(hif_dev, - hif_dev->wlan_rx_data_urb[i]); - if (ret) - goto err_rx_urb; + skb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL); + if (!skb) { + ret = -ENOMEM; + goto err_skb; + } - /* Submit URB */ - ret = usb_submit_urb(hif_dev->wlan_rx_data_urb[i], GFP_KERNEL); - if (ret) - goto err_rx_urb; + usb_fill_bulk_urb(urb, hif_dev->udev, + usb_rcvbulkpipe(hif_dev->udev, + USB_WLAN_RX_PIPE), + skb->data, MAX_RX_BUF_SIZE, + ath9k_hif_usb_rx_cb, skb); + /* Anchor URB */ + usb_anchor_urb(urb, &hif_dev->rx_submitted); + + /* Submit URB */ + ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret) { + usb_unanchor_urb(urb); + goto err_submit; + } } return 0; -err_rx_urb: - ath9k_hif_usb_dealloc_rx_skbs(hif_dev); +err_submit: + dev_kfree_skb_any(skb); +err_skb: + usb_free_urb(urb); +err_urb: ath9k_hif_usb_dealloc_rx_urbs(hif_dev); return ret; } @@ -689,6 +660,8 @@ static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev) { if (hif_dev->reg_in_urb) { usb_kill_urb(hif_dev->reg_in_urb); + if (hif_dev->reg_in_urb->context) + dev_kfree_skb_any((void *)hif_dev->reg_in_urb->context); usb_free_urb(hif_dev->reg_in_urb); hif_dev->reg_in_urb = NULL; } @@ -712,12 +685,10 @@ static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev) ath9k_hif_usb_reg_in_cb, skb, 1); if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0) - goto err_skb; + goto err; return 0; -err_skb: - dev_kfree_skb_any(skb); err: ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); return -ENOMEM; diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 7cc3762a6789..ea9257bdc411 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -85,18 +85,15 @@ struct hif_device_usb { struct usb_interface *interface; const struct firmware *firmware; struct htc_target *htc_handle; - u8 flags; - struct hif_usb_tx tx; - - struct urb *wlan_rx_data_urb[MAX_RX_URB_NUM]; struct urb *reg_in_urb; - + struct usb_anchor rx_submitted; struct sk_buff *remain_skb; int rx_remain_len; int rx_pkt_len; int rx_transfer_len; int rx_pad_len; + u8 flags; /* HIF_USB_* */ }; int ath9k_hif_usb_init(void); -- cgit v1.2.3 From 7757dfed5809b03aa61c7d7f5ff8092f85df8583 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 29 Mar 2010 16:07:17 +0530 Subject: ath9k_htc: Handle TX queue overflow Stop/restart TX queues when the internal SKB queue is full. This helps handle TX better under heavy load. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 3 +++ drivers/net/wireless/ath/ath9k/htc_drv_init.c | 1 + drivers/net/wireless/ath/ath9k/htc_drv_main.c | 23 ++++++++++++++++++++--- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 12 ++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 698e6f1a506a..e09c6c2c9e23 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -349,6 +349,9 @@ struct ath9k_htc_priv { struct sk_buff *beacon; spinlock_t beacon_lock; + bool tx_queues_stop; + spinlock_t tx_lock; + struct ieee80211_vif *vif; unsigned int rxfilter; struct tasklet_struct wmi_tasklet; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 10c87605d2c4..3206eb06497d 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -449,6 +449,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) spin_lock_init(&priv->wmi->wmi_lock); spin_lock_init(&priv->beacon_lock); + spin_lock_init(&priv->tx_lock); mutex_init(&priv->mutex); mutex_init(&priv->aggr_work.mutex); tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 90b13ed1ae4c..63f032d61d5a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -994,7 +994,7 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct ieee80211_hdr *hdr; struct ath9k_htc_priv *priv = hw->priv; - int padpos, padsize; + int padpos, padsize, ret; hdr = (struct ieee80211_hdr *) skb->data; @@ -1008,8 +1008,19 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) memmove(skb->data, skb->data + padsize, padpos); } - if (ath9k_htc_tx_start(priv, skb) != 0) { - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, "Tx failed"); + ret = ath9k_htc_tx_start(priv, skb); + if (ret != 0) { + if (ret == -ENOMEM) { + ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, + "Stopping TX queues\n"); + ieee80211_stop_queues(hw); + spin_lock_bh(&priv->tx_lock); + priv->tx_queues_stop = true; + spin_unlock_bh(&priv->tx_lock); + } else { + ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, + "Tx failed"); + } goto fail_tx; } @@ -1074,6 +1085,12 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) priv->op_flags &= ~OP_INVALID; htc_start(priv->htc); + spin_lock_bh(&priv->tx_lock); + priv->tx_queues_stop = false; + spin_unlock_bh(&priv->tx_lock); + + ieee80211_wake_queues(hw); + mutex_unlock: mutex_unlock(&priv->mutex); return ret; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 838365607aa5..befe5740e2b8 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -226,6 +226,18 @@ void ath9k_tx_tasklet(unsigned long data) /* Send status to mac80211 */ ieee80211_tx_status(priv->hw, skb); } + + /* Wake TX queues if needed */ + spin_lock_bh(&priv->tx_lock); + if (priv->tx_queues_stop) { + priv->tx_queues_stop = false; + spin_unlock_bh(&priv->tx_lock); + ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, + "Waking up TX queues\n"); + ieee80211_wake_queues(priv->hw); + return; + } + spin_unlock_bh(&priv->tx_lock); } void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, -- cgit v1.2.3 From 9f01a84e81d10e38daa504348217895fe414a24b Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 29 Mar 2010 16:07:20 +0530 Subject: ath9k_htc: Initialize HW opmode Not setting the opmode properly during initialization results in the firmware sending up a bunch of packets before add_interface() has been called, for the first interface. This patch fixes the issue by setting the initial mode to 'managed'. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 3206eb06497d..d8779b907131 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -421,6 +421,7 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); priv->op_flags |= OP_TXAGGR; + priv->ah->opmode = NL80211_IFTYPE_STATION; } static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) -- cgit v1.2.3 From e65054b64ff6b89380a7f546c9eebf862e679646 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 30 Mar 2010 09:36:16 +0800 Subject: ipw2200: restart adapter only when abort_scan doesn't work When a scan watchdog is fired, try to send abort scan command first before restarting the adapter. This avoids reconnection for some users when scan hang is detected. This fixed bug https://bugzilla.kernel.org/show_bug.cgi?id=15419 Reported-by: Maurizio Avogadro Tested-by: Maurizio Avogadro Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2200.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index fcdbe8b00551..7fa2a3e6ebb0 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -2348,16 +2348,25 @@ static void ipw_bg_adapter_restart(struct work_struct *work) mutex_unlock(&priv->mutex); } -#define IPW_SCAN_CHECK_WATCHDOG (5 * HZ) +static void ipw_abort_scan(struct ipw_priv *priv); + +#define IPW_SCAN_CHECK_WATCHDOG (5 * HZ) static void ipw_scan_check(void *data) { struct ipw_priv *priv = data; - if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) { + + if (priv->status & STATUS_SCAN_ABORTING) { IPW_DEBUG_SCAN("Scan completion watchdog resetting " "adapter after (%dms).\n", jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG)); queue_work(priv->workqueue, &priv->adapter_restart); + } else if (priv->status & STATUS_SCANNING) { + IPW_DEBUG_SCAN("Scan completion watchdog aborting scan " + "after (%dms).\n", + jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG)); + ipw_abort_scan(priv); + queue_delayed_work(priv->workqueue, &priv->scan_check, HZ); } } -- cgit v1.2.3 From db1a052b73f7c97f9e8b21f3f19a92313ed2acb1 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 29 Mar 2010 20:07:11 -0700 Subject: ath9k: split out access to tx status information This patch passes in a pointer to the ath_tx_status data structure for functions that need it, instead of letting them grab it directly from the ath_desc struct. This is useful for making it possible to allocate the intermediate tx status data separately. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 3 - drivers/net/wireless/ath/ath9k/debug.c | 16 +++-- drivers/net/wireless/ath/ath9k/debug.h | 2 +- drivers/net/wireless/ath/ath9k/mac.c | 75 +++++++++++------------ drivers/net/wireless/ath/ath9k/mac.h | 4 +- drivers/net/wireless/ath/ath9k/xmit.c | 107 +++++++++++++++++---------------- 6 files changed, 104 insertions(+), 103 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 83c7ea4c007f..a581c365da6f 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -178,9 +178,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, #define BAW_WITHIN(_start, _bawsz, _seqno) \ ((((_seqno) - (_start)) & 4095) < (_bawsz)) -#define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum) -#define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low) -#define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA) #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) #define ATH_TX_COMPLETE_POLL_INT 1000 diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 42d2a506845a..6a4ef9bcff33 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -556,10 +556,8 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, } void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf) + struct ath_buf *bf, struct ath_tx_status *ts) { - struct ath_desc *ds = bf->bf_desc; - if (bf_isampdu(bf)) { if (bf_isxretried(bf)) TX_STAT_INC(txq->axq_qnum, a_xretries); @@ -569,17 +567,17 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, TX_STAT_INC(txq->axq_qnum, completed); } - if (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO) + if (ts->ts_status & ATH9K_TXERR_FIFO) TX_STAT_INC(txq->axq_qnum, fifo_underrun); - if (ds->ds_txstat.ts_status & ATH9K_TXERR_XTXOP) + if (ts->ts_status & ATH9K_TXERR_XTXOP) TX_STAT_INC(txq->axq_qnum, xtxop); - if (ds->ds_txstat.ts_status & ATH9K_TXERR_TIMER_EXPIRED) + if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED) TX_STAT_INC(txq->axq_qnum, timer_exp); - if (ds->ds_txstat.ts_flags & ATH9K_TX_DESC_CFG_ERR) + if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR) TX_STAT_INC(txq->axq_qnum, desc_cfg_err); - if (ds->ds_txstat.ts_flags & ATH9K_TX_DATA_UNDERRUN) + if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN) TX_STAT_INC(txq->axq_qnum, data_underrun); - if (ds->ds_txstat.ts_flags & ATH9K_TX_DELIM_UNDERRUN) + if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) TX_STAT_INC(txq->axq_qnum, delim_underrun); } diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 86780e68b31e..789c67791092 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -167,7 +167,7 @@ void ath9k_debug_remove_root(void); void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); void ath_debug_stat_rc(struct ath_softc *sc, int final_rate); void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf); + struct ath_buf *bf, struct ath_tx_status *ts); void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf); void ath_debug_stat_retries(struct ath_softc *sc, int rix, int xretries, int retries, u8 per); diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 7af823a1527d..08ad6dfa976d 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -246,79 +246,80 @@ void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) } EXPORT_SYMBOL(ath9k_hw_cleartxdesc); -int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) +int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, + struct ath_tx_status *ts) { struct ar5416_desc *ads = AR5416DESC(ds); if ((ads->ds_txstatus9 & AR_TxDone) == 0) return -EINPROGRESS; - ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); - ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp; - ds->ds_txstat.ts_status = 0; - ds->ds_txstat.ts_flags = 0; + ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); + ts->ts_tstamp = ads->AR_SendTimestamp; + ts->ts_status = 0; + ts->ts_flags = 0; if (ads->ds_txstatus1 & AR_FrmXmitOK) - ds->ds_txstat.ts_status |= ATH9K_TX_ACKED; + ts->ts_status |= ATH9K_TX_ACKED; if (ads->ds_txstatus1 & AR_ExcessiveRetries) - ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; + ts->ts_status |= ATH9K_TXERR_XRETRY; if (ads->ds_txstatus1 & AR_Filtered) - ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT; + ts->ts_status |= ATH9K_TXERR_FILT; if (ads->ds_txstatus1 & AR_FIFOUnderrun) { - ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO; + ts->ts_status |= ATH9K_TXERR_FIFO; ath9k_hw_updatetxtriglevel(ah, true); } if (ads->ds_txstatus9 & AR_TxOpExceeded) - ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP; + ts->ts_status |= ATH9K_TXERR_XTXOP; if (ads->ds_txstatus1 & AR_TxTimerExpired) - ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED; + ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; if (ads->ds_txstatus1 & AR_DescCfgErr) - ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR; + ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; if (ads->ds_txstatus1 & AR_TxDataUnderrun) { - ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN; + ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; ath9k_hw_updatetxtriglevel(ah, true); } if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { - ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN; + ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; ath9k_hw_updatetxtriglevel(ah, true); } if (ads->ds_txstatus0 & AR_TxBaStatus) { - ds->ds_txstat.ts_flags |= ATH9K_TX_BA; - ds->ds_txstat.ba_low = ads->AR_BaBitmapLow; - ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh; + ts->ts_flags |= ATH9K_TX_BA; + ts->ba_low = ads->AR_BaBitmapLow; + ts->ba_high = ads->AR_BaBitmapHigh; } - ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); - switch (ds->ds_txstat.ts_rateindex) { + ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); + switch (ts->ts_rateindex) { case 0: - ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); + ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); break; case 1: - ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); + ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); break; case 2: - ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); + ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); break; case 3: - ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); + ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); break; } - ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); - ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); - ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); - ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); - ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); - ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); - ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); - ds->ds_txstat.evm0 = ads->AR_TxEVM0; - ds->ds_txstat.evm1 = ads->AR_TxEVM1; - ds->ds_txstat.evm2 = ads->AR_TxEVM2; - ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); - ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); - ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); - ds->ds_txstat.ts_antenna = 0; + ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); + ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); + ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); + ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); + ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); + ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); + ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); + ts->evm0 = ads->AR_TxEVM0; + ts->evm1 = ads->AR_TxEVM1; + ts->evm2 = ads->AR_TxEVM2; + ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); + ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); + ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); + ts->ts_antenna = 0; return 0; } diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index a5e543bd2271..27529204d91e 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -241,7 +241,6 @@ struct ath_desc { void *ds_vdata; } __packed; -#define ds_txstat ds_us.tx #define ds_rxstat ds_us.rx #define ds_stat ds_us.stats @@ -702,7 +701,8 @@ void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, u32 segLen, bool firstSeg, bool lastSeg, const struct ath_desc *ds0); void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); -int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds); +int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, + struct ath_tx_status *ts); void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, u32 pktLen, enum ath9k_pkt_type type, u32 txPower, u32 keyIx, enum ath9k_key_type keyType, u32 flags); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 8359362fc51c..9d5d102b23bd 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -59,15 +59,14 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid, struct list_head *bf_head); static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, - struct ath_txq *txq, - struct list_head *bf_q, - int txok, int sendbar); + struct ath_txq *txq, struct list_head *bf_q, + struct ath_tx_status *ts, int txok, int sendbar); static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, struct list_head *head); static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, - int txok); -static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, + struct ath_tx_status *ts, int txok); +static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, int nbad, int txok, bool update_rc); enum { @@ -223,6 +222,9 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, { struct ath_buf *bf; struct list_head bf_head; + struct ath_tx_status ts; + + memset(&ts, 0, sizeof(ts)); INIT_LIST_HEAD(&bf_head); for (;;) { @@ -236,7 +238,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, ath_tx_update_baw(sc, tid, bf->bf_seqno); spin_unlock(&txq->axq_lock); - ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0); + ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); spin_lock(&txq->axq_lock); } @@ -286,7 +288,7 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf, struct list_head *bf_q, - int txok) + struct ath_tx_status *ts, int txok) { struct ath_node *an = NULL; struct sk_buff *skb; @@ -296,7 +298,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ieee80211_tx_info *tx_info; struct ath_atx_tid *tid = NULL; struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; - struct ath_desc *ds = bf_last->bf_desc; struct list_head bf_head, bf_pending; u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; u32 ba[WME_BA_BMP_SIZE >> 5]; @@ -325,10 +326,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, memset(ba, 0, WME_BA_BMP_SIZE >> 3); if (isaggr && txok) { - if (ATH_DS_TX_BA(ds)) { - seq_st = ATH_DS_BA_SEQ(ds); - memcpy(ba, ATH_DS_BA_BITMAP(ds), - WME_BA_BMP_SIZE >> 3); + if (ts->ts_flags & ATH9K_TX_BA) { + seq_st = ts->ts_seqnum; + memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); } else { /* * AR5416 can become deaf/mute when BA @@ -345,7 +345,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, INIT_LIST_HEAD(&bf_pending); INIT_LIST_HEAD(&bf_head); - nbad = ath_tx_num_badfrms(sc, bf, txok); + nbad = ath_tx_num_badfrms(sc, bf, ts, txok); while (bf) { txfail = txpending = 0; bf_next = bf->bf_next; @@ -359,7 +359,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, acked_cnt++; } else { if (!(tid->state & AGGR_CLEANUP) && - ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { + ts->ts_flags != ATH9K_TX_SW_ABORTED) { if (bf->bf_retries < ATH_MAX_SW_RETRIES) { ath_tx_set_retry(sc, txq, bf); txpending = 1; @@ -402,13 +402,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, spin_unlock_bh(&txq->axq_lock); if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { - ath_tx_rc_status(bf, ds, nbad, txok, true); + ath_tx_rc_status(bf, ts, nbad, txok, true); rc_update = false; } else { - ath_tx_rc_status(bf, ds, nbad, txok, false); + ath_tx_rc_status(bf, ts, nbad, txok, false); } - ath_tx_complete_buf(sc, bf, txq, &bf_head, !txfail, sendbar); + ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, + !txfail, sendbar); } else { /* retry the un-acked ones */ if (bf->bf_next == NULL && bf_last->bf_stale) { @@ -426,10 +427,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, spin_unlock_bh(&txq->axq_lock); bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, ds, nbad, + ath_tx_rc_status(bf, ts, nbad, 0, false); ath_tx_complete_buf(sc, bf, txq, - &bf_head, 0, 0); + &bf_head, ts, 0, 0); break; } @@ -752,8 +753,11 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) struct ath_node *an = (struct ath_node *)sta->drv_priv; struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; + struct ath_tx_status ts; struct ath_buf *bf; struct list_head bf_head; + + memset(&ts, 0, sizeof(ts)); INIT_LIST_HEAD(&bf_head); if (txtid->state & AGGR_CLEANUP) @@ -780,7 +784,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) } list_move_tail(&bf->list, &bf_head); ath_tx_update_baw(sc, txtid, bf->bf_seqno); - ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0); + ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); } spin_unlock_bh(&txq->axq_lock); @@ -1028,6 +1032,11 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) { struct ath_buf *bf, *lastbf; struct list_head bf_head; + struct ath_tx_status ts; + + memset(&ts, 0, sizeof(ts)); + if (!retry_tx) + ts.ts_flags = ATH9K_TX_SW_ABORTED; INIT_LIST_HEAD(&bf_head); @@ -1053,9 +1062,6 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) } lastbf = bf->bf_lastbf; - if (!retry_tx) - lastbf->bf_desc->ds_txstat.ts_flags = - ATH9K_TX_SW_ABORTED; /* remove ath_buf's of the same mpdu from txq */ list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); @@ -1064,9 +1070,9 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) spin_unlock_bh(&txq->axq_lock); if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0); + ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0); else - ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0); + ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); } spin_lock_bh(&txq->axq_lock); @@ -1871,9 +1877,8 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, } static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, - struct ath_txq *txq, - struct list_head *bf_q, - int txok, int sendbar) + struct ath_txq *txq, struct list_head *bf_q, + struct ath_tx_status *ts, int txok, int sendbar) { struct sk_buff *skb = bf->bf_mpdu; unsigned long flags; @@ -1891,7 +1896,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); ath_tx_complete(sc, skb, bf->aphy, tx_flags); - ath_debug_stat_tx(sc, txq, bf); + ath_debug_stat_tx(sc, txq, bf, ts); /* * Return the list of ath_buf of this mpdu to free queue @@ -1902,23 +1907,21 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, } static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, - int txok) + struct ath_tx_status *ts, int txok) { - struct ath_buf *bf_last = bf->bf_lastbf; - struct ath_desc *ds = bf_last->bf_desc; u16 seq_st = 0; u32 ba[WME_BA_BMP_SIZE >> 5]; int ba_index; int nbad = 0; int isaggr = 0; - if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED) + if (ts->ts_flags == ATH9K_TX_SW_ABORTED) return 0; isaggr = bf_isaggr(bf); if (isaggr) { - seq_st = ATH_DS_BA_SEQ(ds); - memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3); + seq_st = ts->ts_seqnum; + memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); } while (bf) { @@ -1932,7 +1935,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, return nbad; } -static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, +static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, int nbad, int txok, bool update_rc) { struct sk_buff *skb = bf->bf_mpdu; @@ -1942,24 +1945,24 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, u8 i, tx_rateindex; if (txok) - tx_info->status.ack_signal = ds->ds_txstat.ts_rssi; + tx_info->status.ack_signal = ts->ts_rssi; - tx_rateindex = ds->ds_txstat.ts_rateindex; + tx_rateindex = ts->ts_rateindex; WARN_ON(tx_rateindex >= hw->max_rates); - if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) + if (ts->ts_status & ATH9K_TXERR_FILT) tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) tx_info->flags |= IEEE80211_TX_STAT_AMPDU; - if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && + if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { if (ieee80211_is_data(hdr->frame_control)) { - if (ds->ds_txstat.ts_flags & + if (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN)) tx_info->pad[0] |= ATH_TX_INFO_UNDERRUN; - if ((ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) || - (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO)) + if ((ts->ts_status & ATH9K_TXERR_XRETRY) || + (ts->ts_status & ATH9K_TXERR_FIFO)) tx_info->pad[0] |= ATH_TX_INFO_XRETRY; tx_info->status.ampdu_len = bf->bf_nframes; tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad; @@ -1997,6 +2000,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) struct ath_buf *bf, *lastbf, *bf_held = NULL; struct list_head bf_head; struct ath_desc *ds; + struct ath_tx_status *ts; int txok; int status; @@ -2035,8 +2039,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) lastbf = bf->bf_lastbf; ds = lastbf->bf_desc; + ts = &ds->ds_us.tx; - status = ath9k_hw_txprocdesc(ah, ds); + status = ath9k_hw_txprocdesc(ah, ds, ts); if (status == -EINPROGRESS) { spin_unlock_bh(&txq->axq_lock); break; @@ -2047,7 +2052,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) * can disable RX. */ if (bf->bf_isnullfunc && - (ds->ds_txstat.ts_status & ATH9K_TX_ACKED)) { + (ts->ts_status & ATH9K_TX_ACKED)) { if ((sc->ps_flags & PS_ENABLED)) ath9k_enable_ps(sc); else @@ -2066,7 +2071,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) &txq->axq_q, lastbf->list.prev); txq->axq_depth--; - txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_MASK); + txok = !(ts->ts_status & ATH9K_TXERR_MASK); txq->axq_tx_inprogress = false; spin_unlock_bh(&txq->axq_lock); @@ -2081,16 +2086,16 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) * This frame is sent out as a single frame. * Use hardware retry status for this frame. */ - bf->bf_retries = ds->ds_txstat.ts_longretry; - if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) + bf->bf_retries = ts->ts_longretry; + if (ts->ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, ds, 0, txok, true); + ath_tx_rc_status(bf, ts, 0, txok, true); } if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); + ath_tx_complete_aggr(sc, txq, bf, &bf_head, ts, txok); else - ath_tx_complete_buf(sc, bf, txq, &bf_head, txok, 0); + ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, txok, 0); ath_wake_mac80211_queue(sc, txq); -- cgit v1.2.3 From 8e6f5aa250d6013ec0d66f9f45f376678d3fc4ab Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 29 Mar 2010 20:09:27 -0700 Subject: ath9k: split out access to rx status information This patch passes in a pointer to the ath_rx_status data structure for functions that need it, instead of letting them grab it directly from the ath_desc struct. This is useful for making it possible to allocate the intermediate rx status data separately. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 19 +++++---- drivers/net/wireless/ath/ath9k/debug.h | 2 +- drivers/net/wireless/ath/ath9k/mac.c | 72 +++++++++++++++++----------------- drivers/net/wireless/ath/ath9k/mac.h | 5 +-- drivers/net/wireless/ath/ath9k/recv.c | 14 +++---- 5 files changed, 52 insertions(+), 60 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 6a4ef9bcff33..c7e895925393 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -660,30 +660,29 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, #undef PHY_ERR } -void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf) +void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) { #define RX_STAT_INC(c) sc->debug.stats.rxstats.c++ #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ - struct ath_desc *ds = bf->bf_desc; u32 phyerr; - if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC) + if (rs->rs_status & ATH9K_RXERR_CRC) RX_STAT_INC(crc_err); - if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) + if (rs->rs_status & ATH9K_RXERR_DECRYPT) RX_STAT_INC(decrypt_crc_err); - if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) + if (rs->rs_status & ATH9K_RXERR_MIC) RX_STAT_INC(mic_err); - if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_PRE) + if (rs->rs_status & ATH9K_RX_DELIM_CRC_PRE) RX_STAT_INC(pre_delim_crc_err); - if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_POST) + if (rs->rs_status & ATH9K_RX_DELIM_CRC_POST) RX_STAT_INC(post_delim_crc_err); - if (ds->ds_rxstat.rs_status & ATH9K_RX_DECRYPT_BUSY) + if (rs->rs_status & ATH9K_RX_DECRYPT_BUSY) RX_STAT_INC(decrypt_busy_err); - if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) { + if (rs->rs_status & ATH9K_RXERR_PHY) { RX_STAT_INC(phy_err); - phyerr = ds->ds_rxstat.rs_phyerr & 0x24; + phyerr = rs->rs_phyerr & 0x24; RX_PHY_ERR_INC(phyerr); } diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 789c67791092..9551d8eb9453 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -168,7 +168,7 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); void ath_debug_stat_rc(struct ath_softc *sc, int final_rate); void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf, struct ath_tx_status *ts); -void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf); +void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); void ath_debug_stat_retries(struct ath_softc *sc, int rix, int xretries, int retries, u8 per); diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 08ad6dfa976d..e020b82a677e 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -859,7 +859,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) EXPORT_SYMBOL(ath9k_hw_resettxqueue); int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 pa, struct ath_desc *nds, u64 tsf) + struct ath_rx_status *rs, u64 tsf) { struct ar5416_desc ads; struct ar5416_desc *adsp = AR5416DESC(ds); @@ -870,70 +870,70 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, ads.u.rx = adsp->u.rx; - ds->ds_rxstat.rs_status = 0; - ds->ds_rxstat.rs_flags = 0; + rs->rs_status = 0; + rs->rs_flags = 0; - ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen; - ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp; + rs->rs_datalen = ads.ds_rxstatus1 & AR_DataLen; + rs->rs_tstamp = ads.AR_RcvTimestamp; if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) { - ds->ds_rxstat.rs_rssi = ATH9K_RSSI_BAD; - ds->ds_rxstat.rs_rssi_ctl0 = ATH9K_RSSI_BAD; - ds->ds_rxstat.rs_rssi_ctl1 = ATH9K_RSSI_BAD; - ds->ds_rxstat.rs_rssi_ctl2 = ATH9K_RSSI_BAD; - ds->ds_rxstat.rs_rssi_ext0 = ATH9K_RSSI_BAD; - ds->ds_rxstat.rs_rssi_ext1 = ATH9K_RSSI_BAD; - ds->ds_rxstat.rs_rssi_ext2 = ATH9K_RSSI_BAD; + rs->rs_rssi = ATH9K_RSSI_BAD; + rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD; + rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD; + rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD; + rs->rs_rssi_ext0 = ATH9K_RSSI_BAD; + rs->rs_rssi_ext1 = ATH9K_RSSI_BAD; + rs->rs_rssi_ext2 = ATH9K_RSSI_BAD; } else { - ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); - ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, + rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); + rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00); - ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, + rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01); - ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, + rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02); - ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, + rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10); - ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, + rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11); - ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, + rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12); } if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) - ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); + rs->rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); else - ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID; + rs->rs_keyix = ATH9K_RXKEYIX_INVALID; - ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads)); - ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; + rs->rs_rate = RXSTATUS_RATE(ah, (&ads)); + rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; - ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; - ds->ds_rxstat.rs_moreaggr = + rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; + rs->rs_moreaggr = (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; - ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna); - ds->ds_rxstat.rs_flags = + rs->rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna); + rs->rs_flags = (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0; - ds->ds_rxstat.rs_flags |= + rs->rs_flags |= (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0; if (ads.ds_rxstatus8 & AR_PreDelimCRCErr) - ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE; + rs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE; if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) - ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST; + rs->rs_flags |= ATH9K_RX_DELIM_CRC_POST; if (ads.ds_rxstatus8 & AR_DecryptBusyErr) - ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY; + rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY; if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { if (ads.ds_rxstatus8 & AR_CRCErr) - ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC; + rs->rs_status |= ATH9K_RXERR_CRC; else if (ads.ds_rxstatus8 & AR_PHYErr) { - ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY; + rs->rs_status |= ATH9K_RXERR_PHY; phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode); - ds->ds_rxstat.rs_phyerr = phyerr; + rs->rs_phyerr = phyerr; } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) - ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT; + rs->rs_status |= ATH9K_RXERR_DECRYPT; else if (ads.ds_rxstatus8 & AR_MichaelErr) - ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC; + rs->rs_status |= ATH9K_RXERR_MIC; } return 0; diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 27529204d91e..d1d5b238cdee 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -241,9 +241,6 @@ struct ath_desc { void *ds_vdata; } __packed; -#define ds_rxstat ds_us.rx -#define ds_stat ds_us.stats - #define ATH9K_TXDESC_CLRDMASK 0x0001 #define ATH9K_TXDESC_NOACK 0x0002 #define ATH9K_TXDESC_RTSENA 0x0004 @@ -732,7 +729,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q); bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q); int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 pa, struct ath_desc *nds, u64 tsf); + struct ath_rx_status *rs, u64 tsf); void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, u32 size, u32 flags); bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 1ca42e5148c8..9617887907b7 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -506,6 +506,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); ds = bf->bf_desc; + rx_stats = &ds->ds_us.rx; /* * Must provide the virtual address of the current @@ -518,10 +519,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) * on. All this is necessary because of our use of * a self-linked list to avoid rx overruns. */ - retval = ath9k_hw_rxprocdesc(ah, ds, - bf->bf_daddr, - PA2DESC(sc, ds->ds_link), - 0); + retval = ath9k_hw_rxprocdesc(ah, ds, rx_stats, 0); if (retval == -EINPROGRESS) { struct ath_buf *tbf; struct ath_desc *tds; @@ -545,8 +543,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) */ tds = tbf->bf_desc; - retval = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr, - PA2DESC(sc, tds->ds_link), 0); + retval = ath9k_hw_rxprocdesc(ah, tds, &tds->ds_us.rx, 0); if (retval == -EINPROGRESS) { break; } @@ -569,9 +566,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) rxs = IEEE80211_SKB_RXCB(skb); hw = ath_get_virt_hw(sc, hdr); - rx_stats = &ds->ds_rxstat; - ath_debug_stat_rx(sc, bf); + ath_debug_stat_rx(sc, rx_stats); /* * If we're asked to flush receive queue, directly @@ -626,7 +622,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) * change the default rx antenna if rx diversity chooses the * other antenna 3 times in a row. */ - if (sc->rx.defant != ds->ds_rxstat.rs_antenna) { + if (sc->rx.defant != rx_stats->rs_antenna) { if (++sc->rx.rxotherant >= 3) ath_setdefantenna(sc, rx_stats->rs_antenna); } else { -- cgit v1.2.3 From 29bffa96e9bef4fb84740a49e93d5bd6ca126bac Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 29 Mar 2010 20:14:23 -0700 Subject: ath9k: allocate tx and rx status information on stack ath_tx_status and ath_rx_status data are only necessary for a short time, until they have been processed and converted into mac80211 data structures. Because of that, it makes no sense to keep them tied to the DMA descriptor, that only wastes precious memory. This patch allocates the data on stack in the functions that call the conversion functions from ath9k_hw. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/mac.h | 5 ----- drivers/net/wireless/ath/ath9k/recv.c | 22 ++++++++++++---------- drivers/net/wireless/ath/ath9k/xmit.c | 20 ++++++++++---------- 3 files changed, 22 insertions(+), 25 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index d1d5b238cdee..68dbd7a8ddca 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -233,11 +233,6 @@ struct ath_desc { u32 ds_ctl0; u32 ds_ctl1; u32 ds_hw[20]; - union { - struct ath_tx_status tx; - struct ath_rx_status rx; - void *stats; - } ds_us; void *ds_vdata; } __packed; diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 9617887907b7..94560e2fe376 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -477,7 +477,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) struct ath_buf *bf; struct ath_desc *ds; - struct ath_rx_status *rx_stats; struct sk_buff *skb = NULL, *requeue_skb; struct ieee80211_rx_status *rxs; struct ath_hw *ah = sc->sc_ah; @@ -491,6 +490,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) struct ieee80211_hdr *hdr; int retval; bool decrypt_error = false; + struct ath_rx_status rs; spin_lock_bh(&sc->rx.rxbuflock); @@ -506,7 +506,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); ds = bf->bf_desc; - rx_stats = &ds->ds_us.rx; /* * Must provide the virtual address of the current @@ -519,11 +518,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) * on. All this is necessary because of our use of * a self-linked list to avoid rx overruns. */ - retval = ath9k_hw_rxprocdesc(ah, ds, rx_stats, 0); + memset(&rs, 0, sizeof(rs)); + retval = ath9k_hw_rxprocdesc(ah, ds, &rs, 0); if (retval == -EINPROGRESS) { + struct ath_rx_status trs; struct ath_buf *tbf; struct ath_desc *tds; + memset(&trs, 0, sizeof(trs)); if (list_is_last(&bf->list, &sc->rx.rxbuf)) { sc->rx.rxlink = NULL; break; @@ -543,7 +545,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) */ tds = tbf->bf_desc; - retval = ath9k_hw_rxprocdesc(ah, tds, &tds->ds_us.rx, 0); + retval = ath9k_hw_rxprocdesc(ah, tds, &trs, 0); if (retval == -EINPROGRESS) { break; } @@ -567,7 +569,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) hw = ath_get_virt_hw(sc, hdr); - ath_debug_stat_rx(sc, rx_stats); + ath_debug_stat_rx(sc, &rs); /* * If we're asked to flush receive queue, directly @@ -576,7 +578,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) if (flush) goto requeue; - retval = ath9k_cmn_rx_skb_preprocess(common, hw, skb, rx_stats, + retval = ath9k_cmn_rx_skb_preprocess(common, hw, skb, &rs, rxs, &decrypt_error); if (retval) goto requeue; @@ -597,9 +599,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) common->rx_bufsize, DMA_FROM_DEVICE); - skb_put(skb, rx_stats->rs_datalen); + skb_put(skb, rs.rs_datalen); - ath9k_cmn_rx_skb_postprocess(common, skb, rx_stats, + ath9k_cmn_rx_skb_postprocess(common, skb, &rs, rxs, decrypt_error); /* We will now give hardware our shiny new allocated skb */ @@ -622,9 +624,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) * change the default rx antenna if rx diversity chooses the * other antenna 3 times in a row. */ - if (sc->rx.defant != rx_stats->rs_antenna) { + if (sc->rx.defant != rs.rs_antenna) { if (++sc->rx.rxotherant >= 3) - ath_setdefantenna(sc, rx_stats->rs_antenna); + ath_setdefantenna(sc, rs.rs_antenna); } else { sc->rx.rxotherant = 0; } diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 9d5d102b23bd..1d04ca86df56 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2000,7 +2000,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) struct ath_buf *bf, *lastbf, *bf_held = NULL; struct list_head bf_head; struct ath_desc *ds; - struct ath_tx_status *ts; + struct ath_tx_status ts; int txok; int status; @@ -2039,9 +2039,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) lastbf = bf->bf_lastbf; ds = lastbf->bf_desc; - ts = &ds->ds_us.tx; - status = ath9k_hw_txprocdesc(ah, ds, ts); + memset(&ts, 0, sizeof(ts)); + status = ath9k_hw_txprocdesc(ah, ds, &ts); if (status == -EINPROGRESS) { spin_unlock_bh(&txq->axq_lock); break; @@ -2052,7 +2052,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) * can disable RX. */ if (bf->bf_isnullfunc && - (ts->ts_status & ATH9K_TX_ACKED)) { + (ts.ts_status & ATH9K_TX_ACKED)) { if ((sc->ps_flags & PS_ENABLED)) ath9k_enable_ps(sc); else @@ -2071,7 +2071,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) &txq->axq_q, lastbf->list.prev); txq->axq_depth--; - txok = !(ts->ts_status & ATH9K_TXERR_MASK); + txok = !(ts.ts_status & ATH9K_TXERR_MASK); txq->axq_tx_inprogress = false; spin_unlock_bh(&txq->axq_lock); @@ -2086,16 +2086,16 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) * This frame is sent out as a single frame. * Use hardware retry status for this frame. */ - bf->bf_retries = ts->ts_longretry; - if (ts->ts_status & ATH9K_TXERR_XRETRY) + bf->bf_retries = ts.ts_longretry; + if (ts.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, ts, 0, txok, true); + ath_tx_rc_status(bf, &ts, 0, txok, true); } if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, ts, txok); + ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok); else - ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, txok, 0); + ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); ath_wake_mac80211_queue(sc, txq); -- cgit v1.2.3 From 32fbccafed7e935432b601f0453c2b702a385a25 Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 30 Mar 2010 08:48:27 +0530 Subject: ath9k_htc: Fix TKIP encryption Set IEEE80211_HW_RX_INCLUDES_FCS to indicate that the FCS is present in RX frames. Also, remove a redundant assignment of skb length and include the FCS_LEN when checking padding. Fixing this issue makes TKIP work. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 3 ++- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index d8779b907131..90cfd9066abf 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -513,7 +513,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_SPECTRUM_MGMT | - IEEE80211_HW_HAS_RATE_CONTROL; + IEEE80211_HW_HAS_RATE_CONTROL | + IEEE80211_HW_RX_INCLUDES_FCS; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index befe5740e2b8..f1e3d830d7de 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -450,7 +450,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, padpos = ath9k_cmn_padpos(fc); padsize = padpos & 3; - if (padsize && skb->len >= padpos+padsize) { + if (padsize && skb->len >= padpos+padsize+FCS_LEN) { memmove(skb->data + padsize, skb->data, padpos); skb_pull(skb, padsize); } @@ -646,7 +646,6 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, spin_lock(&priv->rx.rxbuflock); memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); - skb->len = rxstatus->rs_datalen; rxbuf->skb = skb; rxbuf->in_process = true; spin_unlock(&priv->rx.rxbuflock); -- cgit v1.2.3 From 932d37c094b3c3410b4059f18f3b5c756bff059a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 29 Mar 2010 23:37:36 -0700 Subject: ath9k: Do not indicate RX_FLAG_DECRYPTED for unprotected frames mac80211 skips drop_unencrypted checks if the driver/firmware has already taken care of this. In case of ath9k, we must not indicate that the frame was decrypted if no decryption was actually done. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index cf768f2811eb..09effdedc8c0 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -255,7 +255,8 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, keyix = rx_stats->rs_keyix; - if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { + if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && + ieee80211_has_protected(fc)) { rxs->flag |= RX_FLAG_DECRYPTED; } else if (ieee80211_has_protected(fc) && !decrypt_error && skb->len >= hdrlen + 4) { -- cgit v1.2.3 From 879999cec9489f8942ebce3ec1b5f23ef948dda7 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 23 Mar 2010 21:51:14 +0100 Subject: ar9170usb: fix panic triggered by undersized rxstream buffer While ar9170's USB transport packet size is currently set to 8KiB, the PHY is capable of receiving AMPDUs with up to 64KiB. Such a large frame will be split over several rx URBs and exceed the previously allocated space for rx stream reconstruction. This patch increases the buffer size to 64KiB which is in fact the phy & rx stream designed size limit. Cc: stable@kernel.org Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=15591 Reported-by: Christian Mehlis Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/hw.h | 1 + drivers/net/wireless/ath/ar9170/main.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h index 0a1d4c28e68a..06f1f3c951a4 100644 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h @@ -425,5 +425,6 @@ enum ar9170_txq { #define AR9170_TXQ_DEPTH 32 #define AR9170_TX_MAX_PENDING 128 +#define AR9170_RX_STREAM_MAX_SIZE 65535 #endif /* __AR9170_HW_H */ diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index f4650fcdebc9..2daeaa5bcb88 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -2515,7 +2515,7 @@ void *ar9170_alloc(size_t priv_size) * tends to split the streams into seperate rx descriptors. */ - skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL); + skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL); if (!skb) goto err_nomem; -- cgit v1.2.3 From 9fd1ea428590cf6e35e5a7df32ff6bccfd371db2 Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Wed, 24 Mar 2010 19:46:31 +0100 Subject: wireless/ipw2x00: remove trailing space in messages Signed-off-by: Frans Pop Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2100.c | 38 ++++++++--------- drivers/net/wireless/ipw2x00/ipw2200.c | 74 +++++++++++++++++----------------- 2 files changed, 56 insertions(+), 56 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index fe63bf21c67e..2088ac029b35 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -2140,7 +2140,7 @@ static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status) DECLARE_SSID_BUF(ssid); IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, - "disassociated: '%s' %pM \n", + "disassociated: '%s' %pM\n", print_ssid(ssid, priv->essid, priv->essid_len), priv->bssid); @@ -3285,7 +3285,7 @@ static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) if (inta & IPW2100_INTA_PARITY_ERROR) { printk(KERN_ERR DRV_NAME - ": ***** PARITY ERROR INTERRUPT !!!! \n"); + ": ***** PARITY ERROR INTERRUPT !!!!\n"); priv->inta_other++; write_register(dev, IPW_REG_INTA, IPW2100_INTA_PARITY_ERROR); } @@ -6753,7 +6753,7 @@ static int ipw2100_wx_set_freq(struct net_device *dev, err = -EOPNOTSUPP; goto done; } else { /* Set the channel */ - IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); + IPW_DEBUG_WX("SET Freq/Channel -> %d\n", fwrq->m); err = ipw2100_set_channel(priv, fwrq->m, 0); } @@ -6782,7 +6782,7 @@ static int ipw2100_wx_get_freq(struct net_device *dev, else wrqu->freq.m = 0; - IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel); + IPW_DEBUG_WX("GET Freq/Channel -> %d\n", priv->channel); return 0; } @@ -6794,7 +6794,7 @@ static int ipw2100_wx_set_mode(struct net_device *dev, struct ipw2100_priv *priv = libipw_priv(dev); int err = 0; - IPW_DEBUG_WX("SET Mode -> %d \n", wrqu->mode); + IPW_DEBUG_WX("SET Mode -> %d\n", wrqu->mode); if (wrqu->mode == priv->ieee->iw_mode) return 0; @@ -7149,7 +7149,7 @@ static int ipw2100_wx_set_nick(struct net_device *dev, memset(priv->nick, 0, sizeof(priv->nick)); memcpy(priv->nick, extra, wrqu->data.length); - IPW_DEBUG_WX("SET Nickname -> %s \n", priv->nick); + IPW_DEBUG_WX("SET Nickname -> %s\n", priv->nick); return 0; } @@ -7168,7 +7168,7 @@ static int ipw2100_wx_get_nick(struct net_device *dev, memcpy(extra, priv->nick, wrqu->data.length); wrqu->data.flags = 1; /* active */ - IPW_DEBUG_WX("GET Nickname -> %s \n", extra); + IPW_DEBUG_WX("GET Nickname -> %s\n", extra); return 0; } @@ -7207,7 +7207,7 @@ static int ipw2100_wx_set_rate(struct net_device *dev, err = ipw2100_set_tx_rates(priv, rate, 0); - IPW_DEBUG_WX("SET Rate -> %04X \n", rate); + IPW_DEBUG_WX("SET Rate -> %04X\n", rate); done: mutex_unlock(&priv->action_mutex); return err; @@ -7258,7 +7258,7 @@ static int ipw2100_wx_get_rate(struct net_device *dev, wrqu->bitrate.value = 0; } - IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); + IPW_DEBUG_WX("GET Rate -> %d\n", wrqu->bitrate.value); done: mutex_unlock(&priv->action_mutex); @@ -7294,7 +7294,7 @@ static int ipw2100_wx_set_rts(struct net_device *dev, err = ipw2100_set_rts_threshold(priv, value); - IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X \n", value); + IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X\n", value); done: mutex_unlock(&priv->action_mutex); return err; @@ -7316,7 +7316,7 @@ static int ipw2100_wx_get_rts(struct net_device *dev, /* If RTS is set to the default value, then it is disabled */ wrqu->rts.disabled = (priv->rts_threshold & RTS_DISABLED) ? 1 : 0; - IPW_DEBUG_WX("GET RTS Threshold -> 0x%08X \n", wrqu->rts.value); + IPW_DEBUG_WX("GET RTS Threshold -> 0x%08X\n", wrqu->rts.value); return 0; } @@ -7355,7 +7355,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev, err = ipw2100_set_tx_power(priv, value); - IPW_DEBUG_WX("SET TX Power -> %d \n", value); + IPW_DEBUG_WX("SET TX Power -> %d\n", value); done: mutex_unlock(&priv->action_mutex); @@ -7384,7 +7384,7 @@ static int ipw2100_wx_get_txpow(struct net_device *dev, wrqu->txpower.flags = IW_TXPOW_DBM; - IPW_DEBUG_WX("GET TX Power -> %d \n", wrqu->txpower.value); + IPW_DEBUG_WX("GET TX Power -> %d\n", wrqu->txpower.value); return 0; } @@ -7414,7 +7414,7 @@ static int ipw2100_wx_set_frag(struct net_device *dev, priv->frag_threshold = priv->ieee->fts; } - IPW_DEBUG_WX("SET Frag Threshold -> %d \n", priv->ieee->fts); + IPW_DEBUG_WX("SET Frag Threshold -> %d\n", priv->ieee->fts); return 0; } @@ -7432,7 +7432,7 @@ static int ipw2100_wx_get_frag(struct net_device *dev, wrqu->frag.fixed = 0; /* no auto select */ wrqu->frag.disabled = (priv->frag_threshold & FRAG_DISABLED) ? 1 : 0; - IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value); + IPW_DEBUG_WX("GET Frag Threshold -> %d\n", wrqu->frag.value); return 0; } @@ -7458,14 +7458,14 @@ static int ipw2100_wx_set_retry(struct net_device *dev, if (wrqu->retry.flags & IW_RETRY_SHORT) { err = ipw2100_set_short_retry(priv, wrqu->retry.value); - IPW_DEBUG_WX("SET Short Retry Limit -> %d \n", + IPW_DEBUG_WX("SET Short Retry Limit -> %d\n", wrqu->retry.value); goto done; } if (wrqu->retry.flags & IW_RETRY_LONG) { err = ipw2100_set_long_retry(priv, wrqu->retry.value); - IPW_DEBUG_WX("SET Long Retry Limit -> %d \n", + IPW_DEBUG_WX("SET Long Retry Limit -> %d\n", wrqu->retry.value); goto done; } @@ -7474,7 +7474,7 @@ static int ipw2100_wx_set_retry(struct net_device *dev, if (!err) err = ipw2100_set_long_retry(priv, wrqu->retry.value); - IPW_DEBUG_WX("SET Both Retry Limits -> %d \n", wrqu->retry.value); + IPW_DEBUG_WX("SET Both Retry Limits -> %d\n", wrqu->retry.value); done: mutex_unlock(&priv->action_mutex); @@ -7508,7 +7508,7 @@ static int ipw2100_wx_get_retry(struct net_device *dev, wrqu->retry.value = priv->short_retry_limit; } - IPW_DEBUG_WX("GET Retry -> %d \n", wrqu->retry.value); + IPW_DEBUG_WX("GET Retry -> %d\n", wrqu->retry.value); return 0; } diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 7fa2a3e6ebb0..192abfdc5039 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -458,7 +458,7 @@ static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg) { u32 word; _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); - IPW_DEBUG_IO(" reg = 0x%8X : \n", reg); + IPW_DEBUG_IO(" reg = 0x%8X :\n", reg); word = _ipw_read32(priv, IPW_INDIRECT_DATA); return (word >> ((reg & 0x3) * 8)) & 0xff; } @@ -472,7 +472,7 @@ static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg) _ipw_write32(priv, IPW_INDIRECT_ADDR, reg); value = _ipw_read32(priv, IPW_INDIRECT_DATA); - IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x \n", reg, value); + IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x\n", reg, value); return value; } @@ -2747,7 +2747,7 @@ static inline void ipw_fw_dma_reset_command_blocks(struct ipw_priv *priv) static int ipw_fw_dma_enable(struct ipw_priv *priv) { /* start dma engine but no transfers yet */ - IPW_DEBUG_FW(">> : \n"); + IPW_DEBUG_FW(">> :\n"); /* Start the dma */ ipw_fw_dma_reset_command_blocks(priv); @@ -2755,7 +2755,7 @@ static int ipw_fw_dma_enable(struct ipw_priv *priv) /* Write CB base address */ ipw_write_reg32(priv, IPW_DMA_I_CB_BASE, IPW_SHARED_SRAM_DMA_CONTROL); - IPW_DEBUG_FW("<< : \n"); + IPW_DEBUG_FW("<< :\n"); return 0; } @@ -2770,7 +2770,7 @@ static void ipw_fw_dma_abort(struct ipw_priv *priv) ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control); priv->sram_desc.last_cb_index = 0; - IPW_DEBUG_FW("<< \n"); + IPW_DEBUG_FW("<<\n"); } static int ipw_fw_dma_write_command_block(struct ipw_priv *priv, int index, @@ -2821,29 +2821,29 @@ static void ipw_fw_dma_dump_command_block(struct ipw_priv *priv) IPW_DEBUG_FW(">> :\n"); address = ipw_read_reg32(priv, IPW_DMA_I_CURRENT_CB); - IPW_DEBUG_FW_INFO("Current CB is 0x%x \n", address); + IPW_DEBUG_FW_INFO("Current CB is 0x%x\n", address); /* Read the DMA Controlor register */ register_value = ipw_read_reg32(priv, IPW_DMA_I_DMA_CONTROL); - IPW_DEBUG_FW_INFO("IPW_DMA_I_DMA_CONTROL is 0x%x \n", register_value); + IPW_DEBUG_FW_INFO("IPW_DMA_I_DMA_CONTROL is 0x%x\n", register_value); /* Print the CB values */ cb_fields_address = address; register_value = ipw_read_reg32(priv, cb_fields_address); - IPW_DEBUG_FW_INFO("Current CB ControlField is 0x%x \n", register_value); + IPW_DEBUG_FW_INFO("Current CB Control Field is 0x%x\n", register_value); cb_fields_address += sizeof(u32); register_value = ipw_read_reg32(priv, cb_fields_address); - IPW_DEBUG_FW_INFO("Current CB Source Field is 0x%x \n", register_value); + IPW_DEBUG_FW_INFO("Current CB Source Field is 0x%x\n", register_value); cb_fields_address += sizeof(u32); register_value = ipw_read_reg32(priv, cb_fields_address); - IPW_DEBUG_FW_INFO("Current CB Destination Field is 0x%x \n", + IPW_DEBUG_FW_INFO("Current CB Destination Field is 0x%x\n", register_value); cb_fields_address += sizeof(u32); register_value = ipw_read_reg32(priv, cb_fields_address); - IPW_DEBUG_FW_INFO("Current CB Status Field is 0x%x \n", register_value); + IPW_DEBUG_FW_INFO("Current CB Status Field is 0x%x\n", register_value); IPW_DEBUG_FW(">> :\n"); } @@ -2859,7 +2859,7 @@ static int ipw_fw_dma_command_block_index(struct ipw_priv *priv) current_cb_index = (current_cb_address - IPW_SHARED_SRAM_DMA_CONTROL) / sizeof(struct command_block); - IPW_DEBUG_FW_INFO("Current CB index 0x%x address = 0x%X \n", + IPW_DEBUG_FW_INFO("Current CB index 0x%x address = 0x%X\n", current_cb_index, current_cb_address); IPW_DEBUG_FW(">> :\n"); @@ -2918,7 +2918,7 @@ static int ipw_fw_dma_add_buffer(struct ipw_priv *priv, dma_addr_t *src_address, int ret, i; u32 size; - IPW_DEBUG_FW(">> \n"); + IPW_DEBUG_FW(">>\n"); IPW_DEBUG_FW_INFO("nr=%d dest_address=0x%x len=0x%x\n", nr, dest_address, len); @@ -2935,7 +2935,7 @@ static int ipw_fw_dma_add_buffer(struct ipw_priv *priv, dma_addr_t *src_address, IPW_DEBUG_FW_INFO(": Added new cb\n"); } - IPW_DEBUG_FW("<< \n"); + IPW_DEBUG_FW("<<\n"); return 0; } @@ -2944,7 +2944,7 @@ static int ipw_fw_dma_wait(struct ipw_priv *priv) u32 current_index = 0, previous_index; u32 watchdog = 0; - IPW_DEBUG_FW(">> : \n"); + IPW_DEBUG_FW(">> :\n"); current_index = ipw_fw_dma_command_block_index(priv); IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%08X\n", @@ -2973,7 +2973,7 @@ static int ipw_fw_dma_wait(struct ipw_priv *priv) ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_MASTER_DISABLED | IPW_RESET_REG_STOP_MASTER); - IPW_DEBUG_FW("<< dmaWaitSync \n"); + IPW_DEBUG_FW("<< dmaWaitSync\n"); return 0; } @@ -3034,7 +3034,7 @@ static int ipw_stop_master(struct ipw_priv *priv) { int rc; - IPW_DEBUG_TRACE(">> \n"); + IPW_DEBUG_TRACE(">>\n"); /* stop master. typical delay - 0 */ ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER); @@ -3053,7 +3053,7 @@ static int ipw_stop_master(struct ipw_priv *priv) static void ipw_arc_release(struct ipw_priv *priv) { - IPW_DEBUG_TRACE(">> \n"); + IPW_DEBUG_TRACE(">>\n"); mdelay(5); ipw_clear_bit(priv, IPW_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); @@ -3075,7 +3075,7 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) image = (__le16 *) data; - IPW_DEBUG_TRACE(">> \n"); + IPW_DEBUG_TRACE(">>\n"); rc = ipw_stop_master(priv); @@ -3189,7 +3189,7 @@ static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len) u32 *virts[CB_NUMBER_OF_ELEMENTS_SMALL]; dma_addr_t phys[CB_NUMBER_OF_ELEMENTS_SMALL]; - IPW_DEBUG_TRACE("<< : \n"); + IPW_DEBUG_TRACE("<< :\n"); pool = pci_pool_create("ipw2200", priv->pci_dev, CB_MAX_LENGTH, 0, 0); if (!pool) { @@ -4475,7 +4475,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, case CMAS_ASSOCIATED:{ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, - "associated: '%s' %pM \n", + "associated: '%s' %pM\n", print_ssid(ssid, priv->essid, priv->essid_len), priv->bssid); @@ -4556,7 +4556,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, IPW_DL_ASSOC, "deauthenticated: '%s' " "%pM" - ": (0x%04X) - %s \n", + ": (0x%04X) - %s\n", print_ssid(ssid, priv-> essid, @@ -4607,7 +4607,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, - "disassociated: '%s' %pM \n", + "disassociated: '%s' %pM\n", print_ssid(ssid, priv->essid, priv->essid_len), priv->bssid); @@ -4645,7 +4645,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, switch (auth->state) { case CMAS_AUTHENTICATED: IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, - "authenticated: '%s' %pM \n", + "authenticated: '%s' %pM\n", print_ssid(ssid, priv->essid, priv->essid_len), priv->bssid); @@ -6918,7 +6918,7 @@ static u8 ipw_qos_current_mode(struct ipw_priv * priv) } else { mode = priv->ieee->mode; } - IPW_DEBUG_QOS("QoS network/card mode %d \n", mode); + IPW_DEBUG_QOS("QoS network/card mode %d\n", mode); return mode; } @@ -6958,7 +6958,7 @@ static int ipw_qos_handle_probe_response(struct ipw_priv *priv, &def_parameters_OFDM, size); if ((network->qos_data.active == 1) && (active_network == 1)) { - IPW_DEBUG_QOS("QoS was disabled call qos_activate \n"); + IPW_DEBUG_QOS("QoS was disabled call qos_activate\n"); schedule_work(&priv->qos_activate); } @@ -7535,7 +7535,7 @@ static int ipw_associate_network(struct ipw_priv *priv, return err; } - IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM \n", + IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM\n", print_ssid(ssid, priv->essid, priv->essid_len), priv->bssid); @@ -8786,7 +8786,7 @@ static int ipw_wx_set_freq(struct net_device *dev, } } - IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); + IPW_DEBUG_WX("SET Freq/Channel -> %d\n", fwrq->m); mutex_lock(&priv->mutex); ret = ipw_set_channel(priv, channel); mutex_unlock(&priv->mutex); @@ -8828,7 +8828,7 @@ static int ipw_wx_get_freq(struct net_device *dev, wrqu->freq.m = 0; mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel); + IPW_DEBUG_WX("GET Freq/Channel -> %d\n", priv->channel); return 0; } @@ -9223,7 +9223,7 @@ static int ipw_wx_get_sens(struct net_device *dev, wrqu->sens.value = priv->roaming_threshold; mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("GET roaming threshold -> %s %d \n", + IPW_DEBUG_WX("GET roaming threshold -> %s %d\n", wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); return 0; @@ -9351,7 +9351,7 @@ static int ipw_wx_get_rate(struct net_device *dev, wrqu->bitrate.value = priv->last_rate; wrqu->bitrate.fixed = (priv->config & CFG_FIXED_RATE) ? 1 : 0; mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); + IPW_DEBUG_WX("GET Rate -> %d\n", wrqu->bitrate.value); return 0; } @@ -9374,7 +9374,7 @@ static int ipw_wx_set_rts(struct net_device *dev, ipw_send_rts_threshold(priv, priv->rts_threshold); mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold); + IPW_DEBUG_WX("SET RTS Threshold -> %d\n", priv->rts_threshold); return 0; } @@ -9388,7 +9388,7 @@ static int ipw_wx_get_rts(struct net_device *dev, wrqu->rts.fixed = 0; /* no auto select */ wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value); + IPW_DEBUG_WX("GET RTS Threshold -> %d\n", wrqu->rts.value); return 0; } @@ -9438,7 +9438,7 @@ static int ipw_wx_get_txpow(struct net_device *dev, wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0; mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("GET TX Power -> %s %d \n", + IPW_DEBUG_WX("GET TX Power -> %s %d\n", wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); return 0; @@ -9464,7 +9464,7 @@ static int ipw_wx_set_frag(struct net_device *dev, ipw_send_frag_threshold(priv, wrqu->frag.value); mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value); + IPW_DEBUG_WX("SET Frag Threshold -> %d\n", wrqu->frag.value); return 0; } @@ -9478,7 +9478,7 @@ static int ipw_wx_get_frag(struct net_device *dev, wrqu->frag.fixed = 0; /* no auto select */ wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS); mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value); + IPW_DEBUG_WX("GET Frag Threshold -> %d\n", wrqu->frag.value); return 0; } @@ -9542,7 +9542,7 @@ static int ipw_wx_get_retry(struct net_device *dev, } mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("GET retry -> %d \n", wrqu->retry.value); + IPW_DEBUG_WX("GET retry -> %d\n", wrqu->retry.value); return 0; } -- cgit v1.2.3 From 2b068618031a91929c21410069f872178ec00329 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 22 Mar 2010 09:17:39 -0700 Subject: iwlwifi: merge module parameters into single place Module parameters used to be defined in both iwl-5000.c and iwl-4965.c, after the code re-structure, merge into iwl-agn.c for easy to read and maintenance. Number of module parameters are deprecated after this merge. These are also scheduled for removal by 2.6.40. The current supported parameters are: parm: debug50:50XX debug output mask (deprecated) (uint) parm: debug:debug output mask (uint) parm: swcrypto50:using crypto in software (default 0 [hardware]) (deprecated) (bool) parm: swcrypto:using crypto in software (default 0 [hardware]) (int) parm: queues_num50:number of hw queues in 50xx series (deprecated) (int) parm: queues_num:number of hw queues. (int) parm: 11n_disable50:disable 50XX 11n functionality (deprecated) (int) parm: 11n_disable:disable 11n functionality (int) parm: amsdu_size_8K50:enable 8K amsdu size in 50XX series (deprecated) (int) parm: amsdu_size_8K:enable 8K amsdu size (int) parm: fw_restart50:restart firmware in case of error (deprecated) (int) parm: fw_restart:restart firmware in case of error (int) parm: disable_hw_scan:disable hardware scanning (default 0) (int) Remove "antenna" module parameter, it is not being used in "agn" driver. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-4965.c | 29 +---------------------------- drivers/net/wireless/iwlwifi/iwl-5000.c | 13 ------------- drivers/net/wireless/iwlwifi/iwl-agn.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 41 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 1808c976e504..083983a9d697 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -61,14 +61,6 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv); #define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode" #define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api) - -/* module parameters */ -static struct iwl_mod_params iwl4965_mod_params = { - .amsdu_size_8K = 1, - .restart_fw = 1, - /* the rest are 0 by default */ -}; - /* check contents of special bootstrap uCode SRAM */ static int iwl4965_verify_bsm(struct iwl_priv *priv) { @@ -2245,7 +2237,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .ops = &iwl4965_ops, .num_of_queues = IWL49_NUM_QUEUES, .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, - .mod_params = &iwl4965_mod_params, + .mod_params = &iwlagn_mod_params, .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_ABC, .pll_cfg_val = 0, @@ -2265,22 +2257,3 @@ struct iwl_cfg iwl4965_agn_cfg = { /* Module firmware */ MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); -module_param_named(antenna, iwl4965_mod_params.antenna, int, S_IRUGO); -MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); -module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, S_IRUGO); -MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); -module_param_named( - disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, S_IRUGO); -MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); - -module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, S_IRUGO); -MODULE_PARM_DESC(queues_num, "number of hw queues."); -/* 11n */ -module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, S_IRUGO); -MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); -module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, - int, S_IRUGO); -MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); - -module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, S_IRUGO); -MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error"); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 5ca451722d19..ecc302e4c205 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -585,16 +585,3 @@ struct iwl_cfg iwl5150_abg_cfg = { MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); - -module_param_named(swcrypto50, iwlagn_mod_params.sw_crypto, bool, S_IRUGO); -MODULE_PARM_DESC(swcrypto50, - "using software crypto engine (default 0 [hardware])\n"); -module_param_named(queues_num50, iwlagn_mod_params.num_of_queues, int, S_IRUGO); -MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); -module_param_named(11n_disable50, iwlagn_mod_params.disable_11n, int, S_IRUGO); -MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality"); -module_param_named(amsdu_size_8K50, iwlagn_mod_params.amsdu_size_8K, - int, S_IRUGO); -MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series"); -module_param_named(fw_restart50, iwlagn_mod_params.restart_fw, int, S_IRUGO); -MODULE_PARM_DESC(fw_restart50, "restart firmware in case of error"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b431e9254c06..8262f43df1cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3921,3 +3921,33 @@ module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "debug output mask"); #endif +module_param_named(swcrypto50, iwlagn_mod_params.sw_crypto, bool, S_IRUGO); +MODULE_PARM_DESC(swcrypto50, + "using crypto in software (default 0 [hardware]) (deprecated)"); +module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO); +MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); +module_param_named(queues_num50, + iwlagn_mod_params.num_of_queues, int, S_IRUGO); +MODULE_PARM_DESC(queues_num50, + "number of hw queues in 50xx series (deprecated)"); +module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO); +MODULE_PARM_DESC(queues_num, "number of hw queues."); +module_param_named(11n_disable50, iwlagn_mod_params.disable_11n, int, S_IRUGO); +MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality (deprecated)"); +module_param_named(11n_disable, iwlagn_mod_params.disable_11n, int, S_IRUGO); +MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); +module_param_named(amsdu_size_8K50, iwlagn_mod_params.amsdu_size_8K, + int, S_IRUGO); +MODULE_PARM_DESC(amsdu_size_8K50, + "enable 8K amsdu size in 50XX series (deprecated)"); +module_param_named(amsdu_size_8K, iwlagn_mod_params.amsdu_size_8K, + int, S_IRUGO); +MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); +module_param_named(fw_restart50, iwlagn_mod_params.restart_fw, int, S_IRUGO); +MODULE_PARM_DESC(fw_restart50, + "restart firmware in case of error (deprecated)"); +module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO); +MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); +module_param_named( + disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); +MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); -- cgit v1.2.3 From bed2263feb10ea29b2696030cdec2eea611caf14 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 22 Mar 2010 14:42:03 -0700 Subject: iwlwifi: remove irrelevant comments Removing irrelevant comments from iwl-agn.c Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8262f43df1cf..8b66010a2e82 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -83,13 +83,6 @@ MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_LICENSE("GPL"); MODULE_ALIAS("iwl4965"); -/*************** STATION TABLE MANAGEMENT **** - * mac80211 should be examined to determine if sta_info is duplicating - * the functionality provided here - */ - -/**************************************************************/ - /** * iwl_commit_rxon - commit staging_rxon to hardware * -- cgit v1.2.3 From 6aac74b40d5828c6f6b24974580aa43d7bee905c Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 22 Mar 2010 19:33:41 -0700 Subject: iwlwifi: clear rxq->queue in queue reset In iwl_rx_queue_reset(), we didn't clear the rxq->queue[]. This might cause the same rxb appears on multiple places in rxq->queue. Although this won't cause any problem because of the read and write pointers protection in rxq, we'd better clear it to avoid misleading. Signed-off-by: Zhu Yi Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 1d2e84c1fad5..6fe1d937187b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -403,6 +403,9 @@ void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) list_add_tail(&rxq->pool[i].list, &rxq->rx_used); } + for (i = 0; i < RX_QUEUE_SIZE; i++) + rxq->queue[i] = NULL; + /* Set us so that we have processed and used all buffers, but have * not restocked the Rx queue with fresh buffers */ rxq->read = rxq->write = 0; @@ -538,11 +541,13 @@ void iwlagn_rx_queue_restock(struct iwl_priv *priv) struct list_head *element; struct iwl_rx_mem_buffer *rxb; unsigned long flags; - int write; spin_lock_irqsave(&rxq->lock, flags); - write = rxq->write & ~0x7; while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { + /* The overwritten rxb must be a used one */ + rxb = rxq->queue[rxq->write]; + BUG_ON(rxb && rxb->page); + /* Get next free Rx buffer, remove from free list */ element = rxq->rx_free.next; rxb = list_entry(element, struct iwl_rx_mem_buffer, list); @@ -635,6 +640,7 @@ void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) spin_unlock_irqrestore(&rxq->lock, flags); + BUG_ON(rxb->page); rxb->page = page; /* Get physical address of the RB */ rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, -- cgit v1.2.3 From b744cb79aec7d95905943c0bc64699eb02de143b Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 23 Mar 2010 11:37:59 -0700 Subject: iwlwifi: code cleanup for generic defines Some defines used by all agn devices, but the definitions were in iwl-4965-hw.h, move those to iwl-agn-hw.h which is the better place for those. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 5 ----- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 24 ------------------------ drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-hw.h | 16 ++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + 9 files changed, 25 insertions(+), 36 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 074f42a7dcad..91bcb4e3cdfb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -71,10 +71,6 @@ #include "iwl-eeprom.h" -/* Time constants */ -#define SHORT_SLOT_TIME 9 -#define LONG_SLOT_TIME 20 - /* RSSI to dBm */ #define IWL39_RSSI_OFFSET 95 @@ -230,7 +226,6 @@ struct iwl3945_eeprom { /* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */ #define IWL39_NUM_QUEUES 5 -#define IWL_NUM_SCAN_RATES (2) #define IWL_DEFAULT_TX_RETRY 15 diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 67ef562e8db1..cd4b61ae25b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -81,26 +81,6 @@ */ #define IWL49_FIRST_AMPDU_QUEUE 7 -/* Time constants */ -#define SHORT_SLOT_TIME 9 -#define LONG_SLOT_TIME 20 - -/* RSSI to dBm */ -#define IWL49_RSSI_OFFSET 44 - - -/* PCI registers */ -#define PCI_CFG_RETRY_TIMEOUT 0x041 - -/* PCI register values */ -#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 -#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 - -#define IWL_NUM_SCAN_RATES (2) - -#define IWL_DEFAULT_TX_RETRY 15 - - /* Sizes and addresses for instruction and data memory (SRAM) in * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ #define IWL49_RTC_INST_LOWER_BOUND (0x000000) @@ -393,10 +373,6 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr) * location(s) in command (struct iwl4965_txpowertable_cmd). */ -/* Limit range of txpower output target to be between these values */ -#define IWL_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm = 1 milliwatt */ -#define IWL_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */ - /** * When MIMO is used (2 transmitters operating simultaneously), driver should * limit each transmitter to deliver a max of 3 dB below the regulatory limit diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 083983a9d697..a5122a60d631 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2086,7 +2086,7 @@ static int iwl4965_calc_rssi(struct iwl_priv *priv, /* dBm = max_rssi dB - agc dB - constant. * Higher AGC (higher radio gain) means lower signal. */ - return max_rssi - agc - IWL49_RSSI_OFFSET; + return max_rssi - agc - IWLAGN_RSSI_OFFSET; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 6e331f502e14..28bc8f8ba981 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -254,7 +254,7 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, /* dBm = max_rssi dB - agc dB - constant. * Higher AGC (higher radio gain) means lower signal. */ - return max_rssi - agc - IWL49_RSSI_OFFSET; + return max_rssi - agc - IWLAGN_RSSI_OFFSET; } struct iwl_hcmd_ops iwlagn_hcmd = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index e2ad870bb348..f9a3fbb6338f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h @@ -78,6 +78,22 @@ #define IWLAGN_RTC_DATA_SIZE (IWLAGN_RTC_DATA_UPPER_BOUND - \ IWLAGN_RTC_DATA_LOWER_BOUND) +/* RSSI to dBm */ +#define IWLAGN_RSSI_OFFSET 44 + +/* PCI registers */ +#define PCI_CFG_RETRY_TIMEOUT 0x041 + +/* PCI register values */ +#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 +#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 + +#define IWLAGN_DEFAULT_TX_RETRY 15 + +/* Limit range of txpower output target to be between these values */ +#define IWLAGN_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm: 1 milliwatt */ +#define IWLAGN_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */ + /* EEPROM */ #define IWLAGN_EEPROM_IMG_SIZE 2048 diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 257e4aff3d96..ad6cb1b38eea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -404,7 +404,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, if (ieee80211_is_probe_resp(fc)) data_retry_limit = 3; else - data_retry_limit = IWL_DEFAULT_TX_RETRY; + data_retry_limit = IWLAGN_DEFAULT_TX_RETRY; tx_cmd->data_retry_limit = data_retry_limit; /* Set retry limit on RTS packets */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8b66010a2e82..ef5690a83b35 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3368,7 +3368,7 @@ static int iwl_init_drv(struct iwl_priv *priv) /* Set the tx_power_user_lmt to the lowest power level * this value will get overwritten by channel max power avg * from eeprom */ - priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MIN; + priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN; ret = iwl_init_channel_map(priv); if (ret) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 38d19c11c47e..ff7f5c7b8961 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1376,10 +1376,11 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) int ret = 0; s8 prev_tx_power = priv->tx_power_user_lmt; - if (tx_power < IWL_TX_POWER_TARGET_POWER_MIN) { - IWL_WARN(priv, "Requested user TXPOWER %d below lower limit %d.\n", + if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) { + IWL_WARN(priv, + "Requested user TXPOWER %d below lower limit %d.\n", tx_power, - IWL_TX_POWER_TARGET_POWER_MIN); + IWLAGN_TX_POWER_TARGET_POWER_MIN); return -EINVAL; } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 7f38d2d9b575..4319bda487d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -43,6 +43,7 @@ #include "iwl-debug.h" #include "iwl-4965-hw.h" #include "iwl-3945-hw.h" +#include "iwl-agn-hw.h" #include "iwl-led.h" #include "iwl-power.h" #include "iwl-agn-rs.h" -- cgit v1.2.3 From 91dd6c27a29f97d81d2f71651d3b6bb55a4c1788 Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Wed, 24 Mar 2010 14:19:58 -0700 Subject: iwlwifi: remove trailing space in messages Includes minor improvements in debugging messages in iwl-4965.c, function iwl4965_is_temp_calib_needed(). Signed-off-by: Frans Pop Cc: Zhu Yi Cc: Reinette Chatre Cc: Intel Linux Wireless Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 12 ++++++------ drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-calib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-io.h | 2 +- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 12 ++++++------ drivers/net/wireless/iwlwifi/iwl-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 8 ++++---- 16 files changed, 36 insertions(+), 36 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 605aca4c78c8..9e411dc0e5e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -341,7 +341,7 @@ void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 s struct ieee80211_supported_band *sband; int i; - IWL_DEBUG_INFO(priv, "enter \n"); + IWL_DEBUG_INFO(priv, "enter\n"); if (sta_id == priv->hw_params.bcast_sta_id) goto out; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 2c16c5c10bc5..e81577b1a253 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -486,7 +486,7 @@ static void _iwl3945_dbg_report_frame(struct iwl_priv *priv, * but you can hack it to show more, if you'd like to. */ if (dataframe) IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " - "len=%u, rssi=%d, chnl=%d, rate=%d, \n", + "len=%u, rssi=%d, chnl=%d, rate=%d,\n", title, le16_to_cpu(fc), header->addr1[5], length, rssi, channel, rate); else { @@ -998,7 +998,7 @@ static void iwl3945_nic_config(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); if (rev_id & PCI_CFG_REV_ID_BIT_RTP) - IWL_DEBUG_INFO(priv, "RTP type \n"); + IWL_DEBUG_INFO(priv, "RTP type\n"); else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n"); iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index a5122a60d631..9a220d415449 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -410,7 +410,7 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, sizeof(cmd), &cmd); if (ret) IWL_DEBUG_CALIB(priv, "fail sending cmd " - "REPLY_PHY_CALIBRATION_CMD \n"); + "REPLY_PHY_CALIBRATION_CMD\n"); /* TODO we might want recalculate * rx_chain in rxon cmd */ @@ -1612,19 +1612,19 @@ static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv) /* get absolute value */ if (temp_diff < 0) { - IWL_DEBUG_POWER(priv, "Getting cooler, delta %d, \n", temp_diff); + IWL_DEBUG_POWER(priv, "Getting cooler, delta %d\n", temp_diff); temp_diff = -temp_diff; } else if (temp_diff == 0) - IWL_DEBUG_POWER(priv, "Same temp, \n"); + IWL_DEBUG_POWER(priv, "Temperature unchanged\n"); else - IWL_DEBUG_POWER(priv, "Getting warmer, delta %d, \n", temp_diff); + IWL_DEBUG_POWER(priv, "Getting warmer, delta %d\n", temp_diff); if (temp_diff < IWL_TEMPERATURE_THRESHOLD) { - IWL_DEBUG_POWER(priv, "Thermal txpower calib not needed\n"); + IWL_DEBUG_POWER(priv, " => thermal txpower calib not needed\n"); return 0; } - IWL_DEBUG_POWER(priv, "Thermal txpower calib needed\n"); + IWL_DEBUG_POWER(priv, " => thermal txpower calib needed\n"); return 1; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 6fe1d937187b..49e20f1acb7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -851,7 +851,7 @@ static void iwlagn_dbg_report_frame(struct iwl_priv *priv, * but you can hack it to show more, if you'd like to. */ if (dataframe) IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " - "len=%u, rssi=%d, chnl=%d, rate=%u, \n", + "len=%u, rssi=%d, chnl=%d, rate=%u,\n", title, le16_to_cpu(fc), header->addr1[5], length, rssi, channel, bitrate); else { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index bcae6a088106..0f881947627b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2009,7 +2009,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, /* rates available for this association, and for modulation mode */ rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type); - IWL_DEBUG_RATE(priv, "mask 0x%04X \n", rate_mask); + IWL_DEBUG_RATE(priv, "mask 0x%04X\n", rate_mask); /* mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index ad6cb1b38eea..a76e14351b5a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -723,9 +723,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); - IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", + IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", le16_to_cpu(out_cmd->hdr.sequence)); - IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); + IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); @@ -1289,7 +1289,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, (unsigned long long)le64_to_cpu(ba_resp->bitmap), ba_resp->scd_flow, ba_resp->scd_ssn); - IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx \n", + IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx\n", agg->start_idx, (unsigned long long)agg->bitmap); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ef5690a83b35..629cbf38aa9b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -181,7 +181,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); return ret; } - IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON. \n"); + IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); iwl_clear_ucode_stations(priv, false); iwl_restore_stations(priv); @@ -2303,7 +2303,7 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv) { int ret = 0; - IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter \n"); + IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n"); ret = iwl_set_hw_ready(priv); if (priv->hw_ready) @@ -3067,7 +3067,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, iwl_restore_wepkeys(priv); /* Initialize rate scaling */ - IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM \n", + IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", sta->addr); iwl_rs_rate_init(priv, sta, sta_id); diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 845831ac053e..dbb50a8e0ce3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -592,7 +592,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); if (!rx_enable_time) { - IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0! \n"); + IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0!\n"); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index ff7f5c7b8961..f09bff823ab6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1801,7 +1801,7 @@ static void iwl_ht_conf(struct iwl_priv *priv, struct iwl_ht_config *ht_conf = &priv->current_ht_config; struct ieee80211_sta *sta; - IWL_DEBUG_MAC80211(priv, "enter: \n"); + IWL_DEBUG_MAC80211(priv, "enter:\n"); if (!ht_conf->is_ht) return; @@ -2366,7 +2366,7 @@ int iwl_alloc_txq_mem(struct iwl_priv *priv) sizeof(struct iwl_tx_queue) * priv->cfg->num_of_queues, GFP_KERNEL); if (!priv->txq) { - IWL_ERR(priv, "Not enough memory for txq \n"); + IWL_ERR(priv, "Not enough memory for txq\n"); return -ENOMEM; } return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 73681c4fefe7..51f89e7ba681 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -169,7 +169,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) mutex_lock(&priv->sync_cmd_mutex); set_bit(STATUS_HCMD_ACTIVE, &priv->status); - IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s \n", + IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", get_cmd_string(cmd->id)); cmd_idx = iwl_enqueue_hcmd(priv, cmd); @@ -191,7 +191,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", + IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", get_cmd_string(cmd->id)); ret = -ETIMEDOUT; goto cancel; diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index c719baf2585a..4f54a5f71cd5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -297,7 +297,7 @@ static inline u32 __iwl_read_direct32(const char *f, u32 l, struct iwl_priv *priv, u32 reg) { u32 value = _iwl_read_direct32(priv, reg); - IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value, + IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d\n", reg, value, f, l); return value; } diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index e0581a771aab..2655dbdc8175 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -874,7 +874,7 @@ void iwl_tt_initialize(struct iwl_priv *priv) int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); struct iwl_tt_trans *transaction; - IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling \n"); + IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n"); memset(tt, 0, sizeof(struct iwl_tt_mgmt)); diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 5ecfc7f6ff43..0daa1c9f1c6b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -453,7 +453,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, added++; } - IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added); + IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); return added; } diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 9c28ad7a2de1..e34ac0355c75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -71,7 +71,7 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) || ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) && (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) { - IWL_ERR(priv, "Requested station info for sta %d before ready. \n", + IWL_ERR(priv, "Requested station info for sta %d before ready.\n", ret); ret = IWL_INVALID_STATION; } @@ -143,7 +143,7 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv, sta_id); break; case ADD_STA_MODIFY_NON_EXIST_STA: - IWL_ERR(priv, "Attempting to modify non-existing station %d \n", + IWL_ERR(priv, "Attempting to modify non-existing station %d\n", sta_id); break; default: @@ -571,7 +571,7 @@ static int iwl_remove_station(struct iwl_priv *priv, struct ieee80211_sta *sta) if (!iwl_is_ready(priv)) { IWL_DEBUG_INFO(priv, - "Unable to remove station %pM, device not ready. \n", + "Unable to remove station %pM, device not ready.\n", sta->addr); /* * It is typical for stations to be removed when we are @@ -668,7 +668,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force) } else { for (i = 0; i < priv->hw_params.max_stations; i++) { if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { - IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d \n", i); + IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i); priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; cleared = true; } @@ -1105,7 +1105,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; if (iwl_is_rfkill(priv)) { - IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled. \n"); + IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n"); spin_unlock_irqrestore(&priv->sta_lock, flags); return 0; } @@ -1207,7 +1207,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, return ret; if (init) { - IWL_DEBUG_INFO(priv, "init LQ command complete, clearing sta addition status for sta %d \n", + IWL_DEBUG_INFO(priv, "init LQ command complete, clearing sta addition status for sta %d\n", lq->sta_id); spin_lock_irqsave(&priv->sta_lock, flags_spin); priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 91f9c89b1b6d..65090d386a53 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -579,7 +579,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) if (!(meta->flags & CMD_ASYNC)) { clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", + IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", get_cmd_string(cmd->hdr.cmd)); wake_up_interruptible(&priv->wait_command_queue); } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 24c240d53f5c..4d0394b3fb59 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -597,9 +597,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) txq->need_update = 0; } - IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", + IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", le16_to_cpu(out_cmd->hdr.sequence)); - IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); + IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd)); iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, ieee80211_hdrlen(fc)); @@ -1937,7 +1937,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, added++; } - IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added); + IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); return added; } @@ -3401,7 +3401,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, } /* Initialize rate scaling */ - IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM \n", + IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", sta->addr); iwl3945_rs_rate_init(priv, sta, sta_id); -- cgit v1.2.3 From f18d4463d092162f34a8bd226505627ceeac3e8a Mon Sep 17 00:00:00 2001 From: Luis Correia Date: Sat, 3 Apr 2010 12:49:53 +0100 Subject: rt2x00: remove MCU requests for SoC platforms The ralink SoC platforms do not have an MCU. Signed-off-by: Luis Correia Acked-by: Ivo van Doorn Signed-off-by: Gertjan van Wingerde --- drivers/net/wireless/rt2x00/rt2800pci.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index ce7e88ecbb00..1df2d44a6158 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -60,6 +60,12 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) unsigned int i; u32 reg; + /* + * SOC devices don't support MCU requests. + */ + if (rt2x00_is_soc(rt2x00dev)) + return; + for (i = 0; i < 200; i++) { rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); -- cgit v1.2.3 From 22bedad3ce112d5ca1eaf043d4990fa2ed698c87 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 1 Apr 2010 21:22:57 +0000 Subject: net: convert multicast list to list_head Converts the list and the core manipulating with it to be the same as uc_list. +uses two functions for adding/removing mc address (normal and "global" variant) instead of a function parameter. +removes dev_mcast.c completely. +exposes netdev_hw_addr_list_* macros along with __hw_addr_* functions for manipulation with lists on a sandbox (used in bonding and 80211 drivers) Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/wireless/adm8211.c | 12 +++++------- drivers/net/wireless/ath/ar9170/main.c | 14 +++++--------- drivers/net/wireless/ath/ath5k/base.c | 17 +++++++---------- drivers/net/wireless/libertas/main.c | 12 ++++++------ drivers/net/wireless/libertas_tf/main.c | 14 ++++++-------- drivers/net/wireless/mwl8k.c | 24 ++++++++++++------------ drivers/net/wireless/orinoco/hw.c | 6 +++--- drivers/net/wireless/orinoco/hw.h | 1 - drivers/net/wireless/ray_cs.c | 12 ++++++------ drivers/net/wireless/rndis_wlan.c | 6 +++--- drivers/net/wireless/rtl818x/rtl8180_dev.c | 6 +++--- drivers/net/wireless/rtl818x/rtl8187_dev.c | 4 ++-- drivers/net/wireless/wl12xx/wl1271_main.c | 25 ++++++++++--------------- drivers/net/wireless/zd1201.c | 6 +++--- drivers/net/wireless/zd1211rw/zd_mac.c | 13 +++++-------- 15 files changed, 76 insertions(+), 96 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 547912e6843f..2277998b7264 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -1317,21 +1317,19 @@ static void adm8211_bss_info_changed(struct ieee80211_hw *dev, } static u64 adm8211_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) + struct netdev_hw_addr_list *mc_list) { - unsigned int bit_nr, i; + unsigned int bit_nr; u32 mc_filter[2]; + struct netdev_hw_addr *ha; mc_filter[1] = mc_filter[0] = 0; - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + netdev_hw_addr_list_for_each(ha, mc_list) { + bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; bit_nr &= 0x3F; mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - mclist = mclist->next; } return mc_filter[0] | ((u64)(mc_filter[1]) << 32); diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 257c734733d1..b43d4b006d7e 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -2045,21 +2045,17 @@ out: return err; } -static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, - struct dev_addr_list *mclist) +static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, + struct netdev_hw_addr_list *mc_list) { u64 mchash; - int i; + struct netdev_hw_addr *ha; /* always get broadcast frames */ mchash = 1ULL << (0xff >> 2); - for (i = 0; i < mc_count; i++) { - if (WARN_ON(!mclist)) - break; - mchash |= 1ULL << (mclist->dmi_addr[5] >> 2); - mclist = mclist->next; - } + netdev_hw_addr_list_for_each(ha, mc_list) + mchash |= 1ULL << (ha->addr[5] >> 2); return mchash; } diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index b142a78ed1e5..53a2340f52bc 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -230,7 +230,7 @@ static void ath5k_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); static int ath5k_config(struct ieee80211_hw *hw, u32 changed); static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mc_list); + struct netdev_hw_addr_list *mc_list); static void ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *new_flags, @@ -2999,22 +2999,20 @@ unlock: } static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) + struct netdev_hw_addr_list *mc_list) { u32 mfilt[2], val; - int i; u8 pos; + struct netdev_hw_addr *ha; mfilt[0] = 0; mfilt[1] = 1; - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; + netdev_hw_addr_list_for_each(ha, mc_list) { /* calculate XOR of eight 6-bit values */ - val = get_unaligned_le32(mclist->dmi_addr + 0); + val = get_unaligned_le32(ha->addr + 0); pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; - val = get_unaligned_le32(mclist->dmi_addr + 3); + val = get_unaligned_le32(ha->addr + 3); pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; pos &= 0x3f; mfilt[pos / 32] |= (1 << (pos % 32)); @@ -3022,8 +3020,7 @@ static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, * but not sure, needs testing, if we do use this we'd * neet to inform below to not reset the mcast */ /* ath5k_hw_set_mcast_filterindex(ah, - * mclist->dmi_addr[5]); */ - mclist = mclist->next; + * ha->addr[5]); */ } return ((u64)(mfilt[1]) << 32) | mfilt[0]; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 3c889f43d909..ff7b0d0cca56 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -318,7 +318,7 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd, struct net_device *dev, int nr_addrs) { int i = nr_addrs; - struct dev_mc_list *mc_list; + struct netdev_hw_addr *ha; int cnt; if ((dev->flags & (IFF_UP|IFF_MULTICAST)) != (IFF_UP|IFF_MULTICAST)) @@ -326,19 +326,19 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd, netif_addr_lock_bh(dev); cnt = netdev_mc_count(dev); - netdev_for_each_mc_addr(mc_list, dev) { - if (mac_in_list(cmd->maclist, nr_addrs, mc_list->dmi_addr)) { + netdev_for_each_mc_addr(ha, dev) { + if (mac_in_list(cmd->maclist, nr_addrs, ha->addr)) { lbs_deb_net("mcast address %s:%pM skipped\n", dev->name, - mc_list->dmi_addr); + ha->addr); cnt--; continue; } if (i == MRVDRV_MAX_MULTICAST_LIST_SIZE) break; - memcpy(&cmd->maclist[6*i], mc_list->dmi_addr, ETH_ALEN); + memcpy(&cmd->maclist[6*i], ha->addr, ETH_ALEN); lbs_deb_net("mcast address %s:%pM added to filter\n", dev->name, - mc_list->dmi_addr); + ha->addr); i++; cnt--; } diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 6ab30033c26c..c20eef6b95c2 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -367,22 +367,20 @@ static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed) } static u64 lbtf_op_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) + struct netdev_hw_addr_list *mc_list) { struct lbtf_private *priv = hw->priv; int i; + struct netdev_hw_addr *ha; + int mc_count = netdev_hw_addr_list_count(mc_list); if (!mc_count || mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) return mc_count; priv->nr_of_multicastmacaddr = mc_count; - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - memcpy(&priv->multicastlist[i], mclist->da_addr, - ETH_ALEN); - mclist = mclist->next; - } + i = 0; + netdev_hw_addr_list_for_each(ha, mc_list) + memcpy(&priv->multicastlist[i++], ha->addr, ETH_ALEN); return mc_count; } diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index ac65e13eb0de..6599fd15e675 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1938,11 +1938,15 @@ struct mwl8k_cmd_mac_multicast_adr { static struct mwl8k_cmd_pkt * __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti, - int mc_count, struct dev_addr_list *mclist) + struct netdev_hw_addr_list *mc_list) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_cmd_mac_multicast_adr *cmd; int size; + int mc_count = 0; + + if (mc_list) + mc_count = netdev_hw_addr_list_count(mc_list); if (allmulti || mc_count > priv->num_mcaddrs) { allmulti = 1; @@ -1963,17 +1967,13 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti, if (allmulti) { cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_ALL_MULTICAST); } else if (mc_count) { - int i; + struct netdev_hw_addr *ha; + int i = 0; cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); cmd->numaddr = cpu_to_le16(mc_count); - for (i = 0; i < mc_count && mclist; i++) { - if (mclist->da_addrlen != ETH_ALEN) { - kfree(cmd); - return NULL; - } - memcpy(cmd->addr[i], mclist->da_addr, ETH_ALEN); - mclist = mclist->next; + netdev_hw_addr_list_for_each(ha, mc_list) { + memcpy(cmd->addr[i], ha->addr, ETH_ALEN); } } @@ -3552,7 +3552,7 @@ mwl8k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) + struct netdev_hw_addr_list *mc_list) { struct mwl8k_cmd_pkt *cmd; @@ -3563,7 +3563,7 @@ static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, * we'll end up throwing this packet away and creating a new * one in mwl8k_configure_filter(). */ - cmd = __mwl8k_cmd_mac_multicast_adr(hw, 0, mc_count, mclist); + cmd = __mwl8k_cmd_mac_multicast_adr(hw, 0, mc_list); return (unsigned long)cmd; } @@ -3686,7 +3686,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, */ if (*total_flags & FIF_ALLMULTI) { kfree(cmd); - cmd = __mwl8k_cmd_mac_multicast_adr(hw, 1, 0, NULL); + cmd = __mwl8k_cmd_mac_multicast_adr(hw, 1, NULL); } if (cmd != NULL) { diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index 883b8f868626..9f657afaa3e5 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c @@ -1056,14 +1056,14 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, * group address if either we want to multicast, or if we were * multicasting and want to stop */ if (!promisc && (mc_count || priv->mc_count)) { - struct dev_mc_list *p; + struct netdev_hw_addr *ha; struct hermes_multicast mclist; int i = 0; - netdev_for_each_mc_addr(p, dev) { + netdev_for_each_mc_addr(ha, dev) { if (i == mc_count) break; - memcpy(mclist.addr[i++], p->dmi_addr, ETH_ALEN); + memcpy(mclist.addr[i++], ha->addr, ETH_ALEN); } err = hermes_write_ltv(hw, USER_BAP, diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h index 9799a1d14a63..97af71e79950 100644 --- a/drivers/net/wireless/orinoco/hw.h +++ b/drivers/net/wireless/orinoco/hw.h @@ -22,7 +22,6 @@ /* Forward declarations */ struct orinoco_private; -struct dev_addr_list; int determine_fw_capabilities(struct orinoco_private *priv, char *fw_name, size_t fw_name_len, u32 *hw_ver); diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 4f5bdb528ef7..54680a3a5acb 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -1875,17 +1875,17 @@ static void ray_update_multi_list(struct net_device *dev, int all) writeb(0xff, &pccs->var); local->num_multi = 0xff; } else { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int i = 0; /* Copy the kernel's list of MC addresses to card */ - netdev_for_each_mc_addr(dmi, dev) { - memcpy_toio(p, dmi->dmi_addr, ETH_ALEN); + netdev_for_each_mc_addr(ha, dev) { + memcpy_toio(p, ha->addr, ETH_ALEN); dev_dbg(&link->dev, "ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n", - dmi->dmi_addr[0], dmi->dmi_addr[1], - dmi->dmi_addr[2], dmi->dmi_addr[3], - dmi->dmi_addr[4], dmi->dmi_addr[5]); + ha->addr[0], ha->addr[1], + ha->addr[2], ha->addr[3], + ha->addr[4], ha->addr[5]); p += ETH_ALEN; i++; } diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index aceb95ef7274..8ab9f094747b 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1545,7 +1545,7 @@ static int remove_key(struct usbnet *usbdev, int index, const u8 *bssid) static void set_multicast_list(struct usbnet *usbdev) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - struct dev_mc_list *mclist; + struct netdev_hw_addr *ha; __le32 filter, basefilter; int ret; char *mc_addrs = NULL; @@ -1584,9 +1584,9 @@ static void set_multicast_list(struct usbnet *usbdev) return; } - netdev_for_each_mc_addr(mclist, usbdev->net) + netdev_for_each_mc_addr(ha, usbdev->net) memcpy(mc_addrs + i++ * ETH_ALEN, - mclist->dmi_addr, ETH_ALEN); + ha->addr, ETH_ALEN); } netif_addr_unlock_bh(usbdev->net); diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 2b928ecf47bd..fb8a62f2b9b4 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -723,10 +723,10 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, priv->rf->conf_erp(dev, info); } -static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, int mc_count, - struct dev_addr_list *mc_list) +static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, + struct netdev_hw_addr_list *mc_list) { - return mc_count; + return netdev_hw_addr_list_count(mc_list); } static void rtl8180_configure_filter(struct ieee80211_hw *dev, diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 0fb850e0c656..441d817ed489 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -1193,9 +1193,9 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, } static u64 rtl8187_prepare_multicast(struct ieee80211_hw *dev, - int mc_count, struct dev_addr_list *mc_list) + struct netdev_hw_addr_list *mc_list) { - return mc_count; + return netdev_hw_addr_list_count(mc_list); } static void rtl8187_configure_filter(struct ieee80211_hw *dev, diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 3daba6c0c77f..6036d0206fec 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1266,11 +1266,11 @@ struct wl1271_filter_params { u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN]; }; -static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, - struct dev_addr_list *mc_list) +static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, + struct netdev_hw_addr_list *mc_list) { struct wl1271_filter_params *fp; - int i; + struct netdev_hw_addr *ha; fp = kzalloc(sizeof(*fp), GFP_ATOMIC); if (!fp) { @@ -1279,21 +1279,16 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, } /* update multicast filtering parameters */ - fp->enabled = true; - if (mc_count > ACX_MC_ADDRESS_GROUP_MAX) { - mc_count = 0; - fp->enabled = false; - } - fp->mc_list_length = 0; - for (i = 0; i < mc_count; i++) { - if (mc_list->da_addrlen == ETH_ALEN) { + if (netdev_hw_addr_list_count(mc_list) > ACX_MC_ADDRESS_GROUP_MAX) { + fp->enabled = false; + } else { + fp->enabled = true; + netdev_hw_addr_list_for_each(ha, mc_list) { memcpy(fp->mc_list[fp->mc_list_length], - mc_list->da_addr, ETH_ALEN); + ha->addr, ETH_ALEN); fp->mc_list_length++; - } else - wl1271_warning("Unknown mc address length."); - mc_list = mc_list->next; + } } return (u64)(unsigned long)fp; diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 6917286edcae..74530b2d672c 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -875,7 +875,7 @@ static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev) static void zd1201_set_multicast(struct net_device *dev) { struct zd1201 *zd = netdev_priv(dev); - struct dev_mc_list *mc; + struct netdev_hw_addr *ha; unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI]; int i; @@ -883,8 +883,8 @@ static void zd1201_set_multicast(struct net_device *dev) return; i = 0; - netdev_for_each_mc_addr(mc, dev) - memcpy(reqbuf + i++ * ETH_ALEN, mc->dmi_addr, ETH_ALEN); + netdev_for_each_mc_addr(ha, dev) + memcpy(reqbuf + i++ * ETH_ALEN, ha->addr, ETH_ALEN); zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf, netdev_mc_count(dev) * ETH_ALEN, 0); } diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 00e09e26c826..6d95e4d74d7f 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -947,20 +947,17 @@ static void set_rx_filter_handler(struct work_struct *work) } static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) + struct netdev_hw_addr_list *mc_list) { struct zd_mac *mac = zd_hw_mac(hw); struct zd_mc_hash hash; - int i; + struct netdev_hw_addr *ha; zd_mc_clear(&hash); - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", mclist->dmi_addr); - zd_mc_add_addr(&hash, mclist->dmi_addr); - mclist = mclist->next; + netdev_hw_addr_list_for_each(ha, mc_list) { + dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", ha->addr); + zd_mc_add_addr(&hash, ha->addr); } return hash.low | ((u64)hash.high << 32); -- cgit v1.2.3 From 0a4528e2ae290104f2c343031976542f93ae229d Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Mon, 29 Mar 2010 21:34:39 +0100 Subject: Net: wireless: ath: fix macros coding style issue in hw.c This is a patch to the ath/hw.c file that fixes up a warning about macros found by the checkpatch.pl tool, that said that complex values should be enclosed in parenthesis. Signed-off-by: Luis de Bethencourt Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c index ecc9eb01f4fa..a8f81ea09f14 100644 --- a/drivers/net/wireless/ath/hw.c +++ b/drivers/net/wireless/ath/hw.c @@ -19,8 +19,8 @@ #include "ath.h" #include "reg.h" -#define REG_READ common->ops->read -#define REG_WRITE common->ops->write +#define REG_READ (common->ops->read) +#define REG_WRITE (common->ops->write) /** * ath_hw_set_bssid_mask - filter out bssids we listen -- cgit v1.2.3 From cfcfe4469cc39625cb8257355c00dd8f35f900aa Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Tue, 30 Mar 2010 16:44:33 +0100 Subject: ath: fix code readability in regd.c This is a patch to the ath/regd.c file that fixes two code readability issues. A space between to separate two defines and the indentation inside the ath_redg_is_eeprom_valid function. Signed-off-by: Luis de Bethencourt Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 04abd1f556b7..d5c23328aef1 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -51,6 +51,7 @@ #define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \ ATH9K_5GHZ_5470_5850 + /* This one skips what we call "mid band" */ #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \ ATH9K_5GHZ_5725_5850 @@ -361,7 +362,7 @@ EXPORT_SYMBOL(ath_reg_notifier_apply); static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg) { - u16 rd = ath_regd_get_eepromRD(reg); + u16 rd = ath_regd_get_eepromRD(reg); int i; if (rd & COUNTRY_ERD_FLAG) { -- cgit v1.2.3 From 8a64c0f6b7ec7f758c4ef445e49f479e27fa2236 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 6 Apr 2010 10:52:44 +0200 Subject: libertas/sdio: 8686: set ECSI bit for 1-bit transfers When operating in 1-bit mode, SDAT1 is used as dedicated interrupt line. However, the 8686 will only drive this line when the ECSI bit is set in the CCCR_IF register. Thanks to Alagu Sankar for pointing me in the right direction. Signed-off-by: Daniel Mack Cc: Alagu Sankar Cc: Volker Ernst Cc: Dan Williams Cc: John W. Linville Cc: Holger Schurig Cc: Bing Zhao Cc: libertas-dev@lists.infradead.org Cc: linux-wireless@vger.kernel.org Cc: linux-mmc@vger.kernel.org Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_sdio.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 7a73f625273b..33206a98a572 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include "host.h" #include "decl.h" @@ -942,6 +944,7 @@ static int if_sdio_probe(struct sdio_func *func, int ret, i; unsigned int model; struct if_sdio_packet *packet; + struct mmc_host *host = func->card->host; lbs_deb_enter(LBS_DEB_SDIO); @@ -1022,6 +1025,25 @@ static int if_sdio_probe(struct sdio_func *func, if (ret) goto disable; + /* For 1-bit transfers to the 8686 model, we need to enable the + * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 + * bit to allow access to non-vendor registers. */ + if ((card->model == IF_SDIO_MODEL_8686) && + (host->caps & MMC_CAP_SDIO_IRQ) && + (host->ios.bus_width == MMC_BUS_WIDTH_1)) { + u8 reg; + + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret); + if (ret) + goto release_int; + + reg |= SDIO_BUS_ECSI; + sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret); + if (ret) + goto release_int; + } + card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret); if (ret) goto release_int; -- cgit v1.2.3 From 5731858d0047cad309d334c4cd6ccb6199bf28fe Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Tue, 30 Mar 2010 23:50:23 +0200 Subject: rt2x00: Disable auto wakeup before waking up device. In all drivers ensure that auto wakeup is disabled before waking up the device. This is needed to prevent connection stability issues and problems in waking up the device. Based upon a patch from Ondrej Zary Signed-off-by: Gertjan van Wingerde Cc: Ondrej Zary Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 4 ++++ drivers/net/wireless/rt2x00/rt2500pci.c | 4 ++++ drivers/net/wireless/rt2x00/rt2500usb.c | 4 ++++ drivers/net/wireless/rt2x00/rt2800lib.c | 4 ++-- drivers/net/wireless/rt2x00/rt73usb.c | 6 +++--- 5 files changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index c22b04042d5c..08a4789fc2d8 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -525,6 +525,10 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); rt2x00pci_register_write(rt2x00dev, CSR20, reg); + } else { + rt2x00pci_register_read(rt2x00dev, CSR20, ®); + rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); + rt2x00pci_register_write(rt2x00dev, CSR20, reg); } rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 52bbcf1bd17c..d084d70e5fe2 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -573,6 +573,10 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); rt2x00pci_register_write(rt2x00dev, CSR20, reg); + } else { + rt2x00pci_register_read(rt2x00dev, CSR20, ®); + rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); + rt2x00pci_register_write(rt2x00dev, CSR20, reg); } rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index ee34c137e7cd..c1eec17fe186 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -648,6 +648,10 @@ static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev, rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 1); rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); + } else { + rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); + rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 0); + rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); } rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 18d4d8e4ae6b..d1694912310e 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1014,13 +1014,13 @@ static void rt2800_config_ps(struct rt2x00_dev *rt2x00dev, rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); } else { - rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); - rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); + + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); } } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 47f3e4a26d77..7ebe14b64fe8 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -860,15 +860,15 @@ static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev, rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, USB_MODE_SLEEP, REGISTER_TIMEOUT); } else { - rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, - USB_MODE_WAKEUP, REGISTER_TIMEOUT); - rt2x00usb_register_read(rt2x00dev, MAC_CSR11, ®); rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, 0); rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0); rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 0); rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg); + + rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, + USB_MODE_WAKEUP, REGISTER_TIMEOUT); } } -- cgit v1.2.3 From 9e18944601856c04c07dc569b87e9b98e8a9da5f Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Tue, 30 Mar 2010 23:50:25 +0200 Subject: rt2x00: Add wakeup interrupt handler to rt61pci. This is needed to wake up the device automatically for receiving beacons, and is required for proper powersave handling. Signed-off-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index e2da928dd9f0..ac69dbe5719b 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2117,6 +2117,14 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) } } +static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev) +{ + struct ieee80211_conf conf = { .flags = 0 }; + struct rt2x00lib_conf libconf = { .conf = &conf }; + + rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); +} + static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) { struct rt2x00_dev *rt2x00dev = dev_instance; @@ -2164,6 +2172,12 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff); + /* + * 4 - MCU Autowakeup interrupt. + */ + if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP)) + rt61pci_wakeup(rt2x00dev); + return IRQ_HANDLED; } -- cgit v1.2.3 From 4d66edc8b6c0622ed6df74709de65f70d1ca222f Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Tue, 30 Mar 2010 23:50:26 +0200 Subject: rt2x00: Add wakeup interrupt handler to rt2800pci. This is needed to wake up the device automatically for receiving beacons, and is required for proper powersave handling. Signed-off-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 1df2d44a6158..a2b37d38d400 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1015,6 +1015,14 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) } } +static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) +{ + struct ieee80211_conf conf = { .flags = 0 }; + struct rt2x00lib_conf libconf = { .conf = &conf }; + + rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); +} + static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) { struct rt2x00_dev *rt2x00dev = dev_instance; @@ -1039,6 +1047,9 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) rt2800pci_txdone(rt2x00dev); + if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) + rt2800pci_wakeup(rt2x00dev); + return IRQ_HANDLED; } -- cgit v1.2.3 From b409894f9d6961bd5feffb86ba1d8dbbebfb5b72 Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Wed, 31 Mar 2010 15:07:48 +0100 Subject: ath: fix coding style/readability in ath/ar9170 This is a patch to files in ath/ar9170 that fixes a set of warnings found by checkpatch.pl tool. A line over 80 characters, a few empty spaces before tab and a few empty characters before a new line. Signed-off-by: Luis de Bethencourt Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/cmd.h | 2 +- drivers/net/wireless/ath/ar9170/eeprom.h | 4 ++-- drivers/net/wireless/ath/ar9170/main.c | 11 ++++++----- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ar9170/cmd.h b/drivers/net/wireless/ath/ar9170/cmd.h index 826c45e6b274..ec8134b4b949 100644 --- a/drivers/net/wireless/ath/ar9170/cmd.h +++ b/drivers/net/wireless/ath/ar9170/cmd.h @@ -79,7 +79,7 @@ __regwrite_out : \ if (__nreg) { \ if (IS_ACCEPTING_CMD(__ar)) \ __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ - 8 * __nreg, \ + 8 * __nreg, \ (u8 *) &__ar->cmdbuf[1], \ 0, NULL); \ __nreg = 0; \ diff --git a/drivers/net/wireless/ath/ar9170/eeprom.h b/drivers/net/wireless/ath/ar9170/eeprom.h index d2c8cc83f1dd..6c4663883423 100644 --- a/drivers/net/wireless/ath/ar9170/eeprom.h +++ b/drivers/net/wireless/ath/ar9170/eeprom.h @@ -127,8 +127,8 @@ struct ar9170_eeprom { __le16 checksum; __le16 version; u8 operating_flags; -#define AR9170_OPFLAG_5GHZ 1 -#define AR9170_OPFLAG_2GHZ 2 +#define AR9170_OPFLAG_5GHZ 1 +#define AR9170_OPFLAG_2GHZ 2 u8 misc; __le16 reg_domain[2]; u8 mac_address[6]; diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 2daeaa5bcb88..fed6695ec04e 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -235,7 +235,7 @@ static void __ar9170_dump_txqueue(struct ar9170 *ar, wiphy_name(ar->hw->wiphy), skb_queue_len(queue)); skb_queue_walk(queue, skb) { - printk(KERN_DEBUG "index:%d => \n", i++); + printk(KERN_DEBUG "index:%d =>\n", i++); ar9170_print_txheader(ar, skb); } if (i != skb_queue_len(queue)) @@ -280,7 +280,7 @@ static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar) unsigned long flags; spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags); - printk(KERN_DEBUG "%s: A-MPDU tx_status queue => \n", + printk(KERN_DEBUG "%s: A-MPDU tx_status queue =>\n", wiphy_name(ar->hw->wiphy)); __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu); spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags); @@ -307,7 +307,7 @@ static void ar9170_recycle_expired(struct ar9170 *ar, if (time_is_before_jiffies(arinfo->timeout)) { #ifdef AR9170_QUEUE_DEBUG printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => " - "recycle \n", wiphy_name(ar->hw->wiphy), + "recycle\n", wiphy_name(ar->hw->wiphy), jiffies, arinfo->timeout); ar9170_print_txheader(ar, skb); #endif /* AR9170_QUEUE_DEBUG */ @@ -688,7 +688,8 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) /* firmware debug */ case 0xca: - printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, (char *)buf + 4); + printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, + (char *)buf + 4); break; case 0xcb: len -= 4; @@ -1727,7 +1728,7 @@ static void ar9170_tx(struct ar9170 *ar) printk(KERN_DEBUG "%s: queue %d full\n", wiphy_name(ar->hw->wiphy), i); - printk(KERN_DEBUG "%s: stuck frames: ===> \n", + printk(KERN_DEBUG "%s: stuck frames: ===>\n", wiphy_name(ar->hw->wiphy)); ar9170_dump_txqueue(ar, &ar->tx_pending[i]); ar9170_dump_txqueue(ar, &ar->tx_status[i]); -- cgit v1.2.3 From c81494d548d0735f13c04dd2c336cde470d1a5ae Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Wed, 31 Mar 2010 18:05:25 -0400 Subject: ath9k: rename symbols in enum ath9k_internal_frame_type to avoid confusion Symbols starting with "ATH9K_INT" are also used for interrupt mask. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.h | 6 +++--- drivers/net/wireless/ath/ath9k/virtual.c | 2 +- drivers/net/wireless/ath/ath9k/xmit.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 36083dde863d..3d8d40cdc99e 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -176,9 +176,9 @@ struct ath_rate_priv { #define ATH_TX_INFO_UNDERRUN (1 << 4) enum ath9k_internal_frame_type { - ATH9K_NOT_INTERNAL, - ATH9K_INT_PAUSE, - ATH9K_INT_UNPAUSE + ATH9K_IFT_NOT_INTERNAL, + ATH9K_IFT_PAUSE, + ATH9K_IFT_UNPAUSE }; int ath_rate_control_register(void); diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index a43fbf84dab9..e95aaa3f18f3 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c @@ -218,7 +218,7 @@ static int ath9k_send_nullfunc(struct ath_wiphy *aphy, memset(&txctl, 0, sizeof(struct ath_tx_control)); txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]]; - txctl.frame_type = ps ? ATH9K_INT_PAUSE : ATH9K_INT_UNPAUSE; + txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE; if (ath_tx_start(aphy->hw, skb, &txctl) != 0) goto exit; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 1d04ca86df56..b632c803ee1a 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1593,12 +1593,12 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, tx_info->pad[0] = 0; switch (txctl->frame_type) { - case ATH9K_NOT_INTERNAL: + case ATH9K_IFT_NOT_INTERNAL: break; - case ATH9K_INT_PAUSE: + case ATH9K_IFT_PAUSE: tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_PAUSE; /* fall through */ - case ATH9K_INT_UNPAUSE: + case ATH9K_IFT_UNPAUSE: tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_INTERNAL; break; } -- cgit v1.2.3 From 3069168c82d65f88e4ac76eda09baff02adfd743 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Wed, 31 Mar 2010 18:05:31 -0400 Subject: ath9k: move imask from sc to ah Add ah variable in the functions that didn't have it and used sc->imask. Replace sc->sc_ah with ah in those functions. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 - drivers/net/wireless/ath/ath9k/beacon.c | 35 ++++++++++--------- drivers/net/wireless/ath/ath9k/gpio.c | 15 +++------ drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 60 +++++++++++++++++---------------- 5 files changed, 56 insertions(+), 56 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index a581c365da6f..bdcd257ca7a4 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -480,7 +480,6 @@ struct ath_softc { bool ps_enabled; bool ps_idle; unsigned long ps_usecount; - enum ath9k_int imask; struct ath_config config; struct ath_rx rx; diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index b4a31a43a62c..22375a754718 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -524,6 +524,7 @@ static void ath9k_beacon_init(struct ath_softc *sc, static void ath_beacon_config_ap(struct ath_softc *sc, struct ath_beacon_config *conf) { + struct ath_hw *ah = sc->sc_ah; u32 nexttbtt, intval; /* NB: the beacon interval is kept internally in TU's */ @@ -539,15 +540,15 @@ static void ath_beacon_config_ap(struct ath_softc *sc, * prepare beacon frames. */ intval |= ATH9K_BEACON_ENA; - sc->imask |= ATH9K_INT_SWBA; + ah->imask |= ATH9K_INT_SWBA; ath_beaconq_config(sc); /* Set the computed AP beacon timers */ - ath9k_hw_set_interrupts(sc->sc_ah, 0); + ath9k_hw_set_interrupts(ah, 0); ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); + ath9k_hw_set_interrupts(ah, ah->imask); /* Clear the reset TSF flag, so that subsequent beacon updation will not reset the HW TSF. */ @@ -566,7 +567,8 @@ static void ath_beacon_config_ap(struct ath_softc *sc, static void ath_beacon_config_sta(struct ath_softc *sc, struct ath_beacon_config *conf) { - struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); struct ath9k_beacon_state bs; int dtimperiod, dtimcount, sleepduration; int cfpperiod, cfpcount; @@ -605,7 +607,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc, * Pull nexttbtt forward to reflect the current * TSF and calculate dtim+cfp state for the result. */ - tsf = ath9k_hw_gettsf64(sc->sc_ah); + tsf = ath9k_hw_gettsf64(ah); tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; num_beacons = tsftu / intval + 1; @@ -678,17 +680,18 @@ static void ath_beacon_config_sta(struct ath_softc *sc, /* Set the computed STA beacon timers */ - ath9k_hw_set_interrupts(sc->sc_ah, 0); - ath9k_hw_set_sta_beacon_timers(sc->sc_ah, &bs); - sc->imask |= ATH9K_INT_BMISS; - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); + ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_set_sta_beacon_timers(ah, &bs); + ah->imask |= ATH9K_INT_BMISS; + ath9k_hw_set_interrupts(ah, ah->imask); } static void ath_beacon_config_adhoc(struct ath_softc *sc, struct ath_beacon_config *conf, struct ieee80211_vif *vif) { - struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); u64 tsf; u32 tsftu, intval, nexttbtt; @@ -703,7 +706,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, else if (intval) nexttbtt = roundup(nexttbtt, intval); - tsf = ath9k_hw_gettsf64(sc->sc_ah); + tsf = ath9k_hw_gettsf64(ah); tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; do { nexttbtt += intval; @@ -719,20 +722,20 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, * self-linked tx descriptor and let the hardware deal with things. */ intval |= ATH9K_BEACON_ENA; - if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) - sc->imask |= ATH9K_INT_SWBA; + if (!(ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) + ah->imask |= ATH9K_INT_SWBA; ath_beaconq_config(sc); /* Set the computed ADHOC beacon timers */ - ath9k_hw_set_interrupts(sc->sc_ah, 0); + ath9k_hw_set_interrupts(ah, 0); ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); + ath9k_hw_set_interrupts(ah, ah->imask); /* FIXME: Handle properly when vif is NULL */ - if (vif && sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) + if (vif && ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) ath_beacon_start_adhoc(sc, vif); } diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index deab8beb0680..1e4578d303dd 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -283,22 +283,17 @@ static void ath9k_gen_timer_start(struct ath_hw *ah, u32 timer_next, u32 timer_period) { - struct ath_common *common = ath9k_hw_common(ah); - struct ath_softc *sc = (struct ath_softc *) common->priv; - ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); - if ((sc->imask & ATH9K_INT_GENTIMER) == 0) { + if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { ath9k_hw_set_interrupts(ah, 0); - sc->imask |= ATH9K_INT_GENTIMER; - ath9k_hw_set_interrupts(ah, sc->imask); + ah->imask |= ATH9K_INT_GENTIMER; + ath9k_hw_set_interrupts(ah, ah->imask); } } static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) { - struct ath_common *common = ath9k_hw_common(ah); - struct ath_softc *sc = (struct ath_softc *) common->priv; struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; ath9k_hw_gen_timer_stop(ah, timer); @@ -306,8 +301,8 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) /* if no timer is enabled, turn off interrupt mask */ if (timer_table->timer_mask.val == 0) { ath9k_hw_set_interrupts(ah, 0); - sc->imask &= ~ATH9K_INT_GENTIMER; - ath9k_hw_set_interrupts(ah, sc->imask); + ah->imask &= ~ATH9K_INT_GENTIMER; + ath9k_hw_set_interrupts(ah, ah->imask); } } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 6b03e1688b22..0ac7a80be082 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -478,6 +478,7 @@ struct ath_hw { struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; int16_t curchan_rad_index; + enum ath9k_int imask; u32 mask_reg; u32 imrs2_reg; u32 txok_interrupt_mask; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 67ca4e5a6017..c25216be616f 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -225,7 +225,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, ath_cache_conf_rate(sc, &hw->conf); ath_update_txpow(sc); - ath9k_hw_set_interrupts(ah, sc->imask); + ath9k_hw_set_interrupts(ah, ah->imask); ps_restore: ath9k_ps_restore(sc); @@ -434,7 +434,7 @@ void ath9k_tasklet(unsigned long data) ath_gen_timer_isr(sc->sc_ah); /* re-enable hardware interrupt */ - ath9k_hw_set_interrupts(ah, sc->imask); + ath9k_hw_set_interrupts(ah, ah->imask); ath9k_ps_restore(sc); } @@ -477,7 +477,7 @@ irqreturn_t ath_isr(int irq, void *dev) * value to insure we only process bits we requested. */ ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ - status &= sc->imask; /* discard unasked-for bits */ + status &= ah->imask; /* discard unasked-for bits */ /* * If there are no status bits set, then this interrupt was not @@ -518,7 +518,7 @@ irqreturn_t ath_isr(int irq, void *dev) * the interrupt. */ ath9k_hw_procmibevent(ah); - ath9k_hw_set_interrupts(ah, sc->imask); + ath9k_hw_set_interrupts(ah, ah->imask); } if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) @@ -536,7 +536,7 @@ chip_reset: if (sched) { /* turn off every interrupt except SWBA */ - ath9k_hw_set_interrupts(ah, (sc->imask & ATH9K_INT_SWBA)); + ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA)); tasklet_schedule(&sc->intr_tq); } @@ -887,7 +887,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) ath_beacon_config(sc, NULL); /* restart beacons */ /* Re-Enable interrupts */ - ath9k_hw_set_interrupts(ah, sc->imask); + ath9k_hw_set_interrupts(ah, ah->imask); /* Enable LED */ ath9k_hw_cfg_output(ah, ah->led_pin, @@ -977,7 +977,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) if (sc->sc_flags & SC_OP_BEACONS) ath_beacon_config(sc, NULL); /* restart beacons */ - ath9k_hw_set_interrupts(ah, sc->imask); + ath9k_hw_set_interrupts(ah, ah->imask); if (retry_tx) { int i; @@ -1162,23 +1162,23 @@ static int ath9k_start(struct ieee80211_hw *hw) } /* Setup our intr mask. */ - sc->imask = ATH9K_INT_RX | ATH9K_INT_TX + ah->imask = ATH9K_INT_RX | ATH9K_INT_TX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT) - sc->imask |= ATH9K_INT_GTT; + ah->imask |= ATH9K_INT_GTT; if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) - sc->imask |= ATH9K_INT_CST; + ah->imask |= ATH9K_INT_CST; ath_cache_conf_rate(sc, &hw->conf); sc->sc_flags &= ~SC_OP_INVALID; /* Disable BMISS interrupt when we're not associated */ - sc->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); - ath9k_hw_set_interrupts(ah, sc->imask); + ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); + ath9k_hw_set_interrupts(ah, ah->imask); ieee80211_wake_queues(hw); @@ -1372,14 +1372,15 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); struct ath_vif *avp = (void *)vif->drv_priv; enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; int ret = 0; mutex_lock(&sc->mutex); - if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) && + if (!(ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) && sc->nvifs > 0) { ret = -ENOBUFS; goto out; @@ -1414,19 +1415,19 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, sc->nvifs++; - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) + if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) ath9k_set_bssid_mask(hw); if (sc->nvifs > 1) goto out; /* skip global settings for secondary vif */ if (ic_opmode == NL80211_IFTYPE_AP) { - ath9k_hw_set_tsfadjust(sc->sc_ah, 1); + ath9k_hw_set_tsfadjust(ah, 1); sc->sc_flags |= SC_OP_TSF_RESET; } /* Set the device opmode */ - sc->sc_ah->opmode = ic_opmode; + ah->opmode = ic_opmode; /* * Enable MIB interrupts when there are hardware phy counters. @@ -1435,11 +1436,11 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, if ((vif->type == NL80211_IFTYPE_STATION) || (vif->type == NL80211_IFTYPE_ADHOC) || (vif->type == NL80211_IFTYPE_MESH_POINT)) { - sc->imask |= ATH9K_INT_MIB; - sc->imask |= ATH9K_INT_TSFOOR; + ah->imask |= ATH9K_INT_MIB; + ah->imask |= ATH9K_INT_TSFOOR; } - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); + ath9k_hw_set_interrupts(ah, ah->imask); if (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_ADHOC || @@ -1495,15 +1496,16 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, void ath9k_enable_ps(struct ath_softc *sc) { + struct ath_hw *ah = sc->sc_ah; + sc->ps_enabled = true; - if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { - sc->imask |= ATH9K_INT_TIM_TIMER; - ath9k_hw_set_interrupts(sc->sc_ah, - sc->imask); + if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { + if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) { + ah->imask |= ATH9K_INT_TIM_TIMER; + ath9k_hw_set_interrupts(ah, ah->imask); } } - ath9k_hw_setrxabort(sc->sc_ah, 1); + ath9k_hw_setrxabort(ah, 1); } static int ath9k_config(struct ieee80211_hw *hw, u32 changed) @@ -1580,10 +1582,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) PS_WAIT_FOR_CAB | PS_WAIT_FOR_PSPOLL_DATA | PS_WAIT_FOR_TX_ACK); - if (sc->imask & ATH9K_INT_TIM_TIMER) { - sc->imask &= ~ATH9K_INT_TIM_TIMER; + if (ah->imask & ATH9K_INT_TIM_TIMER) { + ah->imask &= ~ATH9K_INT_TIM_TIMER; ath9k_hw_set_interrupts(sc->sc_ah, - sc->imask); + ah->imask); } } } -- cgit v1.2.3 From 152d530d9edbb08424dc1b6561252597a7932c49 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Wed, 31 Mar 2010 18:05:37 -0400 Subject: ath9k: remove ah->mask_reg, it's never used properly ah->mask_reg was used to hold different data throughout the driver. ath9k_hw_init_interrupt_masks() used it to save the value written to AR_IMR. ath9k_hw_set_interrupts() used it to hold the interrupt mask as defined in enum ath9k_int. Those masks differ in many bits. Use ah->imask instead of ah->mask_reg in ath9k_hw_set_interrupts() and ath9k_hw_updatetxtriglevel(). That's what the code was meant to do. ah->imask is initialized in ath9k_start(), so we don't need to initialize it from ah->mask_reg. Once it's done, ah->mask_reg becomes write-only, so it's replaced with a local variable in ath9k_hw_init_interrupt_masks(). Signed-off-by: Pavel Roskin Reported-by: Julia Lawall Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 15 +++++++-------- drivers/net/wireless/ath/ath9k/hw.h | 1 - drivers/net/wireless/ath/ath9k/mac.c | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 77db932c3137..e716b600dec5 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1120,23 +1120,23 @@ static void ath9k_hw_init_chain_masks(struct ath_hw *ah) static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, enum nl80211_iftype opmode) { - ah->mask_reg = AR_IMR_TXERR | + u32 imr_reg = AR_IMR_TXERR | AR_IMR_TXURN | AR_IMR_RXERR | AR_IMR_RXORN | AR_IMR_BCNMISC; if (ah->config.rx_intr_mitigation) - ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; + imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; else - ah->mask_reg |= AR_IMR_RXOK; + imr_reg |= AR_IMR_RXOK; - ah->mask_reg |= AR_IMR_TXOK; + imr_reg |= AR_IMR_TXOK; if (opmode == NL80211_IFTYPE_AP) - ah->mask_reg |= AR_IMR_MIB; + imr_reg |= AR_IMR_MIB; - REG_WRITE(ah, AR_IMR, ah->mask_reg); + REG_WRITE(ah, AR_IMR, imr_reg); ah->imrs2_reg |= AR_IMR_S2_GTT; REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); @@ -2839,7 +2839,7 @@ EXPORT_SYMBOL(ath9k_hw_getisr); enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) { - u32 omask = ah->mask_reg; + enum ath9k_int omask = ah->imask; u32 mask, mask2; struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_common *common = ath9k_hw_common(ah); @@ -2911,7 +2911,6 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST); ah->imrs2_reg |= mask2; REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); - ah->mask_reg = ints; if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { if (ints & ATH9K_INT_TIM_TIMER) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 0ac7a80be082..97ebeba8a157 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -479,7 +479,6 @@ struct ath_hw { int16_t curchan_rad_index; enum ath9k_int imask; - u32 mask_reg; u32 imrs2_reg; u32 txok_interrupt_mask; u32 txerr_interrupt_mask; diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index e020b82a677e..4a2060e5a777 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -105,7 +105,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) if (ah->tx_trig_level >= ah->config.max_txtrig_level) return false; - omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL); + omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL); txcfg = REG_READ(ah, AR_TXCFG); curLevel = MS(txcfg, AR_FTRIG); -- cgit v1.2.3 From 32ffb1f4488b0727bcfc67a025becc0db3df7a17 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 31 Mar 2010 15:41:36 -0700 Subject: ath9k: fix compile error without debug enabled commits 8e6f5aa250d6013ec0d66f9f45f376678d3fc4ab and db1a052b73f7c97f9e8b21f3f19a92313ed2acb1 accidentally introduced compile errors that happens when ath9k debug is not enabled. This patch fixes the declaration of the inline stubs to resolve this. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 9551d8eb9453..b2af9de755e6 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -204,12 +204,13 @@ static inline void ath_debug_stat_rc(struct ath_softc *sc, static inline void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf) + struct ath_buf *bf, + struct ath_tx_status *ts) { } static inline void ath_debug_stat_rx(struct ath_softc *sc, - struct ath_buf *bf) + struct ath_rx_status *rs) { } -- cgit v1.2.3 From 497ad9adf44013dc9054f80c627acc44d4c90d37 Mon Sep 17 00:00:00 2001 From: Sujith Date: Thu, 1 Apr 2010 10:28:20 +0530 Subject: ath: Add a bus type field This can be used to store the bus types ( AHB/PCI/USB ). Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath.h | 13 ++++++++++--- drivers/net/wireless/ath/ath9k/ahb.c | 1 + drivers/net/wireless/ath/ath9k/htc_drv_init.c | 1 + drivers/net/wireless/ath/ath9k/pci.c | 1 + 4 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 71fc960814f0..1fbf6b1f9a7e 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -48,6 +48,12 @@ enum ath_device_state { ATH_HW_INITIALIZED, }; +enum ath_bus_type { + ATH_PCI, + ATH_AHB, + ATH_USB, +}; + struct reg_dmn_pair_mapping { u16 regDmnEnum; u16 reg_5ghz_ctl; @@ -73,9 +79,10 @@ struct ath_ops { struct ath_common; struct ath_bus_ops { - void (*read_cachesize)(struct ath_common *common, int *csz); - bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); - void (*bt_coex_prep)(struct ath_common *common); + enum ath_bus_type ath_bus_type; + void (*read_cachesize)(struct ath_common *common, int *csz); + bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); + void (*bt_coex_prep)(struct ath_common *common); }; struct ath_common { diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index ca4994f13151..85fdd26039c8 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -47,6 +47,7 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) } static struct ath_bus_ops ath_ahb_bus_ops = { + .ath_bus_type = ATH_AHB, .read_cachesize = ath_ahb_read_cachesize, .eeprom_read = ath_ahb_eeprom_read, }; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 90cfd9066abf..e268d458e7df 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -287,6 +287,7 @@ static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data) } static const struct ath_bus_ops ath9k_usb_bus_ops = { + .ath_bus_type = ATH_USB, .read_cachesize = ath_usb_read_cachesize, .eeprom_read = ath_usb_eeprom_read, }; diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 9441c6718a30..1ec836cf1c0d 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -88,6 +88,7 @@ static void ath_pci_bt_coex_prep(struct ath_common *common) } static const struct ath_bus_ops ath_pci_bus_ops = { + .ath_bus_type = ATH_PCI, .read_cachesize = ath_pci_read_cachesize, .eeprom_read = ath_pci_eeprom_read, .bt_coex_prep = ath_pci_bt_coex_prep, -- cgit v1.2.3 From ffa49f8209ef77ebf2cce0bbc129ca40064b8fb6 Mon Sep 17 00:00:00 2001 From: Sujith Date: Thu, 1 Apr 2010 10:28:23 +0530 Subject: ath9k_hw: Don't check devid for ath9k_htc For USB devices, this check is invalid. Remove the check so that new product IDs can be added. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 13 +++++++------ drivers/net/wireless/ath/ath9k/hw.h | 2 -- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index e716b600dec5..feae55a8124d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -547,7 +547,6 @@ static bool ath9k_hw_devid_supported(u16 devid) case AR9285_DEVID_PCIE: case AR5416_DEVID_AR9287_PCI: case AR5416_DEVID_AR9287_PCIE: - case AR9271_USB: case AR2427_DEVID_PCIE: return true; default: @@ -855,11 +854,13 @@ int ath9k_hw_init(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); int r = 0; - if (!ath9k_hw_devid_supported(ah->hw_version.devid)) { - ath_print(common, ATH_DBG_FATAL, - "Unsupported device ID: 0x%0x\n", - ah->hw_version.devid); - return -EOPNOTSUPP; + if (common->bus_ops->ath_bus_type != ATH_USB) { + if (!ath9k_hw_devid_supported(ah->hw_version.devid)) { + ath_print(common, ATH_DBG_FATAL, + "Unsupported device ID: 0x%0x\n", + ah->hw_version.devid); + return -EOPNOTSUPP; + } } ath9k_hw_init_defaults(ah); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 97ebeba8a157..b02a97c72c64 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -44,8 +44,6 @@ #define AR5416_AR9100_DEVID 0x000b -#define AR9271_USB 0x9271 - #define AR_SUBVENDOR_ID_NOG 0x0e11 #define AR_SUBVENDOR_ID_NEW_A 0x7065 #define AR5416_MAGIC 0x19641014 -- cgit v1.2.3 From e92119ca88691ac2239916d31c3dcecd10867521 Mon Sep 17 00:00:00 2001 From: Sujith Date: Thu, 1 Apr 2010 10:28:24 +0530 Subject: ath9k_htc: Add TL-WN422G v2 product ID Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index e584a2912993..3afc747ccfbf 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -21,6 +21,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { ATH9K_FW_USB_DEV(0x9271, "ar9271.fw"), + ATH9K_FW_USB_DEV(0x1006, "ar9271.fw"), { }, }; -- cgit v1.2.3 From f4b5d8d874b245ec3bf1ed356476e74a346705a2 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 1 Apr 2010 11:38:17 +0300 Subject: wl1271: fix sdio driver name in wl1271_sdio_driver Our SPI driver is called "wl1271_spi" in the driver information structure. Let's use the same for SDIO so that things are aligned. Signed-off-by: Luciano Coelho Reviewed-by: Teemu Paasikivi Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index abfe75b68601..d3d6f302f705 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c @@ -255,7 +255,7 @@ static void __devexit wl1271_remove(struct sdio_func *func) } static struct sdio_driver wl1271_sdio_driver = { - .name = "wl1271", + .name = "wl1271_sdio", .id_table = wl1271_devices, .probe = wl1271_probe, .remove = __devexit_p(wl1271_remove), -- cgit v1.2.3 From 1ed95388caf0ae41f905817e39cd7b5093bf8d7f Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 1 Apr 2010 11:38:18 +0300 Subject: wl1271: added missing command header in wl1271_cmd_disconnect The command header was missing in the wl1271_cmd_disconnect structure. It was working fine by sheer luck, because the parameters are not critical and because our wl1271_cmd_send() function was overwriting the rx_config_options with the actual header. This patch adds the header to the command structure. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index e1131bc0d15c..d61f3394253f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -518,6 +518,8 @@ enum wl1271_disconnect_type { }; struct wl1271_cmd_disconnect { + struct wl1271_cmd_header header; + __le32 rx_config_options; __le32 rx_filter_options; -- cgit v1.2.3 From 40b359c61dc496508b77d1242726e40238e62128 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 1 Apr 2010 11:38:19 +0300 Subject: wl1271: Fix keep-alive related command error The firmware does not like the host configuring the keep-alive after it has been once configured after a join-operation. Instead, it will complain about invalid parameters, which do not break functionality, but do not look nice in the syslog either. This patch prevents the complaints by only configuring the keep-alive once for an association, after the first time join is performed with the correct bssid. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 033cef01fd43..2494c967bb34 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1569,6 +1569,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, enum wl1271_cmd_ps_mode mode; struct wl1271 *wl = hw->priv; bool do_join = false; + bool do_keepalive = false; int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); @@ -1685,6 +1686,14 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (ret < 0) goto out_sleep; + /* + * This is awkward. The keep-alive configs must be done + * *after* the join command, because otherwise it will + * not work, but it must only be done *once* because + * otherwise the firmware will start complaining. + */ + do_keepalive = true; + /* enable the connection monitoring feature */ ret = wl1271_acx_conn_monit_params(wl, true); if (ret < 0) @@ -1763,6 +1772,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, ret = wl1271_acx_aid(wl, wl->aid); if (ret < 0) goto out_sleep; + } + + if (do_keepalive) { ret = wl1271_cmd_build_klv_null_data(wl); if (ret < 0) goto out_sleep; -- cgit v1.2.3 From ebba60c66b3aa321a84c9a90a343c91fde972066 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 1 Apr 2010 11:38:20 +0300 Subject: wl1271: Use minimum rate for each band for control messages Currently the mac80211 is not telling a hardware rate controlled driver a rate to use for association frames etc. So to be safe, use the lowest rate of each band for communication. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 1 + drivers/net/wireless/wl12xx/wl1271_acx.c | 2 +- drivers/net/wireless/wl12xx/wl1271_cmd.c | 27 ++++----- drivers/net/wireless/wl12xx/wl1271_conf.h | 13 ++++ drivers/net/wireless/wl12xx/wl1271_main.c | 98 +++++++++++++++++++++++++------ drivers/net/wireless/wl12xx/wl1271_tx.c | 2 +- drivers/net/wireless/wl12xx/wl1271_tx.h | 1 + 7 files changed, 108 insertions(+), 36 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index c5559efcf5a7..a29969efc861 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -447,6 +447,7 @@ struct wl1271 { /* currently configured rate set */ u32 sta_rate_set; u32 basic_rate_set; + u32 basic_rate; u32 rate_set; /* The current band */ diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 8f0bd5bee6f9..621c94691e7e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -802,7 +802,7 @@ int wl1271_acx_rate_policies(struct wl1271 *wl) /* configure one basic rate class */ idx = ACX_TX_BASIC_RATE; - acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set); + acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate); acx->rate_class[idx].short_retry_limit = c->short_retry_limit; acx->rate_class[idx].long_retry_limit = c->long_retry_limit; acx->rate_class[idx].aflags = c->aflags; diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index f11f9f47ffd5..5cee59fb8c5e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -317,18 +317,10 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) join->rx_config_options = cpu_to_le32(wl->rx_config); join->rx_filter_options = cpu_to_le32(wl->rx_filter); join->bss_type = bss_type; + join->basic_rate_set = wl->basic_rate_set; - if (wl->band == IEEE80211_BAND_2GHZ) - join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_1MBPS | - CONF_HW_BIT_RATE_2MBPS | - CONF_HW_BIT_RATE_5_5MBPS | - CONF_HW_BIT_RATE_11MBPS); - else { + if (wl->band == IEEE80211_BAND_5GHZ) join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; - join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_6MBPS | - CONF_HW_BIT_RATE_12MBPS | - CONF_HW_BIT_RATE_24MBPS); - } join->beacon_interval = cpu_to_le16(wl->beacon_int); join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; @@ -581,17 +573,21 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, struct wl1271_cmd_trigger_scan_to *trigger = NULL; struct wl1271_cmd_scan *params = NULL; struct ieee80211_channel *channels; + u32 rate; int i, j, n_ch, ret; u16 scan_options = 0; u8 ieee_band; - if (band == WL1271_SCAN_BAND_2_4_GHZ) + if (band == WL1271_SCAN_BAND_2_4_GHZ) { ieee_band = IEEE80211_BAND_2GHZ; - else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) + rate = wl->conf.tx.basic_rate; + } else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) { ieee_band = IEEE80211_BAND_2GHZ; - else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) + rate = wl->conf.tx.basic_rate; + } else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) { ieee_band = IEEE80211_BAND_5GHZ; - else + rate = wl->conf.tx.basic_rate_5; + } else return -EINVAL; if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) @@ -618,8 +614,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, params->params.scan_options = cpu_to_le16(scan_options); params->params.num_probe_requests = probe_requests; - /* Let the fw autodetect suitable tx_rate for probes */ - params->params.tx_rate = 0; + params->params.tx_rate = rate; params->params.tid_trigger = 0; params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 82b5dabb6e8d..0b34b6261176 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -674,6 +674,19 @@ struct conf_tx_settings { */ u16 tx_compl_threshold; + /* + * The rate used for control messages and scanning on the 2.4GHz band + * + * Range: CONF_HW_BIT_RATE_* bit mask + */ + u32 basic_rate; + + /* + * The rate used for control messages and scanning on the 5GHz band + * + * Range: CONF_HW_BIT_RATE_* bit mask + */ + u32 basic_rate_5; }; enum { diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 2494c967bb34..ca5cd325fac7 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -116,8 +116,7 @@ static struct conf_drv_settings default_conf = { .tx = { .tx_energy_detection = 0, .rc_conf = { - .enabled_rates = CONF_HW_BIT_RATE_1MBPS | - CONF_HW_BIT_RATE_2MBPS, + .enabled_rates = 0, .short_retry_limit = 10, .long_retry_limit = 10, .aflags = 0 @@ -214,7 +213,9 @@ static struct conf_drv_settings default_conf = { }, .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, .tx_compl_timeout = 700, - .tx_compl_threshold = 4 + .tx_compl_threshold = 4, + .basic_rate = CONF_HW_BIT_RATE_1MBPS, + .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, }, .conn = { .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, @@ -1171,6 +1172,32 @@ out: return ret; } +static void wl1271_set_band_rate(struct wl1271 *wl) +{ + if (wl->band == IEEE80211_BAND_2GHZ) + wl->basic_rate_set = wl->conf.tx.basic_rate; + else + wl->basic_rate_set = wl->conf.tx.basic_rate_5; +} + +static u32 wl1271_min_rate_get(struct wl1271 *wl) +{ + int i; + u32 rate = 0; + + if (!wl->basic_rate_set) { + WARN_ON(1); + wl->basic_rate_set = wl->conf.tx.basic_rate; + } + + for (i = 0; !rate; i++) { + if ((wl->basic_rate_set >> i) & 0x1) + rate = 1 << i; + } + + return rate; +} + static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) { struct wl1271 *wl = hw->priv; @@ -1187,12 +1214,38 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&wl->mutex); - wl->band = conf->channel->band; - ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out; + /* if the channel changes while joined, join again */ + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + wl->band = conf->channel->band; + wl->channel = channel; + + /* + * FIXME: the mac80211 should really provide a fixed rate + * to use here. for now, just use the smallest possible rate + * for the band as a fixed rate for association frames and + * other control messages. + */ + if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + wl1271_set_band_rate(wl); + + wl->basic_rate = wl1271_min_rate_get(wl); + ret = wl1271_acx_rate_policies(wl); + if (ret < 0) + wl1271_warning("rate policy for update channel " + "failed %d", ret); + + if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { + ret = wl1271_cmd_join(wl, wl->set_bss_type); + if (ret < 0) + wl1271_warning("cmd join to update channel " + "failed %d", ret); + } + } + if (changed & IEEE80211_CONF_CHANGE_IDLE) { if (conf->flags & IEEE80211_CONF_IDLE && test_bit(WL1271_FLAG_JOINED, &wl->flags)) @@ -1201,7 +1254,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wl1271_join_channel(wl, channel); if (conf->flags & IEEE80211_CONF_IDLE) { - wl->rate_set = CONF_TX_RATE_MASK_BASIC; + wl->rate_set = wl1271_min_rate_get(wl); wl->sta_rate_set = 0; wl1271_acx_rate_policies(wl); wl1271_acx_keep_alive_config( @@ -1210,18 +1263,6 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) } } - /* if the channel changes while joined, join again */ - if (channel != wl->channel && - test_bit(WL1271_FLAG_JOINED, &wl->flags)) { - wl->channel = channel; - /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ - ret = wl1271_cmd_join(wl, wl->set_bss_type); - if (ret < 0) - wl1271_warning("cmd join to update channel failed %d", - ret); - } else - wl->channel = channel; - if (conf->flags & IEEE80211_CONF_PS && !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); @@ -1659,9 +1700,22 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { + u32 rates; wl->aid = bss_conf->aid; set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); + /* + * use basic rates from AP, and determine lowest rate + * to use with control frames. + */ + rates = bss_conf->basic_rates; + wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, + rates); + wl->basic_rate = wl1271_min_rate_get(wl); + ret = wl1271_acx_rate_policies(wl); + if (ret < 0) + goto out_sleep; + /* * with wl1271, we don't need to update the * beacon_int and dtim_period, because the firmware @@ -1712,6 +1766,13 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); wl->aid = 0; + /* revert back to minimum rates for the current band */ + wl1271_set_band_rate(wl); + wl->basic_rate = wl1271_min_rate_get(wl); + ret = wl1271_acx_rate_policies(wl); + if (ret < 0) + goto out_sleep; + /* disable connection monitor features */ ret = wl1271_acx_conn_monit_params(wl, false); @@ -2261,6 +2322,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->psm_entry_retry = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; + wl->basic_rate = CONF_TX_RATE_MASK_BASIC; wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->sta_rate_set = 0; wl->band = IEEE80211_BAND_2GHZ; diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 66b48b70444e..0b8cdb4e22b6 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -220,7 +220,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) return ret; } -static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) +u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) { struct ieee80211_supported_band *band; u32 enabled_rates = 0; diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index b03c95d9673f..3b8b7ac253fd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h @@ -160,5 +160,6 @@ void wl1271_tx_work(struct work_struct *work); void wl1271_tx_complete(struct wl1271 *wl); void wl1271_tx_flush(struct wl1271 *wl); u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); +u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); #endif -- cgit v1.2.3 From 606c1487ac894798121bc2c64d27c1953c5a6210 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 1 Apr 2010 11:38:21 +0300 Subject: wl1271: Configure rates for templates Configure meaningful rates to be used with the templates. For control frames, use the determined basic rates (currently the lowest rate for the band) and for data-frames (null-funcs) let the firmware use the current rate policy to determine the rate. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 21 +++++++++++++-------- drivers/net/wireless/wl12xx/wl1271_cmd.h | 4 +++- drivers/net/wireless/wl12xx/wl1271_init.c | 18 ++++++++++-------- drivers/net/wireless/wl12xx/wl1271_main.c | 6 ++++-- 4 files changed, 30 insertions(+), 19 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 5cee59fb8c5e..b19090334bc0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -700,7 +700,7 @@ out: } int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, - void *buf, size_t buf_len, int index) + void *buf, size_t buf_len, int index, u32 rates) { struct wl1271_cmd_template_set *cmd; int ret = 0; @@ -718,7 +718,7 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, cmd->len = cpu_to_le16(buf_len); cmd->template_type = template_id; - cmd->enabled_rates = cpu_to_le32(wl->conf.tx.rc_conf.enabled_rates); + cmd->enabled_rates = cpu_to_le32(rates); cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit; cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit; cmd->index = index; @@ -758,7 +758,8 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl) ptr = skb->data; } - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0); + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, + WL1271_RATE_AUTOMATIC); out: dev_kfree_skb(skb); @@ -780,7 +781,8 @@ int wl1271_cmd_build_klv_null_data(struct wl1271 *wl) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, skb->data, skb->len, - CMD_TEMPL_KLV_IDX_NULL_DATA); + CMD_TEMPL_KLV_IDX_NULL_DATA, + WL1271_RATE_AUTOMATIC); out: dev_kfree_skb(skb); @@ -801,7 +803,7 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) goto out; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, - skb->len, 0); + skb->len, 0, wl->basic_rate); out: dev_kfree_skb(skb); @@ -826,10 +828,12 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, if (band == IEEE80211_BAND_2GHZ) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, - skb->data, skb->len, 0); + skb->data, skb->len, 0, + wl->conf.tx.basic_rate); else ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, - skb->data, skb->len, 0); + skb->data, skb->len, 0, + wl->conf.tx.basic_rate_5); out: dev_kfree_skb(skb); @@ -854,7 +858,8 @@ int wl1271_build_qos_null_data(struct wl1271 *wl) template.qos_ctrl = cpu_to_le16(0); return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, - sizeof(template), 0); + sizeof(template), 0, + WL1271_RATE_AUTOMATIC); } int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index d61f3394253f..00f78b7aa384 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -45,7 +45,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, u8 active_scan, u8 high_prio, u8 band, u8 probe_requests); int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, - void *buf, size_t buf_len, int index); + void *buf, size_t buf_len, int index, u32 rates); int wl1271_cmd_build_null_data(struct wl1271 *wl); int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); int wl1271_cmd_build_probe_req(struct wl1271 *wl, @@ -252,6 +252,8 @@ struct cmd_enabledisable_path { u8 padding[3]; } __attribute__ ((packed)); +#define WL1271_RATE_AUTOMATIC 0 + struct wl1271_cmd_template_set { struct wl1271_cmd_header header; diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 8ec94ac84093..9ab336829044 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -56,54 +56,56 @@ int wl1271_init_templates_config(struct wl1271 *wl) /* send empty templates for fw memory reservation */ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, sizeof(struct wl12xx_probe_req_template), - 0); + 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; if (wl1271_11a_enabled()) { size_t size = sizeof(struct wl12xx_probe_req_template); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, - NULL, size, 0); + NULL, size, 0, + WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; } ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, sizeof(struct wl12xx_null_data_template), - 0); + 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL, sizeof(struct wl12xx_ps_poll_template), - 0); + 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, sizeof (struct wl12xx_qos_null_data_template), - 0); + 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, sizeof (struct wl12xx_probe_resp_template), - 0); + 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, sizeof (struct wl12xx_beacon_template), - 0); + 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, - WL1271_CMD_TEMPL_MAX_SIZE, i); + WL1271_CMD_TEMPL_MAX_SIZE, i, + WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; } diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index ca5cd325fac7..247f4079832e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1642,7 +1642,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, wl1271_ssid_set(wl, beacon); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, beacon->data, - beacon->len, 0); + beacon->len, 0, + wl1271_min_rate_get(wl)); if (ret < 0) { dev_kfree_skb(beacon); @@ -1657,7 +1658,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, beacon->data, - beacon->len, 0); + beacon->len, 0, + wl1271_min_rate_get(wl)); dev_kfree_skb(beacon); if (ret < 0) goto out_sleep; -- cgit v1.2.3 From 50c500ad3da49f866628d60d49645f4f8f4ff92c Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 1 Apr 2010 11:38:22 +0300 Subject: wl1271: Configure a higher listen interval to AP upon association Increase the fixed listen-interval max value configured to the mac80211 on driver init. This value will allow a larger value to be configured to the AP, which means the AP will buffer our frames longer. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_conf.h | 7 +++++++ drivers/net/wireless/wl12xx/wl1271_main.c | 6 ++++-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 0b34b6261176..d76ae03762a3 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -977,6 +977,13 @@ struct conf_conn_settings { * Range: 1000 - 3600000 */ u32 keep_alive_interval; + + /* + * Maximum listen interval supported by the driver in units of beacons. + * + * Range: u16 + */ + u8 max_listen_interval; }; enum { diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 247f4079832e..5c32d8d72361 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -219,7 +219,7 @@ static struct conf_drv_settings default_conf = { }, .conn = { .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, - .listen_interval = 0, + .listen_interval = 1, .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, .bcn_filt_ie_count = 1, .bcn_filt_ie = { @@ -266,7 +266,8 @@ static struct conf_drv_settings default_conf = { .bet_enable = CONF_BET_MODE_ENABLE, .bet_max_consecutive = 10, .psm_entry_retries = 3, - .keep_alive_interval = 55000 + .keep_alive_interval = 55000, + .max_listen_interval = 20, }, .init = { .radioparam = { @@ -2253,6 +2254,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) /* unit us */ /* FIXME: find a proper value */ wl->hw->channel_change_time = 10000; + wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval; wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM | -- cgit v1.2.3 From 1a186a515a1e4446cdde2b4341dc361ba6bc76ed Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 1 Apr 2010 11:38:23 +0300 Subject: wl1271: Fix debug prints for beacon-loss and psm-entry-fail scenarios Remove ERROR print from psm-entry-fail scenario, instead use an INFO print. Also, add INFO print to the beacon-loss scenario. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_event.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 4fc212a02a64..daacf176cf09 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -81,7 +81,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, true); } else { - wl1271_error("PSM entry failed, giving up.\n"); + wl1271_info("No ack to nullfunc from AP."); wl->psm_entry_retry = 0; *beacon_loss = true; } @@ -160,7 +160,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) * */ if (vector & BSS_LOSE_EVENT_ID) { - wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); + wl1271_info("Beacon loss detected."); /* indicate to the stack, that beacons have been lost */ beacon_loss = true; -- cgit v1.2.3 From 6bbe89de24ffe0f849e67edba7def3f39f1f80d8 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 1 Apr 2010 11:38:24 +0300 Subject: wl1271: Fix tx queue flushing This patch modifies tx-queue flushing to correspond with tx-path - i.e. also frames for which no ack was requested are forwarded to the mac80211 for disposal. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_tx.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 0b8cdb4e22b6..62db79508ddf 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -416,35 +416,19 @@ void wl1271_tx_flush(struct wl1271 *wl) { int i; struct sk_buff *skb; - struct ieee80211_tx_info *info; /* TX failure */ /* control->flags = 0; FIXME */ while ((skb = skb_dequeue(&wl->tx_queue))) { - info = IEEE80211_SKB_CB(skb); - wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); - - if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { - kfree_skb(skb); - continue; - } - ieee80211_tx_status(wl->hw, skb); } for (i = 0; i < ACX_TX_DESCRIPTORS; i++) if (wl->tx_frames[i] != NULL) { skb = wl->tx_frames[i]; - info = IEEE80211_SKB_CB(skb); - - if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { - kfree_skb(skb); - continue; - } - - ieee80211_tx_status(wl->hw, skb); wl->tx_frames[i] = NULL; + ieee80211_tx_status(wl->hw, skb); } } -- cgit v1.2.3 From bc53e5129ce879ba024b7d21981871ea63a37b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 1 Apr 2010 23:11:10 +0200 Subject: b43: N-PHY: fix copy&paste typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Myhailo Danylenko Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 1ae232c25093..9e93eb4a17cf 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -2800,7 +2800,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, } b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, buffer); - b43_ntab_write_bulk(dev, B43_NTAB16(15, 101), 2, + b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2, buffer); b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, buffer); -- cgit v1.2.3 From 2111ac0d888767999c7dd6d1309dcc1fb8012022 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Fri, 2 Apr 2010 18:44:08 +0900 Subject: ath5k: Adaptive Noise Immunity (ANI) Implementation This is an Adaptive Noise Imunity (ANI) implementation for ath5k. I have looked at both ath9k and HAL sources (they are nearly the same), and even though i have implemented some things differently, the basic algorithm is practically the same, for now. I hope that this can serve as a clean start to improve the algorithm later. This also adds a possibility to manually control ANI settings, right now only thru a debugfs file: * set lowest sensitivity (=highest noise immunity): echo sens-low > /sys/kernel/debug/ath5k/phy0/ani * set highest sensitivity (=lowest noise immunity): echo sens-high > /sys/kernel/debug/ath5k/phy0/ani * automatically control immunity (default): echo ani-on > /sys/kernel/debug/ath5k/phy0/ani * to see the parameters in use and watch them change: cat /sys/kernel/debug/ath5k/phy0/ani Manually setting sensitivity will turn the automatic control off. You can also control each of the five immunity parameters (noise immunity, spur immunity, firstep, ofdm weak signal detection, cck weak signal detection) manually thru the debugfs file. This is tested on AR5414 and nearly doubles the thruput in a noisy 2GHz band. Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/Makefile | 1 + drivers/net/wireless/ath/ath5k/ani.c | 744 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath5k/ani.h | 104 +++++ drivers/net/wireless/ath/ath5k/ath5k.h | 9 +- drivers/net/wireless/ath/ath5k/attach.c | 1 + drivers/net/wireless/ath/ath5k/base.c | 32 +- drivers/net/wireless/ath/ath5k/base.h | 6 + drivers/net/wireless/ath/ath5k/debug.c | 162 +++++++ drivers/net/wireless/ath/ath5k/debug.h | 2 + drivers/net/wireless/ath/ath5k/desc.c | 1 + drivers/net/wireless/ath/ath5k/pcu.c | 1 - drivers/net/wireless/ath/ath5k/reg.h | 36 +- 12 files changed, 1083 insertions(+), 16 deletions(-) create mode 100644 drivers/net/wireless/ath/ath5k/ani.c create mode 100644 drivers/net/wireless/ath/ath5k/ani.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile index 090dc6d268a3..cc09595b781a 100644 --- a/drivers/net/wireless/ath/ath5k/Makefile +++ b/drivers/net/wireless/ath/ath5k/Makefile @@ -12,5 +12,6 @@ ath5k-y += attach.o ath5k-y += base.o ath5k-y += led.o ath5k-y += rfkill.o +ath5k-y += ani.o ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o obj-$(CONFIG_ATH5K) += ath5k.o diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c new file mode 100644 index 000000000000..584a32859bdb --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/ani.c @@ -0,0 +1,744 @@ +/* + * Copyright (C) 2010 Bruno Randolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ath5k.h" +#include "base.h" +#include "reg.h" +#include "debug.h" +#include "ani.h" + +/** + * DOC: Basic ANI Operation + * + * Adaptive Noise Immunity (ANI) controls five noise immunity parameters + * depending on the amount of interference in the environment, increasing + * or reducing sensitivity as necessary. + * + * The parameters are: + * - "noise immunity" + * - "spur immunity" + * - "firstep level" + * - "OFDM weak signal detection" + * - "CCK weak signal detection" + * + * Basically we look at the amount of ODFM and CCK timing errors we get and then + * raise or lower immunity accordingly by setting one or more of these + * parameters. + * Newer chipsets have PHY error counters in hardware which will generate a MIB + * interrupt when they overflow. Older hardware has too enable PHY error frames + * by setting a RX flag and then count every single PHY error. When a specified + * threshold of errors has been reached we will raise immunity. + * Also we regularly check the amount of errors and lower or raise immunity as + * necessary. + */ + + +/*** ANI parameter control ***/ + +/** + * ath5k_ani_set_noise_immunity_level() - Set noise immunity level + * + * @level: level between 0 and @ATH5K_ANI_MAX_NOISE_IMM_LVL + */ +void +ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) +{ + /* TODO: + * ANI documents suggest the following five levels to use, but the HAL + * and ath9k use only use the last two levels, making this + * essentially an on/off option. There *may* be a reason for this (???), + * so i stick with the HAL version for now... + */ +#if 0 + const s8 hi[] = { -18, -18, -16, -14, -12 }; + const s8 lo[] = { -52, -56, -60, -64, -70 }; + const s8 sz[] = { -34, -41, -48, -55, -62 }; + const s8 fr[] = { -70, -72, -75, -78, -80 }; +#else + const s8 sz[] = { -55, -62 }; + const s8 lo[] = { -64, -70 }; + const s8 hi[] = { -14, -12 }; + const s8 fr[] = { -78, -80 }; +#endif + if (level < 0 || level > ARRAY_SIZE(sz)) { + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + "level out of range %d", level); + return; + } + + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, + AR5K_PHY_DESIRED_SIZE_TOT, sz[level]); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_AGCCOARSE, + AR5K_PHY_AGCCOARSE_LO, lo[level]); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_AGCCOARSE, + AR5K_PHY_AGCCOARSE_HI, hi[level]); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG, + AR5K_PHY_SIG_FIRPWR, fr[level]); + + ah->ah_sc->ani_state.noise_imm_level = level; + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); +} + + +/** + * ath5k_ani_set_spur_immunity_level() - Set spur immunity level + * + * @level: level between 0 and @max_spur_level (the maximum level is dependent + * on the chip revision). + */ +void +ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) +{ + const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; + + if (level < 0 || level > ARRAY_SIZE(val) || + level > ah->ah_sc->ani_state.max_spur_level) { + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + "level out of range %d", level); + return; + } + + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, + AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, val[level]); + + ah->ah_sc->ani_state.spur_level = level; + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); +} + + +/** + * ath5k_ani_set_firstep_level() - Set "firstep" level + * + * @level: level between 0 and @ATH5K_ANI_MAX_FIRSTEP_LVL + */ +void +ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) +{ + const int val[] = { 0, 4, 8 }; + + if (level < 0 || level > ARRAY_SIZE(val)) { + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + "level out of range %d", level); + return; + } + + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG, + AR5K_PHY_SIG_FIRSTEP, val[level]); + + ah->ah_sc->ani_state.firstep_level = level; + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); +} + + +/** + * ath5k_ani_set_ofdm_weak_signal_detection() - Control OFDM weak signal + * detection + * + * @on: turn on or off + */ +void +ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on) +{ + const int m1l[] = { 127, 50 }; + const int m2l[] = { 127, 40 }; + const int m1[] = { 127, 0x4d }; + const int m2[] = { 127, 0x40 }; + const int m2cnt[] = { 31, 16 }; + const int m2lcnt[] = { 63, 48 }; + + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, + AR5K_PHY_WEAK_OFDM_LOW_THR_M1, m1l[on]); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, + AR5K_PHY_WEAK_OFDM_LOW_THR_M2, m2l[on]); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_HIGH_THR, + AR5K_PHY_WEAK_OFDM_HIGH_THR_M1, m1[on]); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_HIGH_THR, + AR5K_PHY_WEAK_OFDM_HIGH_THR_M2, m2[on]); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_HIGH_THR, + AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT, m2cnt[on]); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, + AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT, m2lcnt[on]); + + if (on) + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, + AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN); + else + AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, + AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN); + + ah->ah_sc->ani_state.ofdm_weak_sig = on; + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s", + on ? "on" : "off"); +} + + +/** + * ath5k_ani_set_cck_weak_signal_detection() - control CCK weak signal detection + * + * @on: turn on or off + */ +void +ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on) +{ + const int val[] = { 8, 6 }; + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_CCK_CROSSCORR, + AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR, val[on]); + ah->ah_sc->ani_state.cck_weak_sig = on; + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s", + on ? "on" : "off"); +} + + +/*** ANI algorithm ***/ + +/** + * ath5k_ani_raise_immunity() - Increase noise immunity + * + * @ofdm_trigger: If this is true we are called because of too many OFDM errors, + * the algorithm will tune more parameters then. + * + * Try to raise noise immunity (=decrease sensitivity) in several steps + * depending on the average RSSI of the beacons we received. + */ +static void +ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, + bool ofdm_trigger) +{ + int rssi = ah->ah_beacon_rssi_avg.avg; + + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "raise immunity (%s)", + ofdm_trigger ? "ODFM" : "CCK"); + + /* first: raise noise immunity */ + if (as->noise_imm_level < ATH5K_ANI_MAX_NOISE_IMM_LVL) { + ath5k_ani_set_noise_immunity_level(ah, as->noise_imm_level + 1); + return; + } + + /* only OFDM: raise spur immunity level */ + if (ofdm_trigger && + as->spur_level < ah->ah_sc->ani_state.max_spur_level) { + ath5k_ani_set_spur_immunity_level(ah, as->spur_level + 1); + return; + } + + /* AP mode */ + if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) { + if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL) + ath5k_ani_set_firstep_level(ah, as->firstep_level + 1); + return; + } + + /* STA and IBSS mode */ + + /* TODO: for IBSS mode it would be better to keep a beacon RSSI average + * per each neighbour node and use the minimum of these, to make sure we + * don't shut out a remote node by raising immunity too high. */ + + if (rssi > ATH5K_ANI_RSSI_THR_HIGH) { + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + "beacon RSSI high"); + /* only OFDM: beacon RSSI is high, we can disable ODFM weak + * signal detection */ + if (ofdm_trigger && as->ofdm_weak_sig == true) { + ath5k_ani_set_ofdm_weak_signal_detection(ah, false); + ath5k_ani_set_spur_immunity_level(ah, 0); + return; + } + /* as a last resort or CCK: raise firstep level */ + if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL) { + ath5k_ani_set_firstep_level(ah, as->firstep_level + 1); + return; + } + } else if (rssi > ATH5K_ANI_RSSI_THR_LOW) { + /* beacon RSSI in mid range, we need OFDM weak signal detect, + * but can raise firstep level */ + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + "beacon RSSI mid"); + if (ofdm_trigger && as->ofdm_weak_sig == false) + ath5k_ani_set_ofdm_weak_signal_detection(ah, true); + if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL) + ath5k_ani_set_firstep_level(ah, as->firstep_level + 1); + return; + } else if (ah->ah_current_channel->band == IEEE80211_BAND_2GHZ) { + /* beacon RSSI is low. in B/G mode turn of OFDM weak signal + * detect and zero firstep level to maximize CCK sensitivity */ + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + "beacon RSSI low, 2GHz"); + if (ofdm_trigger && as->ofdm_weak_sig == true) + ath5k_ani_set_ofdm_weak_signal_detection(ah, false); + if (as->firstep_level > 0) + ath5k_ani_set_firstep_level(ah, 0); + return; + } + + /* TODO: why not?: + if (as->cck_weak_sig == true) { + ath5k_ani_set_cck_weak_signal_detection(ah, false); + } + */ +} + + +/** + * ath5k_ani_lower_immunity() - Decrease noise immunity + * + * Try to lower noise immunity (=increase sensitivity) in several steps + * depending on the average RSSI of the beacons we received. + */ +static void +ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as) +{ + int rssi = ah->ah_beacon_rssi_avg.avg; + + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "lower immunity"); + + if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) { + /* AP mode */ + if (as->firstep_level > 0) { + ath5k_ani_set_firstep_level(ah, as->firstep_level - 1); + return; + } + } else { + /* STA and IBSS mode (see TODO above) */ + if (rssi > ATH5K_ANI_RSSI_THR_HIGH) { + /* beacon signal is high, leave OFDM weak signal + * detection off or it may oscillate + * TODO: who said it's off??? */ + } else if (rssi > ATH5K_ANI_RSSI_THR_LOW) { + /* beacon RSSI is mid-range: turn on ODFM weak signal + * detection and next, lower firstep level */ + if (as->ofdm_weak_sig == false) { + ath5k_ani_set_ofdm_weak_signal_detection(ah, + true); + return; + } + if (as->firstep_level > 0) { + ath5k_ani_set_firstep_level(ah, + as->firstep_level - 1); + return; + } + } else { + /* beacon signal is low: only reduce firstep level */ + if (as->firstep_level > 0) { + ath5k_ani_set_firstep_level(ah, + as->firstep_level - 1); + return; + } + } + } + + /* all modes */ + if (as->spur_level > 0) { + ath5k_ani_set_spur_immunity_level(ah, as->spur_level - 1); + return; + } + + /* finally, reduce noise immunity */ + if (as->noise_imm_level > 0) { + ath5k_ani_set_noise_immunity_level(ah, as->noise_imm_level - 1); + return; + } +} + + +/** + * ath5k_hw_ani_get_listen_time() - Calculate time spent listening + * + * Return an approximation of the time spent "listening" in milliseconds (ms) + * since the last call of this function by deducting the cycles spent + * transmitting and receiving from the total cycle count. + * Save profile count values for debugging/statistics and because we might want + * to use them later. + * + * We assume no one else clears these registers! + */ +static int +ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as) +{ + int listen; + + /* freeze */ + ath5k_hw_reg_write(ah, AR5K_MIBC_FMC, AR5K_MIBC); + /* read */ + as->pfc_cycles = ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE); + as->pfc_busy = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR); + as->pfc_tx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX); + as->pfc_rx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX); + /* clear */ + ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); + ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); + ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); + ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); + /* un-freeze */ + ath5k_hw_reg_write(ah, 0, AR5K_MIBC); + + /* TODO: where does 44000 come from? (11g clock rate?) */ + listen = (as->pfc_cycles - as->pfc_rx - as->pfc_tx) / 44000; + + if (as->pfc_cycles == 0 || listen < 0) + return 0; + return listen; +} + + +/** + * ath5k_ani_save_and_clear_phy_errors() - Clear and save PHY error counters + * + * Clear the PHY error counters as soon as possible, since this might be called + * from a MIB interrupt and we want to make sure we don't get interrupted again. + * Add the count of CCK and OFDM errors to our internal state, so it can be used + * by the algorithm later. + * + * Will be called from interrupt and tasklet context. + * Returns 0 if both counters are zero. + */ +static int +ath5k_ani_save_and_clear_phy_errors(struct ath5k_hw *ah, + struct ath5k_ani_state *as) +{ + unsigned int ofdm_err, cck_err; + + if (!ah->ah_capabilities.cap_has_phyerr_counters) + return 0; + + ofdm_err = ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1); + cck_err = ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2); + + /* reset counters first, we might be in a hurry (interrupt) */ + ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_OFDM_TRIG_HIGH, + AR5K_PHYERR_CNT1); + ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_CCK_TRIG_HIGH, + AR5K_PHYERR_CNT2); + + ofdm_err = ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - ofdm_err); + cck_err = ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - cck_err); + + /* sometimes both can be zero, especially when there is a superfluous + * second interrupt. detect that here and return an error. */ + if (ofdm_err <= 0 && cck_err <= 0) + return 0; + + /* avoid negative values should one of the registers overflow */ + if (ofdm_err > 0) { + as->ofdm_errors += ofdm_err; + as->sum_ofdm_errors += ofdm_err; + } + if (cck_err > 0) { + as->cck_errors += cck_err; + as->sum_cck_errors += cck_err; + } + return 1; +} + + +/** + * ath5k_ani_period_restart() - Restart ANI period + * + * Just reset counters, so they are clear for the next "ani period". + */ +static void +ath5k_ani_period_restart(struct ath5k_hw *ah, struct ath5k_ani_state *as) +{ + /* keep last values for debugging */ + as->last_ofdm_errors = as->ofdm_errors; + as->last_cck_errors = as->cck_errors; + as->last_listen = as->listen_time; + + as->ofdm_errors = 0; + as->cck_errors = 0; + as->listen_time = 0; +} + + +/** + * ath5k_ani_calibration() - The main ANI calibration function + * + * We count OFDM and CCK errors relative to the time where we did not send or + * receive ("listen" time) and raise or lower immunity accordingly. + * This is called regularly (every second) from the calibration timer, but also + * when an error threshold has been reached. + * + * In order to synchronize access from different contexts, this should be + * called only indirectly by scheduling the ANI tasklet! + */ +void +ath5k_ani_calibration(struct ath5k_hw *ah) +{ + struct ath5k_ani_state *as = &ah->ah_sc->ani_state; + int listen, ofdm_high, ofdm_low, cck_high, cck_low; + + if (as->ani_mode != ATH5K_ANI_MODE_AUTO) + return; + + /* get listen time since last call and add it to the counter because we + * might not have restarted the "ani period" last time */ + listen = ath5k_hw_ani_get_listen_time(ah, as); + as->listen_time += listen; + + ath5k_ani_save_and_clear_phy_errors(ah, as); + + ofdm_high = as->listen_time * ATH5K_ANI_OFDM_TRIG_HIGH / 1000; + cck_high = as->listen_time * ATH5K_ANI_CCK_TRIG_HIGH / 1000; + ofdm_low = as->listen_time * ATH5K_ANI_OFDM_TRIG_LOW / 1000; + cck_low = as->listen_time * ATH5K_ANI_CCK_TRIG_LOW / 1000; + + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + "listen %d (now %d)", as->listen_time, listen); + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + "check high ofdm %d/%d cck %d/%d", + as->ofdm_errors, ofdm_high, as->cck_errors, cck_high); + + if (as->ofdm_errors > ofdm_high || as->cck_errors > cck_high) { + /* too many PHY errors - we have to raise immunity */ + bool ofdm_flag = as->ofdm_errors > ofdm_high ? true : false; + ath5k_ani_raise_immunity(ah, as, ofdm_flag); + ath5k_ani_period_restart(ah, as); + + } else if (as->listen_time > 5 * ATH5K_ANI_LISTEN_PERIOD) { + /* If more than 5 (TODO: why 5?) periods have passed and we got + * relatively little errors we can try to lower immunity */ + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + "check low ofdm %d/%d cck %d/%d", + as->ofdm_errors, ofdm_low, as->cck_errors, cck_low); + + if (as->ofdm_errors <= ofdm_low && as->cck_errors <= cck_low) + ath5k_ani_lower_immunity(ah, as); + + ath5k_ani_period_restart(ah, as); + } +} + + +/*** INTERRUPT HANDLER ***/ + +/** + * ath5k_ani_mib_intr() - Interrupt handler for ANI MIB counters + * + * Just read & reset the registers quickly, so they don't generate more + * interrupts, save the counters and schedule the tasklet to decide whether + * to raise immunity or not. + * + * We just need to handle PHY error counters, ath5k_hw_update_mib_counters() + * should take care of all "normal" MIB interrupts. + */ +void +ath5k_ani_mib_intr(struct ath5k_hw *ah) +{ + struct ath5k_ani_state *as = &ah->ah_sc->ani_state; + + /* nothing to do here if HW does not have PHY error counters - they + * can't be the reason for the MIB interrupt then */ + if (!ah->ah_capabilities.cap_has_phyerr_counters) + return; + + /* not in use but clear anyways */ + ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT); + ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); + + if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO) + return; + + /* if one of the errors triggered, we can get a superfluous second + * interrupt, even though we have already reset the register. the + * function detects that so we can return early */ + if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0) + return; + + if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH || + as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH) + tasklet_schedule(&ah->ah_sc->ani_tasklet); +} + + +/** + * ath5k_ani_phy_error_report() - Used by older HW to report PHY errors + * + * This is used by hardware without PHY error counters to report PHY errors + * on a frame-by-frame basis, instead of the interrupt. + */ +void +ath5k_ani_phy_error_report(struct ath5k_hw *ah, + enum ath5k_phy_error_code phyerr) +{ + struct ath5k_ani_state *as = &ah->ah_sc->ani_state; + + if (phyerr == AR5K_RX_PHY_ERROR_OFDM_TIMING) { + as->ofdm_errors++; + if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH) + tasklet_schedule(&ah->ah_sc->ani_tasklet); + } else if (phyerr == AR5K_RX_PHY_ERROR_CCK_TIMING) { + as->cck_errors++; + if (as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH) + tasklet_schedule(&ah->ah_sc->ani_tasklet); + } +} + + +/*** INIT ***/ + +/** + * ath5k_enable_phy_err_counters() - Enable PHY error counters + * + * Enable PHY error counters for OFDM and CCK timing errors. + */ +static void +ath5k_enable_phy_err_counters(struct ath5k_hw *ah) +{ + ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_OFDM_TRIG_HIGH, + AR5K_PHYERR_CNT1); + ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_CCK_TRIG_HIGH, + AR5K_PHYERR_CNT2); + ath5k_hw_reg_write(ah, AR5K_PHY_ERR_FIL_OFDM, AR5K_PHYERR_CNT1_MASK); + ath5k_hw_reg_write(ah, AR5K_PHY_ERR_FIL_CCK, AR5K_PHYERR_CNT2_MASK); + + /* not in use */ + ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT); + ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); +} + + +/** + * ath5k_disable_phy_err_counters() - Disable PHY error counters + * + * Disable PHY error counters for OFDM and CCK timing errors. + */ +static void +ath5k_disable_phy_err_counters(struct ath5k_hw *ah) +{ + ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT1); + ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT2); + ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT1_MASK); + ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT2_MASK); + + /* not in use */ + ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT); + ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); +} + + +/** + * ath5k_ani_init() - Initialize ANI + * @mode: Which mode to use (auto, manual high, manual low, off) + * + * Initialize ANI according to mode. + */ +void +ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode) +{ + /* ANI is only possible on 5212 and newer */ + if (ah->ah_version < AR5K_AR5212) + return; + + /* clear old state information */ + memset(&ah->ah_sc->ani_state, 0, sizeof(ah->ah_sc->ani_state)); + + /* older hardware has more spur levels than newer */ + if (ah->ah_mac_srev < AR5K_SREV_AR2414) + ah->ah_sc->ani_state.max_spur_level = 7; + else + ah->ah_sc->ani_state.max_spur_level = 2; + + /* initial values for our ani parameters */ + if (mode == ATH5K_ANI_MODE_OFF) { + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI off\n"); + } else if (mode == ATH5K_ANI_MODE_MANUAL_LOW) { + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + "ANI manual low -> high sensitivity\n"); + ath5k_ani_set_noise_immunity_level(ah, 0); + ath5k_ani_set_spur_immunity_level(ah, 0); + ath5k_ani_set_firstep_level(ah, 0); + ath5k_ani_set_ofdm_weak_signal_detection(ah, true); + ath5k_ani_set_cck_weak_signal_detection(ah, true); + } else if (mode == ATH5K_ANI_MODE_MANUAL_HIGH) { + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + "ANI manual high -> low sensitivity\n"); + ath5k_ani_set_noise_immunity_level(ah, + ATH5K_ANI_MAX_NOISE_IMM_LVL); + ath5k_ani_set_spur_immunity_level(ah, + ah->ah_sc->ani_state.max_spur_level); + ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL); + ath5k_ani_set_ofdm_weak_signal_detection(ah, false); + ath5k_ani_set_cck_weak_signal_detection(ah, false); + } else if (mode == ATH5K_ANI_MODE_AUTO) { + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI auto\n"); + ath5k_ani_set_noise_immunity_level(ah, 0); + ath5k_ani_set_spur_immunity_level(ah, 0); + ath5k_ani_set_firstep_level(ah, 0); + ath5k_ani_set_ofdm_weak_signal_detection(ah, true); + ath5k_ani_set_cck_weak_signal_detection(ah, false); + } + + /* newer hardware has PHY error counter registers which we can use to + * get OFDM and CCK error counts. older hardware has to set rxfilter and + * report every single PHY error by calling ath5k_ani_phy_error_report() + */ + if (mode == ATH5K_ANI_MODE_AUTO) { + if (ah->ah_capabilities.cap_has_phyerr_counters) + ath5k_enable_phy_err_counters(ah); + else + ath5k_hw_set_rx_filter(ah, ath5k_hw_get_rx_filter(ah) | + AR5K_RX_FILTER_PHYERR); + } else { + if (ah->ah_capabilities.cap_has_phyerr_counters) + ath5k_disable_phy_err_counters(ah); + else + ath5k_hw_set_rx_filter(ah, ath5k_hw_get_rx_filter(ah) & + ~AR5K_RX_FILTER_PHYERR); + } + + ah->ah_sc->ani_state.ani_mode = mode; +} + + +/*** DEBUG ***/ + +#ifdef CONFIG_ATH5K_DEBUG + +void +ath5k_ani_print_counters(struct ath5k_hw *ah) +{ + /* clears too */ + printk(KERN_NOTICE "ACK fail\t%d\n", + ath5k_hw_reg_read(ah, AR5K_ACK_FAIL)); + printk(KERN_NOTICE "RTS fail\t%d\n", + ath5k_hw_reg_read(ah, AR5K_RTS_FAIL)); + printk(KERN_NOTICE "RTS success\t%d\n", + ath5k_hw_reg_read(ah, AR5K_RTS_OK)); + printk(KERN_NOTICE "FCS error\t%d\n", + ath5k_hw_reg_read(ah, AR5K_FCS_FAIL)); + + /* no clear */ + printk(KERN_NOTICE "tx\t%d\n", + ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX)); + printk(KERN_NOTICE "rx\t%d\n", + ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX)); + printk(KERN_NOTICE "busy\t%d\n", + ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR)); + printk(KERN_NOTICE "cycles\t%d\n", + ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE)); + + printk(KERN_NOTICE "AR5K_PHYERR_CNT1\t%d\n", + ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)); + printk(KERN_NOTICE "AR5K_PHYERR_CNT2\t%d\n", + ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)); + printk(KERN_NOTICE "AR5K_OFDM_FIL_CNT\t%d\n", + ath5k_hw_reg_read(ah, AR5K_OFDM_FIL_CNT)); + printk(KERN_NOTICE "AR5K_CCK_FIL_CNT\t%d\n", + ath5k_hw_reg_read(ah, AR5K_CCK_FIL_CNT)); +} + +#endif diff --git a/drivers/net/wireless/ath/ath5k/ani.h b/drivers/net/wireless/ath/ath5k/ani.h new file mode 100644 index 000000000000..55cf26d8522c --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/ani.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2010 Bruno Randolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef ANI_H +#define ANI_H + +/* these thresholds are relative to the ATH5K_ANI_LISTEN_PERIOD */ +#define ATH5K_ANI_LISTEN_PERIOD 100 +#define ATH5K_ANI_OFDM_TRIG_HIGH 500 +#define ATH5K_ANI_OFDM_TRIG_LOW 200 +#define ATH5K_ANI_CCK_TRIG_HIGH 200 +#define ATH5K_ANI_CCK_TRIG_LOW 100 + +/* average beacon RSSI thresholds */ +#define ATH5K_ANI_RSSI_THR_HIGH 40 +#define ATH5K_ANI_RSSI_THR_LOW 7 + +/* maximum availabe levels */ +#define ATH5K_ANI_MAX_FIRSTEP_LVL 2 +#define ATH5K_ANI_MAX_NOISE_IMM_LVL 1 + + +/** + * enum ath5k_ani_mode - mode for ANI / noise sensitivity + * + * @ATH5K_ANI_MODE_OFF: Turn ANI off. This can be useful to just stop the ANI + * algorithm after it has been on auto mode. + * ATH5K_ANI_MODE_MANUAL_LOW: Manually set all immunity parameters to low, + * maximizing sensitivity. ANI will not run. + * ATH5K_ANI_MODE_MANUAL_HIGH: Manually set all immunity parameters to high, + * minimizing sensitivity. ANI will not run. + * ATH5K_ANI_MODE_AUTO: Automatically control immunity parameters based on the + * amount of OFDM and CCK frame errors (default). + */ +enum ath5k_ani_mode { + ATH5K_ANI_MODE_OFF = 0, + ATH5K_ANI_MODE_MANUAL_LOW = 1, + ATH5K_ANI_MODE_MANUAL_HIGH = 2, + ATH5K_ANI_MODE_AUTO = 3 +}; + + +/** + * struct ath5k_ani_state - ANI state and associated counters + * + * @max_spur_level: the maximum spur level is chip dependent + */ +struct ath5k_ani_state { + enum ath5k_ani_mode ani_mode; + + /* state */ + int noise_imm_level; + int spur_level; + int firstep_level; + bool ofdm_weak_sig; + bool cck_weak_sig; + + int max_spur_level; + + /* used by the algorithm */ + unsigned int listen_time; + unsigned int ofdm_errors; + unsigned int cck_errors; + + /* debug/statistics only: numbers from last ANI calibration */ + unsigned int pfc_tx; + unsigned int pfc_rx; + unsigned int pfc_busy; + unsigned int pfc_cycles; + unsigned int last_listen; + unsigned int last_ofdm_errors; + unsigned int last_cck_errors; + unsigned int sum_ofdm_errors; + unsigned int sum_cck_errors; +}; + +void ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode); +void ath5k_ani_mib_intr(struct ath5k_hw *ah); +void ath5k_ani_calibration(struct ath5k_hw *ah); +void ath5k_ani_phy_error_report(struct ath5k_hw *ah, + enum ath5k_phy_error_code phyerr); + +/* for manual control */ +void ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level); +void ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level); +void ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level); +void ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on); +void ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on); + +void ath5k_ani_print_counters(struct ath5k_hw *ah); + +#endif /* ANI_H */ diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index f578c1ed7f88..2785946f659a 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -203,6 +203,7 @@ #define AR5K_TUNE_DEFAULT_TXPOWER 25 #define AR5K_TUNE_TPC_TXPOWER false #define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL 10000 /* 10 sec */ +#define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */ #define AR5K_INIT_CARR_SENSE_EN 1 @@ -800,9 +801,9 @@ struct ath5k_athchan_2ghz { * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold * We currently do increments on interrupt by * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2 - * @AR5K_INT_MIB: Indicates the Management Information Base counters should be - * checked. We should do this with ath5k_hw_update_mib_counters() but - * it seems we should also then do some noise immunity work. + * @AR5K_INT_MIB: Indicates the either Management Information Base counters or + * one of the PHY error counters reached the maximum value and should be + * read and cleared. * @AR5K_INT_RXPHY: RX PHY Error * @AR5K_INT_RXKCM: RX Key cache miss * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a @@ -894,6 +895,7 @@ enum ath5k_int { enum ath5k_calibration_mask { AR5K_CALIBRATION_FULL = 0x01, AR5K_CALIBRATION_SHORT = 0x02, + AR5K_CALIBRATION_ANI = 0x04, }; /* @@ -1115,6 +1117,7 @@ struct ath5k_hw { /* Calibration timestamp */ unsigned long ah_cal_next_full; + unsigned long ah_cal_next_ani; /* Calibration mask */ u8 ah_cal_mask; diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index f80d3d52c536..dcf7c30f813f 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -124,6 +124,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ah->ah_software_retry = false; ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; ah->ah_noise_floor = -95; /* until first NF calibration is run */ + sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO; /* * Find the mac version diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index a1c0dcb4926e..c085a06f1e05 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -58,6 +58,7 @@ #include "base.h" #include "reg.h" #include "debug.h" +#include "ani.h" static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); @@ -363,6 +364,7 @@ static void ath5k_beacon_send(struct ath5k_softc *sc); static void ath5k_beacon_config(struct ath5k_softc *sc); static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); static void ath5k_tasklet_beacon(unsigned long data); +static void ath5k_tasklet_ani(unsigned long data); static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) { @@ -828,6 +830,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); + tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc); ret = ath5k_eeprom_read_mac(ah, mac); if (ret) { @@ -2530,7 +2533,8 @@ ath5k_init(struct ath5k_softc *sc) sc->curband = &sc->sbands[sc->curchan->band]; sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | - AR5K_INT_FATAL | AR5K_INT_GLOBAL; + AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; + ret = ath5k_reset(sc, NULL); if (ret) goto done; @@ -2642,6 +2646,7 @@ ath5k_stop_hw(struct ath5k_softc *sc) tasklet_kill(&sc->restq); tasklet_kill(&sc->calib); tasklet_kill(&sc->beacontq); + tasklet_kill(&sc->ani_tasklet); ath5k_rfkill_hw_stop(sc->ah); @@ -2651,7 +2656,14 @@ ath5k_stop_hw(struct ath5k_softc *sc) static void ath5k_intr_calibration_poll(struct ath5k_hw *ah) { - if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { + if (time_is_before_eq_jiffies(ah->ah_cal_next_ani) && + !(ah->ah_cal_mask & AR5K_CALIBRATION_FULL)) { + /* run ANI only when full calibration is not active */ + ah->ah_cal_next_ani = jiffies + + msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI); + tasklet_schedule(&ah->ah_sc->ani_tasklet); + + } else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { ah->ah_cal_next_full = jiffies + msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); tasklet_schedule(&ah->ah_sc->calib); @@ -2710,7 +2722,9 @@ ath5k_intr(int irq, void *dev_id) /* TODO */ } if (status & AR5K_INT_MIB) { + sc->stats.mib_intr++; ath5k_hw_update_mib_counters(ah); + ath5k_ani_mib_intr(ah); } if (status & AR5K_INT_GPIO) tasklet_schedule(&sc->rf_kill.toggleq); @@ -2775,6 +2789,18 @@ ath5k_tasklet_calibrate(unsigned long data) } +static void +ath5k_tasklet_ani(unsigned long data) +{ + struct ath5k_softc *sc = (void *)data; + struct ath5k_hw *ah = sc->ah; + + ah->ah_cal_mask |= AR5K_CALIBRATION_ANI; + ath5k_ani_calibration(ah); + ah->ah_cal_mask &= ~AR5K_CALIBRATION_ANI; +} + + /********************\ * Mac80211 functions * \********************/ @@ -2874,6 +2900,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) goto err; } + ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode); + /* * Change channels and update the h/w rate map if we're switching; * e.g. 11a to 11b/g. diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index a572a4844800..53a5651c57a2 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -50,6 +50,7 @@ #include "ath5k.h" #include "debug.h" +#include "ani.h" #include "../regd.h" #include "../ath.h" @@ -132,6 +133,8 @@ struct ath5k_statistics { unsigned int rts_ok; unsigned int fcs_error; unsigned int beacons; + + unsigned int mib_intr; }; #if CHAN_DEBUG @@ -221,6 +224,9 @@ struct ath5k_softc { bool enable_beacon; /* true if beacons are on */ struct ath5k_statistics stats; + + struct ath5k_ani_state ani_state; + struct tasklet_struct ani_tasklet; /* ANI calibration */ }; #define ath5k_hw_hasbssidmask(_ah) \ diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 90247dc74198..6fb5c5ffa5b1 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -69,6 +69,7 @@ module_param_named(debug, ath5k_debug, uint, 0); #include #include "reg.h" +#include "ani.h" static struct dentry *ath5k_global_debugfs; @@ -307,6 +308,7 @@ static const struct { { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, + { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, }; @@ -573,6 +575,160 @@ static const struct file_operations fops_frameerrors = { }; +/* debugfs: ani */ + +static ssize_t read_file_ani(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + struct ath5k_statistics *st = &sc->stats; + struct ath5k_ani_state *as = &sc->ani_state; + + char buf[700]; + unsigned int len = 0; + + len += snprintf(buf+len, sizeof(buf)-len, + "HW has PHY error counters:\t%s\n", + sc->ah->ah_capabilities.cap_has_phyerr_counters ? + "yes" : "no"); + len += snprintf(buf+len, sizeof(buf)-len, + "HW max spur immunity level:\t%d\n", + as->max_spur_level); + len += snprintf(buf+len, sizeof(buf)-len, + "\nANI state\n--------------------------------------------\n"); + len += snprintf(buf+len, sizeof(buf)-len, "operating mode:\t\t\t"); + switch (as->ani_mode) { + case ATH5K_ANI_MODE_OFF: + len += snprintf(buf+len, sizeof(buf)-len, "OFF\n"); + break; + case ATH5K_ANI_MODE_MANUAL_LOW: + len += snprintf(buf+len, sizeof(buf)-len, + "MANUAL LOW\n"); + break; + case ATH5K_ANI_MODE_MANUAL_HIGH: + len += snprintf(buf+len, sizeof(buf)-len, + "MANUAL HIGH\n"); + break; + case ATH5K_ANI_MODE_AUTO: + len += snprintf(buf+len, sizeof(buf)-len, "AUTO\n"); + break; + default: + len += snprintf(buf+len, sizeof(buf)-len, + "??? (not good)\n"); + break; + } + len += snprintf(buf+len, sizeof(buf)-len, + "noise immunity level:\t\t%d\n", + as->noise_imm_level); + len += snprintf(buf+len, sizeof(buf)-len, + "spur immunity level:\t\t%d\n", + as->spur_level); + len += snprintf(buf+len, sizeof(buf)-len, "firstep level:\t\t\t%d\n", + as->firstep_level); + len += snprintf(buf+len, sizeof(buf)-len, + "OFDM weak signal detection:\t%s\n", + as->ofdm_weak_sig ? "on" : "off"); + len += snprintf(buf+len, sizeof(buf)-len, + "CCK weak signal detection:\t%s\n", + as->cck_weak_sig ? "on" : "off"); + + len += snprintf(buf+len, sizeof(buf)-len, + "\nMIB INTERRUPTS:\t\t%u\n", + st->mib_intr); + len += snprintf(buf+len, sizeof(buf)-len, + "beacon RSSI average:\t%d\n", + sc->ah->ah_beacon_rssi_avg.avg); + len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n", + as->pfc_tx, + as->pfc_cycles > 0 ? + as->pfc_tx*100/as->pfc_cycles : 0); + len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n", + as->pfc_rx, + as->pfc_cycles > 0 ? + as->pfc_rx*100/as->pfc_cycles : 0); + len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n", + as->pfc_busy, + as->pfc_cycles > 0 ? + as->pfc_busy*100/as->pfc_cycles : 0); + len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n", + as->pfc_cycles); + len += snprintf(buf+len, sizeof(buf)-len, + "listen time\t\t%d\tlast: %d\n", + as->listen_time, as->last_listen); + len += snprintf(buf+len, sizeof(buf)-len, + "OFDM errors\t\t%u\tlast: %u\tsum: %u\n", + as->ofdm_errors, as->last_ofdm_errors, + as->sum_ofdm_errors); + len += snprintf(buf+len, sizeof(buf)-len, + "CCK errors\t\t%u\tlast: %u\tsum: %u\n", + as->cck_errors, as->last_cck_errors, + as->sum_cck_errors); + len += snprintf(buf+len, sizeof(buf)-len, + "AR5K_PHYERR_CNT1\t%x\t(=%d)\n", + ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1), + ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - + ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1))); + len += snprintf(buf+len, sizeof(buf)-len, + "AR5K_PHYERR_CNT2\t%x\t(=%d)\n", + ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2), + ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - + ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2))); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_ani(struct file *file, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; + + if (strncmp(buf, "sens-low", 8) == 0) { + ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_HIGH); + } else if (strncmp(buf, "sens-high", 9) == 0) { + ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_LOW); + } else if (strncmp(buf, "ani-off", 7) == 0) { + ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_OFF); + } else if (strncmp(buf, "ani-on", 6) == 0) { + ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_AUTO); + } else if (strncmp(buf, "noise-low", 9) == 0) { + ath5k_ani_set_noise_immunity_level(sc->ah, 0); + } else if (strncmp(buf, "noise-high", 10) == 0) { + ath5k_ani_set_noise_immunity_level(sc->ah, + ATH5K_ANI_MAX_NOISE_IMM_LVL); + } else if (strncmp(buf, "spur-low", 8) == 0) { + ath5k_ani_set_spur_immunity_level(sc->ah, 0); + } else if (strncmp(buf, "spur-high", 9) == 0) { + ath5k_ani_set_spur_immunity_level(sc->ah, + sc->ani_state.max_spur_level); + } else if (strncmp(buf, "fir-low", 7) == 0) { + ath5k_ani_set_firstep_level(sc->ah, 0); + } else if (strncmp(buf, "fir-high", 8) == 0) { + ath5k_ani_set_firstep_level(sc->ah, ATH5K_ANI_MAX_FIRSTEP_LVL); + } else if (strncmp(buf, "ofdm-off", 8) == 0) { + ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, false); + } else if (strncmp(buf, "ofdm-on", 7) == 0) { + ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, true); + } else if (strncmp(buf, "cck-off", 7) == 0) { + ath5k_ani_set_cck_weak_signal_detection(sc->ah, false); + } else if (strncmp(buf, "cck-on", 6) == 0) { + ath5k_ani_set_cck_weak_signal_detection(sc->ah, true); + } + return count; +} + +static const struct file_operations fops_ani = { + .read = read_file_ani, + .write = write_file_ani, + .open = ath5k_debugfs_open, + .owner = THIS_MODULE, +}; + + /* init */ void @@ -611,6 +767,11 @@ ath5k_debug_init_device(struct ath5k_softc *sc) S_IWUSR | S_IRUSR, sc->debug.debugfs_phydir, sc, &fops_frameerrors); + + sc->debug.debugfs_ani = debugfs_create_file("ani", + S_IWUSR | S_IRUSR, + sc->debug.debugfs_phydir, sc, + &fops_ani); } void @@ -628,6 +789,7 @@ ath5k_debug_finish_device(struct ath5k_softc *sc) debugfs_remove(sc->debug.debugfs_reset); debugfs_remove(sc->debug.debugfs_antenna); debugfs_remove(sc->debug.debugfs_frameerrors); + debugfs_remove(sc->debug.debugfs_ani); debugfs_remove(sc->debug.debugfs_phydir); } diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index da24ff52e274..ddd5b3a99e8d 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h @@ -76,6 +76,7 @@ struct ath5k_dbg_info { struct dentry *debugfs_reset; struct dentry *debugfs_antenna; struct dentry *debugfs_frameerrors; + struct dentry *debugfs_ani; }; /** @@ -115,6 +116,7 @@ enum ath5k_debug_level { ATH5K_DEBUG_DUMP_TX = 0x00000200, ATH5K_DEBUG_DUMPBANDS = 0x00000400, ATH5K_DEBUG_TRACE = 0x00001000, + ATH5K_DEBUG_ANI = 0x00002000, ATH5K_DEBUG_ANY = 0xffffffff }; diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 9d920fb14d5d..7d7b646ab65a 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -645,6 +645,7 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, rs->rs_status |= AR5K_RXERR_PHY; rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); + ath5k_ani_phy_error_report(ah, rs->rs_phyerr); } if (rx_status->rx_status_1 & diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index c7c1fe023724..710870ea179b 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -379,7 +379,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) * (ACK etc). * * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma - * TODO: Init ANI here */ void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) { diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index f325e664065a..cbd11d4c98e8 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -212,10 +212,10 @@ * MIB control register */ #define AR5K_MIBC 0x0040 /* Register Address */ -#define AR5K_MIBC_COW 0x00000001 /* Warn test indicator */ +#define AR5K_MIBC_COW 0x00000001 /* Counter Overflow Warning */ #define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */ -#define AR5K_MIBC_CMC 0x00000004 /* Clean MIB Counters */ -#define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe */ +#define AR5K_MIBC_CMC 0x00000004 /* Clear MIB Counters */ +#define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe, increment all */ /* * Timeout prescale register @@ -1516,7 +1516,14 @@ AR5K_NAV_5210 : AR5K_NAV_5211) /* - * RTS success register + * MIB counters: + * + * max value is 0xc000, if this is reached we get a MIB interrupt. + * they can be controlled via AR5K_MIBC and are cleared on read. + */ + +/* + * RTS success (MIB counter) */ #define AR5K_RTS_OK_5210 0x8090 #define AR5K_RTS_OK_5211 0x8088 @@ -1524,7 +1531,7 @@ AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211) /* - * RTS failure register + * RTS failure (MIB counter) */ #define AR5K_RTS_FAIL_5210 0x8094 #define AR5K_RTS_FAIL_5211 0x808c @@ -1532,7 +1539,7 @@ AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211) /* - * ACK failure register + * ACK failure (MIB counter) */ #define AR5K_ACK_FAIL_5210 0x8098 #define AR5K_ACK_FAIL_5211 0x8090 @@ -1540,7 +1547,7 @@ AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211) /* - * FCS failure register + * FCS failure (MIB counter) */ #define AR5K_FCS_FAIL_5210 0x809c #define AR5K_FCS_FAIL_5211 0x8094 @@ -1667,11 +1674,17 @@ /* * Profile count registers + * + * These registers can be cleared and freezed with ATH5K_MIBC, but they do not + * generate a MIB interrupt. + * Instead of overflowing, they shift by one bit to the right. All registers + * shift together, i.e. when one reaches the max, all shift at the same time by + * one bit to the right. This way we should always get consistent values. */ #define AR5K_PROFCNT_TX 0x80ec /* Tx count */ #define AR5K_PROFCNT_RX 0x80f0 /* Rx count */ -#define AR5K_PROFCNT_RXCLR 0x80f4 /* Clear Rx count */ -#define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle count (?) */ +#define AR5K_PROFCNT_RXCLR 0x80f4 /* Busy count */ +#define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle counter */ /* * Quiet period control registers @@ -1758,7 +1771,7 @@ #define AR5K_CCK_FIL_CNT 0x8128 /* - * PHY Error Counters (?) + * PHY Error Counters (same masks as AR5K_PHY_ERR_FIL) */ #define AR5K_PHYERR_CNT1 0x812c #define AR5K_PHYERR_CNT1_MASK 0x8130 @@ -1766,6 +1779,9 @@ #define AR5K_PHYERR_CNT2 0x8134 #define AR5K_PHYERR_CNT2_MASK 0x8138 +/* if the PHY Error Counters reach this maximum, we get MIB interrupts */ +#define ATH5K_PHYERR_CNT_MAX 0x00c00000 + /* * TSF Threshold register (?) */ -- cgit v1.2.3 From 7590a550b88b8c3cb025f0a8ed58e279ad62e4c1 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Fri, 2 Apr 2010 15:31:46 +0300 Subject: wl1251: use DRIVER_NAME macro in wl1251_spi_driver Better use the macro for consistency, the content is the same anyway. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c index 9cc8c323830f..df2ff8bc8ef4 100644 --- a/drivers/net/wireless/wl12xx/wl1251_spi.c +++ b/drivers/net/wireless/wl12xx/wl1251_spi.c @@ -309,7 +309,7 @@ static int __devexit wl1251_spi_remove(struct spi_device *spi) static struct spi_driver wl1251_spi_driver = { .driver = { - .name = "wl1251", + .name = DRIVER_NAME, .bus = &spi_bus_type, .owner = THIS_MODULE, }, -- cgit v1.2.3 From 53bc7aa08b48e5cd745f986731cc7dc24eef2a9f Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Mon, 5 Apr 2010 14:48:04 +0530 Subject: ath9k: Add support for newer AR9285 chipsets. This patch adds support for a modified newer version of AR9285 chipsets. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 59 +++++++++++++++- drivers/net/wireless/ath/ath9k/hw.c | 29 ++++++-- drivers/net/wireless/ath/ath9k/initvals.h | 109 ++++++++++++++++++++++++++---- drivers/net/wireless/ath/ath9k/phy.h | 14 +++- drivers/net/wireless/ath/ath9k/reg.h | 13 +++- 5 files changed, 201 insertions(+), 23 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index d5026e4f484b..064f5b51dfcd 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -18,6 +18,7 @@ /* We can tune this as we go by monitoring really low values */ #define ATH9K_NF_TOO_LOW -60 +#define AR9285_CLCAL_REDO_THRESH 1 /* AR5416 may return very high value (like -31 dBm), in those cases the nf * is incorrect and we should use the static NF value. Later we can try to @@ -1091,7 +1092,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, EXPORT_SYMBOL(ath9k_hw_calibrate); /* Carrier leakage Calibration fix */ -static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) +static bool ar9285_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) { struct ath_common *common = ath9k_hw_common(ah); @@ -1132,6 +1133,62 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) return true; } +static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) +{ + int i; + u_int32_t txgain_max; + u_int32_t clc_gain, gain_mask = 0, clc_num = 0; + u_int32_t reg_clc_I0, reg_clc_Q0; + u_int32_t i0_num = 0; + u_int32_t q0_num = 0; + u_int32_t total_num = 0; + u_int32_t reg_rf2g5_org; + bool retv = true; + + if (!(ar9285_cl_cal(ah, chan))) + return false; + + txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7), + AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX); + + for (i = 0; i < (txgain_max+1); i++) { + clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) & + AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S; + if (!(gain_mask & (1 << clc_gain))) { + gain_mask |= (1 << clc_gain); + clc_num++; + } + } + + for (i = 0; i < clc_num; i++) { + reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) + & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S; + reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) + & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S; + if (reg_clc_I0 == 0) + i0_num++; + + if (reg_clc_Q0 == 0) + q0_num++; + } + total_num = i0_num + q0_num; + if (total_num > AR9285_CLCAL_REDO_THRESH) { + reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5); + if (AR_SREV_9285E_20(ah)) { + REG_WRITE(ah, AR9285_RF2G5, + (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | + AR9285_RF2G5_IC50TX_XE_SET); + } else { + REG_WRITE(ah, AR9285_RF2G5, + (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | + AR9285_RF2G5_IC50TX_SET); + } + retv = ar9285_cl_cal(ah, chan); + REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org); + } + return retv; +} + bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) { struct ath_common *common = ath9k_hw_common(ah); diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index feae55a8124d..81965b2d263b 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -815,15 +815,30 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) /* txgain table */ if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9285Modes_high_power_tx_gain_9285_1_2, - ARRAY_SIZE(ar9285Modes_high_power_tx_gain_9285_1_2), 6); + if (AR_SREV_9285E_20(ah)) { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9285Modes_XE2_0_high_power, + ARRAY_SIZE( + ar9285Modes_XE2_0_high_power), 6); + } else { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9285Modes_high_power_tx_gain_9285_1_2, + ARRAY_SIZE( + ar9285Modes_high_power_tx_gain_9285_1_2), 6); + } } else { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9285Modes_original_tx_gain_9285_1_2, - ARRAY_SIZE(ar9285Modes_original_tx_gain_9285_1_2), 6); + if (AR_SREV_9285E_20(ah)) { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9285Modes_XE2_0_normal_power, + ARRAY_SIZE( + ar9285Modes_XE2_0_normal_power), 6); + } else { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9285Modes_original_tx_gain_9285_1_2, + ARRAY_SIZE( + ar9285Modes_original_tx_gain_9285_1_2), 6); + } } - } } diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h index 177bdeb84ad7..455e9d3b3f13 100644 --- a/drivers/net/wireless/ath/ath9k/initvals.h +++ b/drivers/net/wireless/ath/ath9k/initvals.h @@ -4184,7 +4184,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, + { 0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, @@ -4198,8 +4198,8 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, + { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, @@ -4312,7 +4312,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, + { 0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, @@ -4326,8 +4326,8 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, + { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, @@ -4731,17 +4731,12 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { { 0x00007808, 0x54214514 }, { 0x0000780c, 0x02025830 }, { 0x00007810, 0x71c0d388 }, - { 0x00007814, 0x924934a8 }, { 0x0000781c, 0x00000000 }, { 0x00007824, 0x00d86fff }, - { 0x00007828, 0x26d2491b }, { 0x0000782c, 0x6e36d97b }, - { 0x00007830, 0xedb6d96e }, { 0x00007834, 0x71400087 }, - { 0x0000783c, 0x0001fffe }, - { 0x00007840, 0xffeb1a20 }, { 0x00007844, 0x000c0db6 }, - { 0x00007848, 0x6db61b6f }, + { 0x00007848, 0x6db6246f }, { 0x0000784c, 0x6d9b66db }, { 0x00007850, 0x6d8c6dba }, { 0x00007854, 0x00040000 }, @@ -4777,7 +4772,12 @@ static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 }, + { 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b }, + { 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e }, { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, + { 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe }, + { 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 }, { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, @@ -4813,7 +4813,12 @@ static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 }, + { 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b }, + { 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e }, { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 }, + { 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe }, + { 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 }, { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, @@ -4825,6 +4830,86 @@ static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, }; +static const u_int32_t ar9285Modes_XE2_0_normal_power[][6] = { + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 }, + { 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b }, + { 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6dbae }, + { 0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441 }, + { 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe }, + { 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c }, + { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, + { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, + { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, + { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, + { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, + { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, +}; + +static const u_int32_t ar9285Modes_XE2_0_high_power[][6] = { + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 }, + { 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b }, + { 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e }, + { 0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443 }, + { 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe }, + { 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c }, + { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, + { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, + { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 }, + { 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, + { 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, +}; + static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { {0x00004040, 0x9248fd00 }, {0x00004040, 0x24924924 }, diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 0999a495fd46..0132e4c9a9f9 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -503,6 +503,8 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, #define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 #define AR_PHY_TX_PWRCTRL7 0xa274 +#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX 0x0007E000 +#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX_S 13 #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 @@ -513,8 +515,16 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 #define AR_PHY_TX_GAIN_TBL1 0xa300 -#define AR_PHY_TX_GAIN 0x0007F000 -#define AR_PHY_TX_GAIN_S 12 +#define AR_PHY_TX_GAIN_CLC 0x0000001E +#define AR_PHY_TX_GAIN_CLC_S 1 +#define AR_PHY_TX_GAIN 0x0007F000 +#define AR_PHY_TX_GAIN_S 12 + +#define AR_PHY_CLC_TBL1 0xa35c +#define AR_PHY_CLC_I0 0x07ff0000 +#define AR_PHY_CLC_I0_S 16 +#define AR_PHY_CLC_Q0 0x0000ffd0 +#define AR_PHY_CLC_Q0_S 5 #define AR_PHY_CH0_TX_PWRCTRL11 0xa398 #define AR_PHY_CH1_TX_PWRCTRL11 0xb398 diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 198e41dd38a6..7e36ad7421b7 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -679,7 +679,7 @@ #define AR_WA 0x4004 #define AR_WA_D3_L1_DISABLE (1 << 14) -#define AR9285_WA_DEFAULT 0x004a05cb +#define AR9285_WA_DEFAULT 0x004a050b #define AR9280_WA_DEFAULT 0x0040073b #define AR_WA_DEFAULT 0x0000073f @@ -845,6 +845,10 @@ (AR_SREV_9271(_ah) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11)) +#define AR_SREV_9285E_20(_ah) \ + (AR_SREV_9285_12_OR_LATER(_ah) && \ + ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) + #define AR_RADIO_SREV_MAJOR 0xf0 #define AR_RAD5133_SREV_MAJOR 0xc0 #define AR_RAD2133_SREV_MAJOR 0xd0 @@ -1181,6 +1185,13 @@ enum { #define AR9285_AN_RF2G4_DB2_4 0x00003800 #define AR9285_AN_RF2G4_DB2_4_S 11 +#define AR9285_RF2G5 0x7830 +#define AR9285_RF2G5_IC50TX 0xfffff8ff +#define AR9285_RF2G5_IC50TX_SET 0x00000400 +#define AR9285_RF2G5_IC50TX_XE_SET 0x00000500 +#define AR9285_RF2G5_IC50TX_CLEAR 0x00000700 +#define AR9285_RF2G5_IC50TX_CLEAR_S 8 + /* AR9271 : 0x7828, 0x782c different setting from AR9285 */ #define AR9271_AN_RF2G3_OB_cck 0x001C0000 #define AR9271_AN_RF2G3_OB_cck_S 18 -- cgit v1.2.3 From bde748a40d4d5a9915def6772e208848c105e616 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Mon, 5 Apr 2010 14:48:05 +0530 Subject: ath9k_htc: Add support for power save. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 9 +++ drivers/net/wireless/ath/ath9k/htc_drv_init.c | 8 ++- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 93 ++++++++++++++++++++++++++- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 7 +- drivers/net/wireless/ath/ath9k/hw.c | 6 +- 5 files changed, 117 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index e09c6c2c9e23..0160e83f8fb6 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -363,6 +363,11 @@ struct ath9k_htc_priv { struct ath9k_htc_aggr_work aggr_work; struct delayed_work ath9k_aggr_work; struct delayed_work ath9k_ani_work; + struct work_struct ps_work; + + struct mutex htc_pm_lock; + unsigned long ps_usecount; + bool ps_enabled; struct ath_led radio_led; struct ath_led assoc_led; @@ -420,6 +425,10 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv); void ath9k_rx_tasklet(unsigned long data); u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv); +void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv); +void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv); +void ath9k_ps_work(struct work_struct *work); + void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); void ath9k_init_leds(struct ath9k_htc_priv *priv); void ath9k_deinit_leds(struct ath9k_htc_priv *priv); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index e268d458e7df..aed53573c547 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -454,6 +454,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) spin_lock_init(&priv->tx_lock); mutex_init(&priv->mutex); mutex_init(&priv->aggr_work.mutex); + mutex_init(&priv->htc_pm_lock); tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, (unsigned long)priv); tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, @@ -461,6 +462,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); INIT_DELAYED_WORK(&priv->ath9k_aggr_work, ath9k_htc_aggr_work); INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); + INIT_WORK(&priv->ps_work, ath9k_ps_work); /* * Cache line size is used to size and align various @@ -515,12 +517,16 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_HAS_RATE_CONTROL | - IEEE80211_HW_RX_INCLUDES_FCS; + IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); + hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; + hw->queues = 4; hw->channel_change_time = 5000; hw->max_listen_interval = 10; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 63f032d61d5a..e04452f888e0 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -65,6 +65,56 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, return mode; } +static bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, + enum ath9k_power_mode mode) +{ + bool ret; + + mutex_lock(&priv->htc_pm_lock); + ret = ath9k_hw_setpower(priv->ah, mode); + mutex_unlock(&priv->htc_pm_lock); + + return ret; +} + +void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv) +{ + mutex_lock(&priv->htc_pm_lock); + if (++priv->ps_usecount != 1) + goto unlock; + ath9k_hw_setpower(priv->ah, ATH9K_PM_AWAKE); + +unlock: + mutex_unlock(&priv->htc_pm_lock); +} + +void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv) +{ + mutex_lock(&priv->htc_pm_lock); + if (--priv->ps_usecount != 0) + goto unlock; + + if (priv->ps_enabled) + ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP); +unlock: + mutex_unlock(&priv->htc_pm_lock); +} + +void ath9k_ps_work(struct work_struct *work) +{ + struct ath9k_htc_priv *priv = + container_of(work, struct ath9k_htc_priv, + ps_work); + ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); + + /* The chip wakes up after receiving the first beacon + while network sleep is enabled. For the driver to + be in sync with the hw, set the chip to awake and + only then set it to sleep. + */ + ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); +} + static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, struct ieee80211_hw *hw, struct ath9k_channel *hchan) @@ -87,7 +137,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, /* Fiddle around with fastcc later on, for now just use full reset */ fastcc = false; - + ath9k_htc_ps_wakeup(priv); htc_stop(priv->htc); WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); @@ -103,6 +153,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, ath_print(common, ATH_DBG_FATAL, "Unable to reset channel (%u Mhz) " "reset status %d\n", channel->center_freq, ret); + ath9k_htc_ps_restore(priv); goto err; } @@ -128,6 +179,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, priv->op_flags &= ~OP_FULL_RESET; err: + ath9k_htc_ps_restore(priv); return ret; } @@ -693,6 +745,10 @@ void ath9k_ani_work(struct work_struct *work) short_cal_interval = ATH_STA_SHORT_CALINTERVAL; + /* Only calibrate if awake */ + if (ah->power_mode != ATH9K_PM_AWAKE) + goto set_timer; + /* Long calibration runs independently of short calibration. */ if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { longcal = true; @@ -727,6 +783,9 @@ void ath9k_ani_work(struct work_struct *work) /* Skip all processing if there's nothing to do. */ if (longcal || shortcal || aniflag) { + + ath9k_htc_ps_wakeup(priv); + /* Call ANI routine if necessary */ if (aniflag) ath9k_hw_ani_monitor(ah, ah->curchan); @@ -748,8 +807,11 @@ void ath9k_ani_work(struct work_struct *work) ah->curchan->channelFlags, common->ani.noise_floor); } + + ath9k_htc_ps_restore(priv); } +set_timer: /* * Set timer interval based on previous results. * The interval must be the shortest necessary to satisfy ANI, @@ -1112,6 +1174,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) return; } + ath9k_htc_ps_wakeup(priv); htc_stop(priv->htc); WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); @@ -1119,8 +1182,10 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) ath9k_hw_phy_disable(ah); ath9k_hw_disable(ah); ath9k_hw_configpcipowersave(ah, 1, 1); - ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); + ath9k_htc_ps_restore(priv); + ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); + cancel_work_sync(&priv->ps_work); cancel_delayed_work_sync(&priv->ath9k_ani_work); cancel_delayed_work_sync(&priv->ath9k_aggr_work); cancel_delayed_work_sync(&priv->ath9k_led_blink_work); @@ -1161,6 +1226,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, goto out; } + ath9k_htc_ps_wakeup(priv); memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); @@ -1207,6 +1273,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, priv->vif = vif; out: + ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); return ret; } @@ -1275,6 +1342,16 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) } } + if (changed & IEEE80211_CONF_CHANGE_PS) { + if (conf->flags & IEEE80211_CONF_PS) { + ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); + priv->ps_enabled = true; + } else { + priv->ps_enabled = false; + cancel_work_sync(&priv->ps_work); + ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); + } + } if (changed & IEEE80211_CONF_CHANGE_MONITOR) { if (conf->flags & IEEE80211_CONF_MONITOR) { @@ -1311,6 +1388,7 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); changed_flags &= SUPPORTED_FILTERS; *total_flags &= SUPPORTED_FILTERS; @@ -1321,6 +1399,7 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", rfilt); + ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); } @@ -1398,6 +1477,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); + ath9k_htc_ps_wakeup(priv); switch (cmd) { case SET_KEY: @@ -1420,6 +1500,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, ret = -EINVAL; } + ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); return ret; @@ -1435,6 +1516,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, struct ath_common *common = ath9k_hw_common(ah); mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); if (changed & BSS_CHANGED_ASSOC) { common->curaid = bss_conf->assoc ? @@ -1447,6 +1529,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, ath_start_ani(priv); } else { priv->op_flags &= ~OP_ASSOCIATED; + cancel_work_sync(&priv->ps_work); cancel_delayed_work_sync(&priv->ath9k_ani_work); } } @@ -1506,6 +1589,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, ath9k_hw_init_global_settings(ah); } + ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); } @@ -1534,9 +1618,11 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw) { struct ath9k_htc_priv *priv = hw->priv; + ath9k_htc_ps_wakeup(priv); mutex_lock(&priv->mutex); ath9k_hw_reset_tsf(priv->ah); mutex_unlock(&priv->mutex); + ath9k_htc_ps_restore(priv); } static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, @@ -1585,6 +1671,7 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) spin_lock_bh(&priv->beacon_lock); priv->op_flags |= OP_SCANNING; spin_unlock_bh(&priv->beacon_lock); + cancel_work_sync(&priv->ps_work); cancel_delayed_work_sync(&priv->ath9k_ani_work); mutex_unlock(&priv->mutex); } @@ -1593,6 +1680,7 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) { struct ath9k_htc_priv *priv = hw->priv; + ath9k_htc_ps_wakeup(priv); mutex_lock(&priv->mutex); spin_lock_bh(&priv->beacon_lock); priv->op_flags &= ~OP_SCANNING; @@ -1600,6 +1688,7 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) priv->op_flags |= OP_FULL_RESET; ath_start_ani(priv); mutex_unlock(&priv->mutex); + ath9k_htc_ps_restore(priv); } static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index f1e3d830d7de..0a7cb30af5b4 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -553,7 +553,7 @@ void ath9k_rx_tasklet(unsigned long data) struct ieee80211_rx_status rx_status; struct sk_buff *skb; unsigned long flags; - + struct ieee80211_hdr *hdr; do { spin_lock_irqsave(&priv->rx.rxbuflock, flags); @@ -580,6 +580,11 @@ void ath9k_rx_tasklet(unsigned long data) memcpy(IEEE80211_SKB_RXCB(rxbuf->skb), &rx_status, sizeof(struct ieee80211_rx_status)); skb = rxbuf->skb; + hdr = (struct ieee80211_hdr *) skb->data; + + if (ieee80211_is_beacon(hdr->frame_control) && priv->ps_enabled) + ieee80211_queue_work(priv->hw, &priv->ps_work); + spin_unlock_irqrestore(&priv->rx.rxbuflock, flags); ieee80211_rx(priv->hw, skb); diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 81965b2d263b..88f8bfdbded4 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -3245,8 +3245,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; } #endif - - pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; + if (AR_SREV_9271(ah)) + pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; + else + pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; -- cgit v1.2.3 From 1c3652a5732879263aeebe606ca7af9e66fe0b2f Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Mon, 5 Apr 2010 14:48:06 +0530 Subject: ath9k_htc: Configure the beacon timers once the scan is completed. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 12 ++++++-- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 41 +++++++++++++++++-------- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 6 ++-- 3 files changed, 43 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 0160e83f8fb6..78213fc71b09 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -309,6 +309,14 @@ struct ath_led { int brightness; }; +struct htc_beacon_config { + u16 beacon_interval; + u16 listen_interval; + u16 dtim_period; + u16 bmiss_timeout; + u8 dtim_count; +}; + #define OP_INVALID BIT(0) #define OP_SCANNING BIT(1) #define OP_FULL_RESET BIT(2) @@ -353,6 +361,7 @@ struct ath9k_htc_priv { spinlock_t tx_lock; struct ieee80211_vif *vif; + struct htc_beacon_config cur_beacon_conf; unsigned int rxfilter; struct tasklet_struct wmi_tasklet; struct tasklet_struct rx_tasklet; @@ -394,8 +403,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) } void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf); + struct ieee80211_vif *vif); void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); void ath9k_htc_beacon_update(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 25f5b5377bac..5e21f4d92ff5 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -19,7 +19,7 @@ #define FUDGE 2 static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, - struct ieee80211_bss_conf *bss_conf) + struct htc_beacon_config *bss_conf) { struct ath_common *common = ath9k_hw_common(priv->ah); struct ath9k_beacon_state bs; @@ -34,8 +34,8 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, memset(&bs, 0, sizeof(bs)); - intval = bss_conf->beacon_int & ATH9K_BEACON_PERIOD; - bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_int); + intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; + bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval); /* * Setup dtim and cfp parameters according to @@ -138,7 +138,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, } static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, - struct ieee80211_bss_conf *bss_conf) + struct htc_beacon_config *bss_conf) { struct ath_common *common = ath9k_hw_common(priv->ah); enum ath9k_int imask = 0; @@ -146,7 +146,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, int ret; u8 cmd_rsp; - intval = bss_conf->beacon_int & ATH9K_BEACON_PERIOD; + intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; nexttbtt = intval; intval |= ATH9K_BEACON_ENA; if (priv->op_flags & OP_ENABLE_BEACON) @@ -154,7 +154,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, ath_print(common, ATH_DBG_BEACON, "IBSS Beacon config, intval: %d, imask: 0x%x\n", - bss_conf->beacon_int, imask); + bss_conf->beacon_interval, imask); WMI_CMD(WMI_DISABLE_INTR_CMDID); ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); @@ -239,18 +239,35 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) spin_unlock_bh(&priv->beacon_lock); } + void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf) + struct ieee80211_vif *vif) { struct ath_common *common = ath9k_hw_common(priv->ah); - - switch (vif->type) { + enum nl80211_iftype iftype; + struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; + + if (vif) { + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + iftype = vif->type; + cur_conf->beacon_interval = bss_conf->beacon_int; + cur_conf->dtim_period = bss_conf->dtim_period; + cur_conf->listen_interval = 1; + cur_conf->dtim_count = 1; + cur_conf->bmiss_timeout = + ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; + } else + iftype = priv->ah->opmode; + + if (cur_conf->beacon_interval == 0) + cur_conf->beacon_interval = 100; + + switch (iftype) { case NL80211_IFTYPE_STATION: - ath9k_htc_beacon_config_sta(priv, bss_conf); + ath9k_htc_beacon_config_sta(priv, cur_conf); break; case NL80211_IFTYPE_ADHOC: - ath9k_htc_beacon_config_adhoc(priv, bss_conf); + ath9k_htc_beacon_config_adhoc(priv, cur_conf); break; default: ath_print(common, ATH_DBG_CONFIG, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index e04452f888e0..eb7722b2cfcc 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1549,7 +1549,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) { priv->op_flags |= OP_ENABLE_BEACON; - ath9k_htc_beacon_config(priv, vif, bss_conf); + ath9k_htc_beacon_config(priv, vif); } if (changed & BSS_CHANGED_BEACON) @@ -1558,7 +1558,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) { priv->op_flags &= ~OP_ENABLE_BEACON; - ath9k_htc_beacon_config(priv, vif, bss_conf); + ath9k_htc_beacon_config(priv, vif); } if (changed & BSS_CHANGED_ERP_PREAMBLE) { @@ -1686,6 +1686,8 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) priv->op_flags &= ~OP_SCANNING; spin_unlock_bh(&priv->beacon_lock); priv->op_flags |= OP_FULL_RESET; + if (priv->op_flags & OP_ASSOCIATED) + ath9k_htc_beacon_config(priv, NULL); ath_start_ani(priv); mutex_unlock(&priv->mutex); ath9k_htc_ps_restore(priv); -- cgit v1.2.3 From 60ece4047e4870c7be28dcf661162d8312c161e7 Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Wed, 24 Mar 2010 19:46:30 +0100 Subject: wireless/ath: remove trailing space in messages Signed-off-by: Frans Pop Cc: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 4 ++-- drivers/net/wireless/ath/ath9k/eeprom_4k.c | 2 +- drivers/net/wireless/ath/ath9k/eeprom_9287.c | 2 +- drivers/net/wireless/ath/ath9k/gpio.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index c7e895925393..b22d46509b67 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -156,10 +156,10 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n", (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); - len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x \n", + len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x\n", REG_READ_D(ah, AR_OBS_BUS_1)); len += snprintf(buf + len, DMA_BUF_LEN - len, - "AR_CR: 0x%x \n", REG_READ_D(ah, AR_CR)); + "AR_CR: 0x%x\n", REG_READ_D(ah, AR_CR)); ath9k_ps_restore(sc); diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 68db16690abf..0354fe50f8e0 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -43,7 +43,7 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) { ath_print(common, ATH_DBG_EEPROM, - "Unable to read eeprom region \n"); + "Unable to read eeprom region\n"); return false; } eep_data++; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 839d05a1df29..d8ca94c3fa0c 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -44,7 +44,7 @@ static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) { ath_print(common, ATH_DBG_EEPROM, - "Unable to read eeprom region \n"); + "Unable to read eeprom region\n"); return false; } eep_data++; diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 1e4578d303dd..0ee75e79fe35 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -359,7 +359,7 @@ static void ath_btcoex_no_stomp_timer(void *arg) bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, - "no stomp timer running \n"); + "no stomp timer running\n"); spin_lock_bh(&btcoex->btcoex_lock); -- cgit v1.2.3 From 62c33447fa720d71b05bbc626b01351a4889c2d7 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Tue, 30 Mar 2010 23:50:24 +0200 Subject: rt2x00: Enable powersaving by default again on rt2500usb. Now that the powersave issues on rt2500usb have been tackled, powersave can be enabled by default again. Signed-off-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 54d2716e389c..c1eec17fe186 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1646,11 +1646,6 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) char *tx_power; unsigned int i; - /* - * Disable powersaving as default. - */ - rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; - /* * Initialize all hw fields. */ -- cgit v1.2.3 From 46baa1a24945b5813097af5a632db721f9c9d03b Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 6 Apr 2010 15:28:11 +0530 Subject: ath9k_htc: Protect RX stream variables Use a spin lock to prevent concurrent access to variables dealing with RX stream mode handling. Currently, no protection is implemented - which causes problems in RX. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 8 ++++++++ drivers/net/wireless/ath/ath9k/hif_usb.h | 1 + 2 files changed, 9 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 3afc747ccfbf..8838cdfcc497 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -330,6 +330,8 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, u16 pkt_len, pkt_tag, pool_index = 0; u8 *ptr; + spin_lock(&hif_dev->rx_lock); + rx_remain_len = hif_dev->rx_remain_len; rx_pkt_len = hif_dev->rx_transfer_len; @@ -356,6 +358,8 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, } } + spin_unlock(&hif_dev->rx_lock); + while (index < len) { ptr = (u8 *) skb->data; @@ -373,6 +377,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, index = index + 4 + pkt_len + pad_len; if (index > MAX_RX_BUF_SIZE) { + spin_lock(&hif_dev->rx_lock); hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; hif_dev->rx_transfer_len = MAX_RX_BUF_SIZE - chk_idx - 4; @@ -384,6 +389,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, dev_err(&hif_dev->udev->dev, "ath9k_htc: RX memory allocation" " error\n"); + spin_unlock(&hif_dev->rx_lock); goto err; } skb_reserve(nskb, 32); @@ -394,6 +400,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, /* Record the buffer pointer */ hif_dev->remain_skb = nskb; + spin_unlock(&hif_dev->rx_lock); } else { nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); if (!nskb) { @@ -612,6 +619,7 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) int i, ret; init_usb_anchor(&hif_dev->rx_submitted); + spin_lock_init(&hif_dev->rx_lock); for (i = 0; i < MAX_RX_URB_NUM; i++) { diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index ea9257bdc411..ed9708cd4aa0 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -93,6 +93,7 @@ struct hif_device_usb { int rx_pkt_len; int rx_transfer_len; int rx_pad_len; + spinlock_t rx_lock; u8 flags; /* HIF_USB_* */ }; -- cgit v1.2.3 From 66b10e33f742bb45a29b7dbbc8dc85583d4c9ef6 Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 6 Apr 2010 15:28:13 +0530 Subject: ath9k_htc: Fix RX URB reference count RX URBs are automatically freed when the reference count drops to zero - this currently doesn't happen when usb_kill_anchored_urbs() is called during unload. Fix this by dropping the reference count by one during initial submission. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 8838cdfcc497..4528df4a5bdc 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -652,6 +652,12 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) usb_unanchor_urb(urb); goto err_submit; } + + /* + * Drop reference count. + * This ensures that the URB is freed when killing them. + */ + usb_free_urb(urb); } return 0; -- cgit v1.2.3 From c503269a0f77e9b2d6de9e8a5f66ace53dde6e04 Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 6 Apr 2010 15:28:15 +0530 Subject: ath9k_htc: Fix module unloading issue The maximum number of packets in a single buffer in stream mode is 10. The driver currently uses 8 - which caused stack corruption, in the absence of any kind of OOB checking. Fixing this to the correct value of 10 fixes the module unload issue. Signed-off-by: Sujith Tested-by: Ming Lei Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 2 +- drivers/net/wireless/ath/ath9k/hif_usb.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 4528df4a5bdc..69bef1de71ae 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -324,7 +324,7 @@ static struct ath9k_htc_hif hif_usb = { static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, struct sk_buff *skb) { - struct sk_buff *nskb, *skb_pool[8]; + struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER]; int index = 0, i = 0, chk_idx, len = skb->len; int rx_remain_len = 0, rx_pkt_len = 0; u16 pkt_len, pkt_tag, pool_index = 0; diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index ed9708cd4aa0..179cea46a8e7 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -34,6 +34,7 @@ #define MAX_RX_URB_NUM 8 #define MAX_RX_BUF_SIZE 16384 +#define MAX_PKT_NUM_IN_TRANSFER 10 #define MAX_REG_OUT_URB_NUM 1 #define MAX_REG_OUT_BUF_NUM 8 -- cgit v1.2.3 From 6f0f2669f508fb239a0f589a8b453dbe22112bf9 Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 6 Apr 2010 15:28:17 +0530 Subject: ath9k_htc: Use anchors for REGOUT pipe hif_usb_regout_cb() frees the given URB, which is borked by design. Use an anchor to simplify URB management. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 30 ++++++++++++++---------------- drivers/net/wireless/ath/ath9k/hif_usb.h | 1 + 2 files changed, 15 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 69bef1de71ae..e2117e7222e7 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -32,27 +32,15 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev); static void hif_usb_regout_cb(struct urb *urb) { struct cmd_buf *cmd = (struct cmd_buf *)urb->context; - struct hif_device_usb *hif_dev = cmd->hif_dev; - - if (!hif_dev) { - usb_free_urb(urb); - if (cmd) { - if (cmd->skb) - dev_kfree_skb_any(cmd->skb); - kfree(cmd); - } - return; - } switch (urb->status) { case 0: break; case -ENOENT: case -ECONNRESET: - break; case -ENODEV: case -ESHUTDOWN: - return; + goto free; default: break; } @@ -61,8 +49,12 @@ static void hif_usb_regout_cb(struct urb *urb) ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, cmd->skb, 1); kfree(cmd); - usb_free_urb(urb); } + + return; +free: + dev_kfree_skb_any(cmd->skb); + kfree(cmd); } static int hif_usb_send_regout(struct hif_device_usb *hif_dev, @@ -90,11 +82,13 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev, skb->data, skb->len, hif_usb_regout_cb, cmd, 1); + usb_anchor_urb(urb, &hif_dev->regout_submitted); ret = usb_submit_urb(urb, GFP_KERNEL); if (ret) { - usb_free_urb(urb); + usb_unanchor_urb(urb); kfree(cmd); } + usb_free_urb(urb); return ret; } @@ -711,6 +705,9 @@ err: static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) { + /* Register Write */ + init_usb_anchor(&hif_dev->regout_submitted); + /* TX */ if (ath9k_hif_usb_alloc_tx_urbs(hif_dev) < 0) goto err; @@ -719,7 +716,7 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) if (ath9k_hif_usb_alloc_rx_urbs(hif_dev) < 0) goto err; - /* Register Read/Write */ + /* Register Read */ if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0) goto err; @@ -816,6 +813,7 @@ err_fw_req: static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) { + usb_kill_anchored_urbs(&hif_dev->regout_submitted); ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); ath9k_hif_usb_dealloc_tx_urbs(hif_dev); ath9k_hif_usb_dealloc_rx_urbs(hif_dev); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 179cea46a8e7..7d49a8af420e 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -88,6 +88,7 @@ struct hif_device_usb { struct htc_target *htc_handle; struct hif_usb_tx tx; struct urb *reg_in_urb; + struct usb_anchor regout_submitted; struct usb_anchor rx_submitted; struct sk_buff *remain_skb; int rx_remain_len; -- cgit v1.2.3 From f984d94c500c79048b33ab14923dfcec336d9968 Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 6 Apr 2010 15:28:19 +0530 Subject: ath9k_htc: Fix HTC layer memleak Messages that are generated by the HTC layer don't have any TX callback endpoints assigned to them. Consequently, the allocated SKBs are never freed. Fix this issue by handling this case in the HTC layer itself. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_hst.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 30f608bfc567..24d7b886fe23 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -326,11 +326,13 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, if (htc_handle->htc_flags & HTC_OP_CONFIG_PIPE_CREDITS) { complete(&htc_handle->cmd_wait); htc_handle->htc_flags &= ~HTC_OP_CONFIG_PIPE_CREDITS; + goto ret; } if (htc_handle->htc_flags & HTC_OP_START_WAIT) { complete(&htc_handle->cmd_wait); htc_handle->htc_flags &= ~HTC_OP_START_WAIT; + goto ret; } if (skb) { @@ -343,6 +345,11 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, htc_hdr->endpoint_id, txok); } } + + return; +ret: + /* HTC-generated packets are freed here. */ + dev_kfree_skb_any(skb); } /* -- cgit v1.2.3 From 2eb46d9bda44b3f85727fee6865d9b25725e6bf9 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Wed, 7 Apr 2010 01:33:33 -0400 Subject: ath9k: simplify AR9220 fixup code for AR_AN_TOP2 register Don't modify ah->iniModes, it's supposed to be constant. Instead, apply the fixup when the data is written to the registers. Change ath9k_hw_init_eeprom_fix() to only determine whether the fixup is needed. This allows similteneous support for AR9220 cards that need AR_AN_TOP2 fixup (such as Ubiquiti SR71-12) and those that don't need it (D-Link DWA-552 rev A2). Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 76 ++++++------------------------------- drivers/net/wireless/ath/ath9k/hw.h | 1 + 2 files changed, 13 insertions(+), 64 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 88f8bfdbded4..3b9f4c1f8d4e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -27,9 +27,6 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan); -static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, - struct ar5416_eeprom_def *pEepData, - u32 reg, u32 value); MODULE_AUTHOR("Atheros Communications"); MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); @@ -844,24 +841,17 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah) { - u32 i, j; - - if (ah->hw_version.devid == AR9280_DEVID_PCI) { - - /* EEPROM Fixup */ - for (i = 0; i < ah->iniModes.ia_rows; i++) { - u32 reg = INI_RA(&ah->iniModes, i, 0); + struct base_eep_header *pBase = &(ah->eeprom.def.baseEepHeader); + struct ath_common *common = ath9k_hw_common(ah); - for (j = 1; j < ah->iniModes.ia_columns; j++) { - u32 val = INI_RA(&ah->iniModes, i, j); + ah->need_an_top2_fixup = (ah->hw_version.devid == AR9280_DEVID_PCI) && + (ah->eep_map != EEP_MAP_4KBITS) && + ((pBase->version & 0xff) > 0x0a) && + (pBase->pwdclkind == 0); - INI_RA(&ah->iniModes, i, j) = - ath9k_hw_ini_fixup(ah, - &ah->eeprom.def, - reg, val); - } - } - } + if (ah->need_an_top2_fixup) + ath_print(common, ATH_DBG_EEPROM, + "needs fixup for AR_AN_TOP2 register\n"); } int ath9k_hw_init(struct ath_hw *ah) @@ -1305,51 +1295,6 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, } } -static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah, - struct ar5416_eeprom_def *pEepData, - u32 reg, u32 value) -{ - struct base_eep_header *pBase = &(pEepData->baseEepHeader); - struct ath_common *common = ath9k_hw_common(ah); - - switch (ah->hw_version.devid) { - case AR9280_DEVID_PCI: - if (reg == 0x7894) { - ath_print(common, ATH_DBG_EEPROM, - "ini VAL: %x EEPROM: %x\n", value, - (pBase->version & 0xff)); - - if ((pBase->version & 0xff) > 0x0a) { - ath_print(common, ATH_DBG_EEPROM, - "PWDCLKIND: %d\n", - pBase->pwdclkind); - value &= ~AR_AN_TOP2_PWDCLKIND; - value |= AR_AN_TOP2_PWDCLKIND & - (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S); - } else { - ath_print(common, ATH_DBG_EEPROM, - "PWDCLKIND Earlier Rev\n"); - } - - ath_print(common, ATH_DBG_EEPROM, - "final ini VAL: %x\n", value); - } - break; - } - - return value; -} - -static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, - struct ar5416_eeprom_def *pEepData, - u32 reg, u32 value) -{ - if (ah->eep_map == EEP_MAP_4KBITS) - return value; - else - return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value); -} - static void ath9k_olc_init(struct ath_hw *ah) { u32 i; @@ -1455,6 +1400,9 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, u32 reg = INI_RA(&ah->iniModes, i, 0); u32 val = INI_RA(&ah->iniModes, i, modesIndex); + if (reg == AR_AN_TOP2 && ah->need_an_top2_fixup) + val &= ~AR_AN_TOP2_PWDCLKIND; + REG_WRITE(ah, reg, val); if (reg >= 0x7800 && reg < 0x78a0 diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index b02a97c72c64..f4821cf33b87 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -459,6 +459,7 @@ struct ath_hw { bool sw_mgmt_crypto; bool is_pciexpress; + bool need_an_top2_fixup; u16 tx_trig_level; u16 rfsilent; u32 rfkill_gpio; -- cgit v1.2.3 From 403820edc4ba1f2fb2514c022f2662c498ce0d11 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Wed, 7 Apr 2010 09:06:34 +0200 Subject: rt2x00: use rt2800_config_channel_rt3x for rt2872 rt2872 needs the same rf register setup as rt3070 and rt3090, hence use rt2800_config_channel_rt3x instead of rt2800_config_channel_rt2x. This change allows me to actually switch channels and hence scan all configured channels on the RT305x SoC platform (which uses a rt2872) here. Signed-off-by: Helmut Schaa Acked-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Tested-by: Luis Correia Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 68d0cfee3f20..ec3ec786f350 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -827,7 +827,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, u8 bbp; if ((rt2x00_rt(rt2x00dev, RT3070) || - rt2x00_rt(rt2x00dev, RT3090)) && + rt2x00_rt(rt2x00dev, RT3090) || + rt2x00_rt(rt2x00dev, RT2872)) && (rt2x00_rf(rt2x00dev, RF2020) || rt2x00_rf(rt2x00dev, RF3020) || rt2x00_rf(rt2x00dev, RF3021) || -- cgit v1.2.3 From 1968cc78d91c79857089713bf3f3cceb5e9c63ae Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 7 Apr 2010 23:55:56 -0400 Subject: ath5k: correct channel setting for 2.5 mhz spacing These channels aren't selectable anyway, but our calculations for 2.5 mhz frequencies are incorrect. The value is supposed to be: (frequency - reference) * (10/25) i.e., divide by 2.5, but we were instead doing: (10 * frequency - reference) / 25. Additionally, the check for (frequency % 5 == 2) had an extra subtraction that wasn't in madwifi HAL. Signed-off-by: Bob Copeland Acked-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/phy.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index b6704c93f808..fcfc32d4da20 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -979,7 +979,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, return -EINVAL; data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); - } else if ((c - (c % 5)) != 2 || c > 5435) { + } else if ((c % 5) != 2 || c > 5435) { if (!(c % 20) && c >= 5120) { data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); data2 = ath5k_hw_bitswap(3, 2); @@ -992,7 +992,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, } else return -EINVAL; } else { - data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); + data0 = ath5k_hw_bitswap((10 * (c - 2 - 4800)) / 25 + 1, 8); data2 = ath5k_hw_bitswap(0, 2); } @@ -1020,7 +1020,7 @@ static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, data0 = ath5k_hw_bitswap((c - 2272), 8); data2 = 0; /* ? 5GHz ? */ - } else if ((c - (c % 5)) != 2 || c > 5435) { + } else if ((c % 5) != 2 || c > 5435) { if (!(c % 20) && c < 5120) data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); else if (!(c % 10)) @@ -1031,7 +1031,7 @@ static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, return -EINVAL; data2 = ath5k_hw_bitswap(1, 2); } else { - data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); + data0 = ath5k_hw_bitswap((10 * (c - 2 - 4800)) / 25 + 1, 8); data2 = ath5k_hw_bitswap(0, 2); } -- cgit v1.2.3 From 6b5d117eddc09cd976ad8030d715f4350f598a22 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 7 Apr 2010 23:55:57 -0400 Subject: ath5k: clean up queue manipulation Review spotted a couple of strange invocations to ieee80211_wake_queues that could potentially cause problems: - queues are awakened in the calibration tasklet before phy calibration, and then again after calibration - queues are awakened inside reset when we're trying to drain the ath5k transmit queues, and again after reset is completed (in callers to ath5k_reset_wake). In both cases the first wake is unnecessary, so remove it. Signed-off-by: Bob Copeland Acked-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index c085a06f1e05..38c41e3c7988 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1636,7 +1636,6 @@ ath5k_txq_cleanup(struct ath5k_softc *sc) sc->txqs[i].link); } } - ieee80211_wake_queues(sc->hw); /* XXX move to callers */ for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) if (sc->txqs[i].setup) @@ -2775,7 +2774,7 @@ ath5k_tasklet_calibrate(unsigned long data) * to load new gain values. */ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n"); - ath5k_reset_wake(sc); + ath5k_reset(sc, sc->curchan); } if (ath5k_hw_phy_calibrate(ah, sc->curchan)) ATH5K_ERR(sc, "calibration of channel %u failed\n", -- cgit v1.2.3 From a05988bbbef5ac2391fe696646f0b80708f33f2e Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 7 Apr 2010 23:55:58 -0400 Subject: ath5k: fix race condition in tx desc processing As pointed out by Benoit Papillault, there is a potential race condition between the host and the hardware in reading the next link in the transmit descriptor list: cpu0 hw tx for buf completed raise tx_ok interrupt process buf buf->ds_link = 0 read buf->ds_link This change checks txdp before processing a descriptor (if there are any subsequent descriptors) to see if hardware moved on. We'll then process this descriptor on the next tasklet. Signed-off-by: Bob Copeland Acked-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 38c41e3c7988..f7f57c1cca7d 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2083,6 +2083,17 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) list_for_each_entry_safe(bf, bf0, &txq->q, list) { ds = bf->desc; + /* + * It's possible that the hardware can say the buffer is + * completed when it hasn't yet loaded the ds_link from + * host memory and moved on. If there are more TX + * descriptors in the queue, wait for TXDP to change + * before processing this one. + */ + if (ath5k_hw_get_txdp(sc->ah, txq->qnum) == bf->daddr && + !list_is_last(&bf->list, &txq->q)) + break; + ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); if (unlikely(ret == -EINPROGRESS)) break; -- cgit v1.2.3 From 4f59fce9e099fb6ba3c8361e5094163a3efce5be Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 7 Apr 2010 23:55:59 -0400 Subject: ath5k: add bounds check to pdadc table We check the bounds on pdadc once when correcting for negative curves but not when we later copy values from from the pdadc_tmp array, leading to a potential overrun. Although we shouldn't hit this case in practice, let's be consistent. Reported-by: Dan Carpenter Signed-off-by: Bob Copeland Acked-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index fcfc32d4da20..4a49dbb17352 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -2557,7 +2557,7 @@ ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah, max_idx = (pdadc_n < table_size) ? pdadc_n : table_size; /* Fill pdadc_out table */ - while (pdadc_0 < max_idx) + while (pdadc_0 < max_idx && pdadc_i < 128) pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++]; /* Need to extrapolate above this pdgain? */ -- cgit v1.2.3 From f74cb0f7b1d8d6e4c11c6679a7d012be641225e3 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 8 Apr 2010 11:50:47 -0400 Subject: mac80211_hwsim: add sw_scan sw_scan_complete Simple pre-scan and scan complete callbacks, this at least shows to me that mac80211 will issue two scans at the same time on the same wiphy. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 45 +++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 6ea77e95277b..ec8b08291790 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -290,7 +290,8 @@ struct mac80211_hwsim_data { struct ieee80211_channel *channel; unsigned long beacon_int; /* in jiffies unit */ unsigned int rx_filter; - bool started, idle; + bool started, idle, scanning; + struct mutex mutex; struct timer_list beacon_timer; enum ps_mode { PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL @@ -956,9 +957,9 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, hsd->hw = hw; INIT_DELAYED_WORK(&hsd->w, hw_scan_done); - printk(KERN_DEBUG "hwsim scan request\n"); + printk(KERN_DEBUG "hwsim hw_scan request\n"); for (i = 0; i < req->n_channels; i++) - printk(KERN_DEBUG "hwsim scan freq %d\n", + printk(KERN_DEBUG "hwsim hw_scan freq %d\n", req->channels[i]->center_freq); ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ); @@ -966,6 +967,36 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, return 0; } +static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw) +{ + struct mac80211_hwsim_data *hwsim = hw->priv; + + mutex_lock(&hwsim->mutex); + + if (hwsim->scanning) { + printk(KERN_DEBUG "two hwsim sw_scans detected!\n"); + goto out; + } + + printk(KERN_DEBUG "hwsim sw_scan request, prepping stuff\n"); + hwsim->scanning = true; + +out: + mutex_unlock(&hwsim->mutex); +} + +static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw) +{ + struct mac80211_hwsim_data *hwsim = hw->priv; + + mutex_lock(&hwsim->mutex); + + printk(KERN_DEBUG "hwsim sw_scan_complete\n"); + hwsim->scanning = true; + + mutex_unlock(&hwsim->mutex); +} + static struct ieee80211_ops mac80211_hwsim_ops = { .tx = mac80211_hwsim_tx, @@ -983,6 +1014,8 @@ static struct ieee80211_ops mac80211_hwsim_ops = .conf_tx = mac80211_hwsim_conf_tx, CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) .ampdu_action = mac80211_hwsim_ampdu_action, + .sw_scan_start = mac80211_hwsim_sw_scan, + .sw_scan_complete = mac80211_hwsim_sw_scan_complete, .flush = mac80211_hwsim_flush, }; @@ -1178,8 +1211,11 @@ static int __init init_mac80211_hwsim(void) if (radios < 1 || radios > 100) return -EINVAL; - if (fake_hw_scan) + if (fake_hw_scan) { mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; + mac80211_hwsim_ops.sw_scan_start = NULL; + mac80211_hwsim_ops.sw_scan_complete = NULL; + } spin_lock_init(&hwsim_radio_lock); INIT_LIST_HEAD(&hwsim_radios); @@ -1284,6 +1320,7 @@ static int __init init_mac80211_hwsim(void) } /* By default all radios are belonging to the first group */ data->group = 1; + mutex_init(&data->mutex); /* Work to be done prior to ieee80211_register_hw() */ switch (regtest) { -- cgit v1.2.3 From ace5d5de6bbaff00d3b5dd7ea8f160b570fdb726 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 8 Apr 2010 16:34:49 -0400 Subject: ath5k: fixup some merge damage for AR5211 IQ calibration Resolution of a merge conflict upstream accidentally removed a hunk of "ath5k: IQ calibration for AR5211 is slightly different", so restore it. Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/phy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 4a49dbb17352..60873a4f6171 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1388,7 +1388,10 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, i_coff = (-iq_corr) / i_coffd; i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ - q_coff = (i_pwr / q_coffd) - 128; + if (ah->ah_version == AR5K_AR5211) + q_coff = (i_pwr / q_coffd) - 64; + else + q_coff = (i_pwr / q_coffd) - 128; q_coff = clamp(q_coff, -16, 15); /* signed 5 bit */ ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, -- cgit v1.2.3 From bd9dc49cd565aeb20d4f6eb2f6af4c16acce2ef5 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 9 Apr 2010 11:07:26 +0300 Subject: wl1271: Fix memory leaks on driver initialization This patch fixes some memory leaks occurring during driver init/de-init. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 5c32d8d72361..4e9754056d45 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1093,6 +1093,14 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, wl->tx_blocks_freed[i] = 0; wl1271_debugfs_reset(wl); + + kfree(wl->fw_status); + wl->fw_status = NULL; + kfree(wl->tx_res_if); + wl->tx_res_if = NULL; + kfree(wl->target_mem_map); + wl->target_mem_map = NULL; + mutex_unlock(&wl->mutex); } @@ -2387,7 +2395,6 @@ int wl1271_free_hw(struct wl1271 *wl) wl1271_debugfs_exit(wl); - kfree(wl->target_mem_map); vfree(wl->fw); wl->fw = NULL; kfree(wl->nvs); -- cgit v1.2.3 From 2c10bb9cb3f9cecb71bd2cbb771778136433ebe2 Mon Sep 17 00:00:00 2001 From: Saravanan Dhanabal Date: Fri, 9 Apr 2010 11:07:27 +0300 Subject: wl1271: Fix mac80211 configuration requests during WL1271_STATE_OFF mac80211 sends configuration requests even if the wl1271 interface state is WL1271_STATE_OFF. This creates warnings from mac80211. This patch leaves the configuration functions, if the interface is going down. Signed-off-by: Saravanan Dhanabal Reviewed-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 4e9754056d45..2eb7b99ff276 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1223,6 +1223,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&wl->mutex); + if (unlikely(wl->state == WL1271_STATE_OFF)) + goto out; + ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out; @@ -1324,8 +1327,12 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, struct dev_addr_list *mc_list) { struct wl1271_filter_params *fp; + struct wl1271 *wl = hw->priv; int i; + if (unlikely(wl->state == WL1271_STATE_OFF)) + return 0; + fp = kzalloc(sizeof(*fp), GFP_ATOMIC); if (!fp) { wl1271_error("Out of memory setting filters."); @@ -1372,15 +1379,16 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF) + *total &= WL1271_SUPPORTED_FILTERS; + changed &= WL1271_SUPPORTED_FILTERS; + + if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out; - *total &= WL1271_SUPPORTED_FILTERS; - changed &= WL1271_SUPPORTED_FILTERS; if (*total & FIF_ALLMULTI) ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); -- cgit v1.2.3 From aecb0565e3e331d4dd23b4d35180519532015f22 Mon Sep 17 00:00:00 2001 From: Saravanan Dhanabal Date: Fri, 9 Apr 2010 11:07:28 +0300 Subject: wl1271: Fix mac80211 RTS threshold requests during WL1271_STATE_OFF mac80211 sends RTS threshold configuration request even if the wl1271 interface state is WL1271_STATE_OFF. This leads to failures during pm tests. This patch leaves the configuration function, if the interface is going down. Signed-off-by: Saravanan Dhanabal Reviewed-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 2eb7b99ff276..4adc5162e7e5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1582,10 +1582,13 @@ out: static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) { struct wl1271 *wl = hw->priv; - int ret; + int ret = 0; mutex_lock(&wl->mutex); + if (unlikely(wl->state == WL1271_STATE_OFF)) + goto out; + ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out; -- cgit v1.2.3 From e19728181ca7187fa0ecb7076ce681311cf785e7 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 9 Apr 2010 11:07:29 +0300 Subject: wl1271: Go to ELP in idle Allow the wl1271 go to ELP mode also in idle. This will reduce current consumption remarkably in idle mode (~12mA -> ~0.2mA) Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 1 + drivers/net/wireless/wl12xx/wl1271_main.c | 4 +++- drivers/net/wireless/wl12xx/wl1271_ps.c | 6 ++++-- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index a29969efc861..789460074670 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -374,6 +374,7 @@ struct wl1271 { #define WL1271_FLAG_PSM_REQUESTED (8) #define WL1271_FLAG_IRQ_PENDING (9) #define WL1271_FLAG_IRQ_RUNNING (10) +#define WL1271_FLAG_IDLE (11) unsigned long flags; struct wl1271_partition_set part; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 4adc5162e7e5..551714164ff5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1272,7 +1272,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wl1271_acx_keep_alive_config( wl, CMD_TEMPL_KLV_IDX_NULL_DATA, ACX_KEEP_ALIVE_TPL_INVALID); - } + set_bit(WL1271_FLAG_IDLE, &wl->flags); + } else + clear_bit(WL1271_FLAG_IDLE, &wl->flags); } if (conf->flags & IEEE80211_CONF_PS && diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index 5a04482b9353..a5e60e0403e5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c @@ -40,7 +40,8 @@ void wl1271_elp_work(struct work_struct *work) mutex_lock(&wl->mutex); if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || - !test_bit(WL1271_FLAG_PSM, &wl->flags)) + (!test_bit(WL1271_FLAG_PSM, &wl->flags) && + !test_bit(WL1271_FLAG_IDLE, &wl->flags))) goto out; wl1271_debug(DEBUG_PSM, "chip to elp"); @@ -56,7 +57,8 @@ out: /* Routines to toggle sleep mode while in ELP */ void wl1271_ps_elp_sleep(struct wl1271 *wl) { - if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { + if (test_bit(WL1271_FLAG_PSM, &wl->flags) || + test_bit(WL1271_FLAG_IDLE, &wl->flags)) { cancel_delayed_work(&wl->elp_work); ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, msecs_to_jiffies(ELP_ENTRY_DELAY)); -- cgit v1.2.3 From 00236aedf1d2c49a18ae9ea00698d97705ff7289 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 9 Apr 2010 11:07:30 +0300 Subject: wl1271: Add support for connection quality monitoring This patch will add support for connection quality monitoring by configuring rssi triggers to the firmware, and enabling the firmware rssi trigger functionality. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 3 + drivers/net/wireless/wl12xx/wl1271_acx.c | 71 ++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1271_acx.h | 56 +++++++++++++++- drivers/net/wireless/wl12xx/wl1271_boot.c | 3 +- drivers/net/wireless/wl12xx/wl1271_conf.h | 103 +++++++++++------------------ drivers/net/wireless/wl12xx/wl1271_event.c | 24 +++++++ drivers/net/wireless/wl12xx/wl1271_event.h | 8 +++ drivers/net/wireless/wl12xx/wl1271_init.c | 5 ++ drivers/net/wireless/wl12xx/wl1271_main.c | 52 ++++++--------- 9 files changed, 228 insertions(+), 97 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 789460074670..75887e74205b 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -473,6 +473,9 @@ struct wl1271 { /* in dBm */ int power_level; + int rssi_thold; + int last_rssi_event; + struct wl1271_stats stats; struct wl1271_debugfs debugfs; diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 621c94691e7e..1a6b2ec1db58 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -1165,6 +1165,7 @@ out: kfree(acx); return ret; } + int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) { struct wl1271_acx_keep_alive_config *acx = NULL; @@ -1194,3 +1195,73 @@ out: kfree(acx); return ret; } + +int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, + s16 thold, u8 hyst) +{ + struct wl1271_acx_rssi_snr_trigger *acx = NULL; + int ret = 0; + + wl1271_debug(DEBUG_ACX, "acx rssi snr trigger"); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) { + ret = -ENOMEM; + goto out; + } + + wl->last_rssi_event = -1; + + acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing); + acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON; + acx->type = WL1271_ACX_TRIG_TYPE_EDGE; + if (enable) + acx->enable = WL1271_ACX_TRIG_ENABLE; + else + acx->enable = WL1271_ACX_TRIG_DISABLE; + + acx->index = WL1271_ACX_TRIG_IDX_RSSI; + acx->dir = WL1271_ACX_TRIG_DIR_BIDIR; + acx->threshold = cpu_to_le16(thold); + acx->hysteresis = hyst; + + ret = wl1271_cmd_configure(wl, ACX_RSSI_SNR_TRIGGER, acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("acx rssi snr trigger setting failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} + +int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl) +{ + struct wl1271_acx_rssi_snr_avg_weights *acx = NULL; + struct conf_roam_trigger_settings *c = &wl->conf.roam_trigger; + int ret = 0; + + wl1271_debug(DEBUG_ACX, "acx rssi snr avg weights"); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) { + ret = -ENOMEM; + goto out; + } + + acx->rssi_beacon = c->avg_weight_rssi_beacon; + acx->rssi_data = c->avg_weight_rssi_data; + acx->snr_beacon = c->avg_weight_snr_beacon; + acx->snr_data = c->avg_weight_snr_data; + + ret = wl1271_cmd_configure(wl, ACX_RSSI_SNR_WEIGHTS, acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("acx rssi snr trigger weights failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 15cc56192de9..420e7e2fc021 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -942,6 +942,57 @@ struct wl1271_acx_keep_alive_config { u8 padding; } __attribute__ ((packed)); +enum { + WL1271_ACX_TRIG_TYPE_LEVEL = 0, + WL1271_ACX_TRIG_TYPE_EDGE, +}; + +enum { + WL1271_ACX_TRIG_DIR_LOW = 0, + WL1271_ACX_TRIG_DIR_HIGH, + WL1271_ACX_TRIG_DIR_BIDIR, +}; + +enum { + WL1271_ACX_TRIG_ENABLE = 1, + WL1271_ACX_TRIG_DISABLE, +}; + +enum { + WL1271_ACX_TRIG_METRIC_RSSI_BEACON = 0, + WL1271_ACX_TRIG_METRIC_RSSI_DATA, + WL1271_ACX_TRIG_METRIC_SNR_BEACON, + WL1271_ACX_TRIG_METRIC_SNR_DATA, +}; + +enum { + WL1271_ACX_TRIG_IDX_RSSI = 0, + WL1271_ACX_TRIG_COUNT = 8, +}; + +struct wl1271_acx_rssi_snr_trigger { + struct acx_header header; + + __le16 threshold; + __le16 pacing; /* 0 - 60000 ms */ + u8 metric; + u8 type; + u8 dir; + u8 hysteresis; + u8 index; + u8 enable; + u8 padding[2]; +}; + +struct wl1271_acx_rssi_snr_avg_weights { + struct acx_header header; + + u8 rssi_beacon; + u8 rssi_data; + u8 snr_beacon; + u8 snr_data; +}; + enum { ACX_WAKE_UP_CONDITIONS = 0x0002, ACX_MEM_CFG = 0x0003, @@ -990,7 +1041,7 @@ enum { ACX_FRAG_CFG = 0x004F, ACX_BET_ENABLE = 0x0050, ACX_RSSI_SNR_TRIGGER = 0x0051, - ACX_RSSI_SNR_WEIGHTS = 0x0051, + ACX_RSSI_SNR_WEIGHTS = 0x0052, ACX_KEEP_ALIVE_MODE = 0x0053, ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, @@ -1060,5 +1111,8 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, int wl1271_acx_pm_config(struct wl1271 *wl); int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); +int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, + s16 thold, u8 hyst); +int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl); #endif /* __WL1271_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 7acef88df1fe..f16d15bd5643 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -412,7 +412,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) SCAN_COMPLETE_EVENT_ID | PS_REPORT_EVENT_ID | JOIN_EVENT_COMPLETE_ID | - DISCONNECT_EVENT_COMPLETE_ID; + DISCONNECT_EVENT_COMPLETE_ID | + RSSI_SNR_TRIGGER_0_EVENT_ID; ret = wl1271_event_unmask(wl); if (ret < 0) { diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index d76ae03762a3..c44307c4bcf8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -756,65 +756,6 @@ enum { CONF_TRIG_EVENT_DIR_BIDIR }; - -struct conf_sig_trigger { - /* - * The RSSI / SNR threshold value. - * - * FIXME: what is the range? - */ - s16 threshold; - - /* - * Minimum delay between two trigger events for this trigger in ms. - * - * Range: 0 - 60000 - */ - u16 pacing; - - /* - * The measurement data source for this trigger. - * - * Range: CONF_TRIG_METRIC_* - */ - u8 metric; - - /* - * The trigger type of this trigger. - * - * Range: CONF_TRIG_EVENT_TYPE_* - */ - u8 type; - - /* - * The direction of the trigger. - * - * Range: CONF_TRIG_EVENT_DIR_* - */ - u8 direction; - - /* - * Hysteresis range of the trigger around the threshold (in dB) - * - * Range: u8 - */ - u8 hysteresis; - - /* - * Index of the trigger rule. - * - * Range: 0 - CONF_MAX_RSSI_SNR_TRIGGERS-1 - */ - u8 index; - - /* - * Enable / disable this rule (to use for clearing rules.) - * - * Range: 1 - Enabled, 2 - Not enabled - */ - u8 enable; -}; - struct conf_sig_weights { /* @@ -932,12 +873,6 @@ struct conf_conn_settings { */ u8 ps_poll_threshold; - /* - * Configuration of signal (rssi/snr) triggers. - */ - u8 sig_trigger_count; - struct conf_sig_trigger sig_trigger[CONF_MAX_RSSI_SNR_TRIGGERS]; - /* * Configuration of signal average weights. */ @@ -1045,6 +980,43 @@ struct conf_pm_config_settings { bool host_fast_wakeup_support; }; +struct conf_roam_trigger_settings { + /* + * The minimum interval between two trigger events. + * + * Range: 0 - 60000 ms + */ + u16 trigger_pacing; + + /* + * The weight for rssi/beacon average calculation + * + * Range: 0 - 255 + */ + u8 avg_weight_rssi_beacon; + + /* + * The weight for rssi/data frame average calculation + * + * Range: 0 - 255 + */ + u8 avg_weight_rssi_data; + + /* + * The weight for snr/beacon average calculation + * + * Range: 0 - 255 + */ + u8 avg_weight_snr_beacon; + + /* + * The weight for snr/data frame average calculation + * + * Range: 0 - 255 + */ + u8 avg_weight_snr_data; +}; + struct conf_drv_settings { struct conf_sg_settings sg; struct conf_rx_settings rx; @@ -1053,6 +1025,7 @@ struct conf_drv_settings { struct conf_init_settings init; struct conf_itrim_settings itrim; struct conf_pm_config_settings pm_config; + struct conf_roam_trigger_settings roam_trigger; }; #endif diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index daacf176cf09..cf37aa6eb137 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -125,6 +125,24 @@ static int wl1271_event_ps_report(struct wl1271 *wl, return ret; } +static void wl1271_event_rssi_trigger(struct wl1271 *wl, + struct event_mailbox *mbox) +{ + enum nl80211_cqm_rssi_threshold_event event; + s8 metric = mbox->rssi_snr_trigger_metric[0]; + + wl1271_debug(DEBUG_EVENT, "RSSI trigger metric: %d", metric); + + if (metric <= wl->rssi_thold) + event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; + else + event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; + + if (event != wl->last_rssi_event) + ieee80211_cqm_rssi_notify(wl->vif, event, GFP_KERNEL); + wl->last_rssi_event = event; +} + static void wl1271_event_mbox_dump(struct event_mailbox *mbox) { wl1271_debug(DEBUG_EVENT, "MBOX DUMP:"); @@ -173,6 +191,12 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) return ret; } + if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { + wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); + if (wl->vif) + wl1271_event_rssi_trigger(wl, mbox); + } + if (wl->vif && beacon_loss) ieee80211_connection_loss(wl->vif); diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h index 278f9206aa56..58371008f270 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/drivers/net/wireless/wl12xx/wl1271_event.h @@ -38,6 +38,14 @@ */ enum { + RSSI_SNR_TRIGGER_0_EVENT_ID = BIT(0), + RSSI_SNR_TRIGGER_1_EVENT_ID = BIT(1), + RSSI_SNR_TRIGGER_2_EVENT_ID = BIT(2), + RSSI_SNR_TRIGGER_3_EVENT_ID = BIT(3), + RSSI_SNR_TRIGGER_4_EVENT_ID = BIT(4), + RSSI_SNR_TRIGGER_5_EVENT_ID = BIT(5), + RSSI_SNR_TRIGGER_6_EVENT_ID = BIT(6), + RSSI_SNR_TRIGGER_7_EVENT_ID = BIT(7), MEASUREMENT_START_EVENT_ID = BIT(8), MEASUREMENT_COMPLETE_EVENT_ID = BIT(9), SCAN_COMPLETE_EVENT_ID = BIT(10), diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 9ab336829044..b880382cf15d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -352,6 +352,11 @@ int wl1271_hw_init(struct wl1271 *wl) if (ret < 0) goto out_free_memmap; + /* Configure rssi/snr averaging weights */ + ret = wl1271_acx_rssi_snr_avg_weights(wl); + if (ret < 0) + goto out_free_memmap; + return 0; out_free_memmap: diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 551714164ff5..283d5dade1ae 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -234,35 +234,6 @@ static struct conf_drv_settings default_conf = { .broadcast_timeout = 20000, .rx_broadcast_in_ps = 1, .ps_poll_threshold = 20, - .sig_trigger_count = 2, - .sig_trigger = { - [0] = { - .threshold = -75, - .pacing = 500, - .metric = CONF_TRIG_METRIC_RSSI_BEACON, - .type = CONF_TRIG_EVENT_TYPE_EDGE, - .direction = CONF_TRIG_EVENT_DIR_LOW, - .hysteresis = 2, - .index = 0, - .enable = 1 - }, - [1] = { - .threshold = -75, - .pacing = 500, - .metric = CONF_TRIG_METRIC_RSSI_BEACON, - .type = CONF_TRIG_EVENT_TYPE_EDGE, - .direction = CONF_TRIG_EVENT_DIR_HIGH, - .hysteresis = 2, - .index = 1, - .enable = 1 - } - }, - .sig_weights = { - .rssi_bcn_avg_weight = 10, - .rssi_pkt_avg_weight = 10, - .snr_bcn_avg_weight = 10, - .snr_pkt_avg_weight = 10 - }, .bet_enable = CONF_BET_MODE_ENABLE, .bet_max_consecutive = 10, .psm_entry_retries = 3, @@ -281,6 +252,14 @@ static struct conf_drv_settings default_conf = { .pm_config = { .host_clk_settling_time = 5000, .host_fast_wakeup_support = false + }, + .roam_trigger = { + /* FIXME: due to firmware bug, must use value 1 for now */ + .trigger_pacing = 1, + .avg_weight_rssi_beacon = 20, + .avg_weight_rssi_data = 10, + .avg_weight_snr_beacon = 20, + .avg_weight_snr_data = 10 } }; @@ -1703,6 +1682,18 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, do_join = true; } + if (changed & BSS_CHANGED_CQM) { + bool enable = false; + if (bss_conf->cqm_rssi_thold) + enable = true; + ret = wl1271_acx_rssi_snr_trigger(wl, enable, + bss_conf->cqm_rssi_thold, + bss_conf->cqm_rssi_hyst); + if (ret < 0) + goto out; + wl->rssi_thold = bss_conf->cqm_rssi_thold; + } + if ((changed & BSS_CHANGED_BSSID) && /* * Now we know the correct bssid, so we send a new join command @@ -2283,7 +2274,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl) IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_UAPSD | IEEE80211_HW_HAS_RATE_CONTROL | - IEEE80211_HW_CONNECTION_MONITOR; + IEEE80211_HW_CONNECTION_MONITOR | + IEEE80211_HW_SUPPORTS_CQM_RSSI; wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); -- cgit v1.2.3 From 678b385d07835c6c21371c12eaaa3fba4de05168 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 26 Mar 2010 12:54:37 -0700 Subject: iwlwifi: default max event log size Size of event log is determined by uCode which is different per NICs. Set the maximum event log size per device to better match uCode configuration. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-3945.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 7 +++++++ drivers/net/wireless/iwlwifi/iwl-6000.c | 7 +++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 15 ++++++--------- drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 15 ++++++--------- 8 files changed, 32 insertions(+), 18 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index b941b3e95697..9a0191a5ea35 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -253,6 +253,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 128, }; struct iwl_cfg iwl1000_bg_cfg = { @@ -282,6 +283,7 @@ struct iwl_cfg iwl1000_bg_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 128, }; MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index f88f75dfd96e..7424586a5edb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2770,6 +2770,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { .broken_powersave = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; static struct iwl_cfg iwl3945_abg_cfg = { @@ -2789,6 +2790,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .broken_powersave = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 6edae9b83bb7..0164c3f2109d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2250,6 +2250,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .temperature_kelvin = true, .off_channel_workaround = true, + .max_event_log_size = 512, }; /* Module firmware */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index ecc302e4c205..e967cfcac224 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -423,6 +423,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; struct iwl_cfg iwl5100_bgn_cfg = { @@ -450,6 +451,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; struct iwl_cfg iwl5100_abg_cfg = { @@ -475,6 +477,7 @@ struct iwl_cfg iwl5100_abg_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; struct iwl_cfg iwl5100_agn_cfg = { @@ -502,6 +505,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; struct iwl_cfg iwl5350_agn_cfg = { @@ -529,6 +533,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; struct iwl_cfg iwl5150_agn_cfg = { @@ -556,6 +561,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; struct iwl_cfg iwl5150_abg_cfg = { @@ -581,6 +587,7 @@ struct iwl_cfg iwl5150_abg_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 7473518e7e0a..dd03384432f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -394,6 +394,7 @@ struct iwl_cfg iwl6000i_g2_2agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 1024, }; struct iwl_cfg iwl6000i_2agn_cfg = { @@ -427,6 +428,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 1024, }; struct iwl_cfg iwl6000i_2abg_cfg = { @@ -459,6 +461,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 1024, }; struct iwl_cfg iwl6000i_2bg_cfg = { @@ -491,6 +494,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 1024, }; struct iwl_cfg iwl6050_2agn_cfg = { @@ -524,6 +528,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1500, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 1024, }; struct iwl_cfg iwl6050_2abg_cfg = { @@ -556,6 +561,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1500, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 1024, }; struct iwl_cfg iwl6000_3agn_cfg = { @@ -589,6 +595,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 1024, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4f0cb803f732..978604f8ae92 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1990,9 +1990,6 @@ static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, return pos; } -/* For sanity check only. Actual size is determined by uCode, typ. 512 */ -#define MAX_EVENT_LOG_SIZE (512) - #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, @@ -2025,16 +2022,16 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); - if (capacity > MAX_EVENT_LOG_SIZE) { + if (capacity > priv->cfg->max_event_log_size) { IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", - capacity, MAX_EVENT_LOG_SIZE); - capacity = MAX_EVENT_LOG_SIZE; + capacity, priv->cfg->max_event_log_size); + capacity = priv->cfg->max_event_log_size; } - if (next_entry > MAX_EVENT_LOG_SIZE) { + if (next_entry > priv->cfg->max_event_log_size) { IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", - next_entry, MAX_EVENT_LOG_SIZE); - next_entry = MAX_EVENT_LOG_SIZE; + next_entry, priv->cfg->max_event_log_size); + next_entry = priv->cfg->max_event_log_size; } size = num_wraps ? capacity : next_entry; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 10f95724536f..d89755f5031a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -307,6 +307,7 @@ struct iwl_cfg { u32 monitor_recover_period; bool temperature_kelvin; bool off_channel_workaround; + u32 max_event_log_size; }; /*************************** diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c9188b9c5651..24e969440b31 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1603,9 +1603,6 @@ static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, return pos; } -/* For sanity check only. Actual size is determined by uCode, typ. 512 */ -#define IWL3945_MAX_EVENT_LOG_SIZE (512) - #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, @@ -1632,16 +1629,16 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); - if (capacity > IWL3945_MAX_EVENT_LOG_SIZE) { + if (capacity > priv->cfg->max_event_log_size) { IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", - capacity, IWL3945_MAX_EVENT_LOG_SIZE); - capacity = IWL3945_MAX_EVENT_LOG_SIZE; + capacity, priv->cfg->max_event_log_size); + capacity = priv->cfg->max_event_log_size; } - if (next_entry > IWL3945_MAX_EVENT_LOG_SIZE) { + if (next_entry > priv->cfg->max_event_log_size) { IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", - next_entry, IWL3945_MAX_EVENT_LOG_SIZE); - next_entry = IWL3945_MAX_EVENT_LOG_SIZE; + next_entry, priv->cfg->max_event_log_size); + next_entry = priv->cfg->max_event_log_size; } size = num_wraps ? capacity : next_entry; -- cgit v1.2.3 From 335348b1702cf78c9e79987a3d66e85a05c98b5c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 Mar 2010 10:11:46 -0700 Subject: iwlwifi: make WEP key restoring explicit The firmware clears default WEP keys on transitions to !associated, so we need to restore them just like stations. This is rather implicit as part of sending a station right now, which is odd. Make it explicit instead and only for agn since 3945 doesn't use hw crypto for WEP. Due to that, iwl_send_static_wepkey_cmd is now only used in iwl-sta.c and can be static. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 25 ++++++++++--------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-sta.c | 14 +++++++++----- drivers/net/wireless/iwlwifi/iwl-sta.h | 2 +- 4 files changed, 20 insertions(+), 22 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 978604f8ae92..8a3b0edf83b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -158,6 +158,11 @@ int iwl_commit_rxon(struct iwl_priv *priv) } iwl_clear_ucode_stations(priv, false); iwl_restore_stations(priv); + ret = iwl_restore_default_wep_keys(priv); + if (ret) { + IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); + return ret; + } } IWL_DEBUG_INFO(priv, "Sending RXON\n" @@ -185,6 +190,11 @@ int iwl_commit_rxon(struct iwl_priv *priv) memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); iwl_clear_ucode_stations(priv, false); iwl_restore_stations(priv); + ret = iwl_restore_default_wep_keys(priv); + if (ret) { + IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); + return ret; + } } priv->start_calib = 0; @@ -3030,19 +3040,6 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, } } -/** - * iwl_restore_wepkeys - Restore WEP keys to device - */ -static void iwl_restore_wepkeys(struct iwl_priv *priv) -{ - mutex_lock(&priv->mutex); - if (priv->iw_mode == NL80211_IFTYPE_STATION && - priv->default_wep_key && - iwl_send_static_wepkey_cmd(priv, 0)) - IWL_ERR(priv, "Could not send WEP static key\n"); - mutex_unlock(&priv->mutex); -} - static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) @@ -3069,8 +3066,6 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, return ret; } - iwl_restore_wepkeys(priv); - /* Initialize rate scaling */ IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", sta->addr); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 4319bda487d9..95c2bc3c79ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1167,7 +1167,6 @@ struct iwl_priv { int num_stations; struct iwl_station_entry stations[IWL_STATION_COUNT]; struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; /* protected by mutex */ - u8 default_wep_key; u8 key_mapping_key; unsigned long ucode_key_table; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index e34ac0355c75..be3d222d8f2b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -759,7 +759,7 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_get_free_ucode_key_index); -int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) +static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) { int i, not_empty = 0; u8 buff[sizeof(struct iwl_wep_cmd) + @@ -803,7 +803,14 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) else return 0; } -EXPORT_SYMBOL(iwl_send_static_wepkey_cmd); + +int iwl_restore_default_wep_keys(struct iwl_priv *priv) +{ + WARN_ON(!mutex_is_locked(&priv->mutex)); + + return iwl_send_static_wepkey_cmd(priv, 0); +} +EXPORT_SYMBOL(iwl_restore_default_wep_keys); int iwl_remove_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf) @@ -819,7 +826,6 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, IWL_ERR(priv, "index %d not used in uCode key table.\n", keyconf->keyidx); - priv->default_wep_key--; memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); if (iwl_is_rfkill(priv)) { IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); @@ -851,8 +857,6 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, keyconf->hw_key_idx = HW_KEY_DEFAULT; priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; - priv->default_wep_key++; - if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table)) IWL_ERR(priv, "index %d already used in uCode key table.\n", keyconf->keyidx); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 87a34997a758..42cd2f4a01cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -44,11 +44,11 @@ */ u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid); -int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty); int iwl_remove_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *key); int iwl_set_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *key); +int iwl_restore_default_wep_keys(struct iwl_priv *priv); int iwl_set_dynamic_key(struct iwl_priv *priv, struct ieee80211_key_conf *key, u8 sta_id); int iwl_remove_dynamic_key(struct iwl_priv *priv, -- cgit v1.2.3 From 43a61261d7f571f760611711cd4e6b64ef661ad1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 Mar 2010 02:43:05 -0700 Subject: iwlwifi: remove wrong key use check Default WEP keys and regular keys are not allocated from the same space in the firmware, so we shouldn't use the same bits to indicate in use. For default WEP keys, however, mac80211 won't allow using the same key index twice, so the check is not necessary at all -- add/remove are perfectly nested due to those checks. Other keys are allocated in the device in a global array that only has a certain number of slots, so for that we need to keep the allocation bitmap; but the 802.11 key index isn't relevant there. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-sta.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index be3d222d8f2b..a43493f2abcf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -822,10 +822,6 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", keyconf->keyidx); - if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table)) - IWL_ERR(priv, "index %d not used in uCode key table.\n", - keyconf->keyidx); - memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); if (iwl_is_rfkill(priv)) { IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); @@ -857,10 +853,6 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, keyconf->hw_key_idx = HW_KEY_DEFAULT; priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; - if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table)) - IWL_ERR(priv, "index %d already used in uCode key table.\n", - keyconf->keyidx); - priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, keyconf->keylen); -- cgit v1.2.3 From a90178fa1dce52816ae9fa4a3ba031886b79c5ae Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 Mar 2010 02:44:16 -0700 Subject: iwlagn: simplify WEP key check Simplify the WEP group key check by checking the sta pointer instead of the sta_id we calculate with it; also clean up the comment formatting. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8a3b0edf83b0..3526d5ee4755 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2901,12 +2901,13 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, 100); - /* If we are getting WEP group key and we didn't receive any key mapping + /* + * If we are getting WEP group key and we didn't receive any key mapping * so far, we are in legacy wep mode (group key only), otherwise we are * in 1X mode. - * In legacy wep mode, we use another host command to the uCode */ - if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id && - priv->iw_mode != NL80211_IFTYPE_AP) { + * In legacy wep mode, we use another host command to the uCode. + */ + if (key->alg == ALG_WEP && !sta && vif->type != NL80211_IFTYPE_AP) { if (cmd == SET_KEY) is_default_wep_key = !priv->key_mapping_key; else -- cgit v1.2.3 From 76c3c698bf47927fb31044fa2f4321c99ed7411d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 Mar 2010 02:46:29 -0700 Subject: iwlwifi: remove pointless sta_id invalid check lq->sta_id cannot be invalid here since this function will only be called after the station has been added properly. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-sta.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index a43493f2abcf..6876f7c59368 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1187,13 +1187,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, .data = lq, }; - if ((lq->sta_id == 0xFF) && - (priv->iw_mode == NL80211_IFTYPE_ADHOC)) + if (WARN_ON(lq->sta_id == IWL_INVALID_STATION)) return -EINVAL; - if (lq->sta_id == 0xFF) - lq->sta_id = IWL_AP_ID; - iwl_dump_lq_cmd(priv, lq); BUG_ON(init && (cmd.flags & CMD_ASYNC)); -- cgit v1.2.3 From 05d5752027d02ca9204d1ece5074d41000fee23d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 31 Mar 2010 08:59:17 -0700 Subject: iwlwifi: clean up last_phy_res The last_phy_res[100] variable is used in an odd way. The first byte of it is used as a flag, and the rest as the data. Thus, the array need only be 61 bytes, since it is just the flag and a struct iwl_rx_phy_res (which is 60 bytes). Clean this up by splitting the variable into two: last_phy_res and last_phy_res_valid, using correct types for both (struct and bool). While doing all this also move the variables to the _agn part of the hw-specific union since they only apply to A-MPDUs. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 10 +++++----- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 49e20f1acb7c..7f27a945c187 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1001,11 +1001,11 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, phy_res->cfg_phy_cnt + len); ampdu_status = le32_to_cpu(rx_pkt_status); } else { - if (!priv->last_phy_res[0]) { + if (!priv->_agn.last_phy_res_valid) { IWL_ERR(priv, "MPDU frame without cached PHY data\n"); return; } - phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; + phy_res = &priv->_agn.last_phy_res; amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); len = le16_to_cpu(amsdu->byte_count); @@ -1094,10 +1094,10 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - priv->last_phy_res[0] = 1; - memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), + priv->_agn.last_phy_res_valid = true; + memcpy(&priv->_agn.last_phy_res, pkt->u.raw, sizeof(struct iwl_rx_phy_res)); } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 95c2bc3c79ed..9466e909f553 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1120,7 +1120,6 @@ struct iwl_priv { __le16 sensitivity_tbl[HD_TABLE_SIZE]; struct iwl_ht_config current_ht_config; - u8 last_phy_res[100]; /* Rate scaling data */ u8 retry_rate; @@ -1237,6 +1236,9 @@ struct iwl_priv { * no AGGREGATION */ u8 agg_tids_count; + + struct iwl_rx_phy_res last_phy_res; + bool last_phy_res_valid; } _agn; #endif }; -- cgit v1.2.3 From 461ef382fd68f02b7bac8f94f7f2b85162bad896 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 30 Mar 2010 17:57:53 -0700 Subject: iwlwifi: add more debug info in error event dump When sys assert happen, driver will dump the error table information provided by uCode. There are more information available but is not being display by the driver; adding program counter and last host command the to log to help uCode debugging. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 10 ++++++---- drivers/net/wireless/iwlwifi/iwl-commands.h | 27 ++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3526d5ee4755..8a002c6f3a61 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1843,6 +1843,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) u32 data2, line; u32 desc, time, count, base, data1; u32 blink1, blink2, ilink1, ilink2; + u32 pc, hcmd; if (priv->ucode_type == UCODE_INIT) base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); @@ -1865,6 +1866,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) } desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); + pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32)); blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); @@ -1873,6 +1875,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); + hcmd = iwl_read_targ_mem(priv, base + 22 * sizeof(u32)); trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, blink1, blink2, ilink1, ilink2); @@ -1881,10 +1884,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) "data1 data2 line\n"); IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", desc_lookup(desc), desc, time, data1, data2, line); - IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n"); - IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, - ilink1, ilink2); - + IWL_ERR(priv, "pc blink1 blink2 ilink1 ilink2 hcmd\n"); + IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n", + pc, blink1, blink2, ilink1, ilink2, hcmd); } #define EVENT_START_OFFSET (4 * sizeof(u32)) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 6383d9f8c9b3..74d6887c7500 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -512,8 +512,9 @@ struct iwl_init_alive_resp { * * Entries without timestamps contain only event_id and data. * + * * 2) error_event_table_ptr indicates base of the error log. This contains - * information about any uCode error that occurs. For 4965, the format + * information about any uCode error that occurs. For agn, the format * of the error log is: * * __le32 valid; (nonzero) valid, (0) log is empty @@ -529,6 +530,30 @@ struct iwl_init_alive_resp { * __le32 bcon_time; beacon timer * __le32 tsf_low; network timestamp function timer * __le32 tsf_hi; network timestamp function timer + * __le32 gp1; GP1 timer register + * __le32 gp2; GP2 timer register + * __le32 gp3; GP3 timer register + * __le32 ucode_ver; uCode version + * __le32 hw_ver; HW Silicon version + * __le32 brd_ver; HW board version + * __le32 log_pc; log program counter + * __le32 frame_ptr; frame pointer + * __le32 stack_ptr; stack pointer + * __le32 hcmd; last host command + * __le32 isr0; isr status register LMPM_NIC_ISR0: rxtx_flag + * __le32 isr1; isr status register LMPM_NIC_ISR1: host_flag + * __le32 isr2; isr status register LMPM_NIC_ISR2: enc_flag + * __le32 isr3; isr status register LMPM_NIC_ISR3: time_flag + * __le32 isr4; isr status register LMPM_NIC_ISR4: wico interrupt + * __le32 isr_pref; isr status register LMPM_NIC_PREF_STAT + * __le32 wait_event; wait event() caller address + * __le32 l2p_control; L2pControlField + * __le32 l2p_duration; L2pDurationField + * __le32 l2p_mhvalid; L2pMhValidBits + * __le32 l2p_addr_match; L2pAddrMatchStat + * __le32 lmpm_pmg_sel; indicate which clocks are turned on (LMPM_PMG_SEL) + * __le32 u_timestamp; indicate when the date and time of the compilation + * __le32 reserved; * * The Linux driver can print both logs to the system log when a uCode error * occurs. -- cgit v1.2.3 From 04569cbe7653fe0057acc46afc07f2c2fd2508b3 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 31 Mar 2010 17:57:28 -0700 Subject: iwlwifi: update tx command response status Update to include additional tx command response status for "_agn" devices. The following status indicate the transmission was postponed: TX_STATUS_POSTPONE_DELAY TX_STATUS_POSTPONE_FEW_BYTES TX_STATUS_POSTPONE_BT_PRIO TX_STATUS_POSTPONE_QUIET_PERIOD TX_STATUS_POSTPONE_CALC_TTAK Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 3 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 11 +++- drivers/net/wireless/iwlwifi/iwl-agn.h | 24 +++++++++ drivers/net/wireless/iwlwifi/iwl-commands.h | 79 ++++++++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-tx.c | 41 ++++++++------- 6 files changed, 108 insertions(+), 54 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 7424586a5edb..ae5efc376b91 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -191,12 +191,12 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp) } #ifdef CONFIG_IWLWIFI_DEBUG -#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x +#define TX_STATUS_ENTRY(x) case TX_3945_STATUS_FAIL_ ## x: return #x static const char *iwl3945_get_tx_fail_reason(u32 status) { switch (status & TX_STATUS_MSK) { - case TX_STATUS_SUCCESS: + case TX_3945_STATUS_SUCCESS: return "SUCCESS"; TX_STATUS_ENTRY(SHORT_LIMIT); TX_STATUS_ENTRY(LONG_LIMIT); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 0164c3f2109d..c710b26a1c86 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2049,8 +2049,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); - if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) - IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); + iwl_check_abort_status(priv, tx_resp->frame_count, status); } static int iwl4965_calc_rssi(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 7f27a945c187..384b45c519f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -161,6 +161,14 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, return 0; } +void iwl_check_abort_status(struct iwl_priv *priv, + u8 frame_count, u32 status) +{ + if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { + IWL_ERR(priv, "TODO: Implement Tx flush command!!!\n"); + } +} + static void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -246,8 +254,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); - if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) - IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); + iwl_check_abort_status(priv, tx_resp->frame_count, status); } void iwlagn_rx_handler_setup(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 5ad14055eda3..608060abe80c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -105,6 +105,8 @@ void iwlagn_init_alive_start(struct iwl_priv *priv); int iwlagn_alive_notify(struct iwl_priv *priv); /* lib */ +void iwl_check_abort_status(struct iwl_priv *priv, + u8 frame_count, u32 status); void iwlagn_rx_handler_setup(struct iwl_priv *priv); void iwlagn_setup_deferred_work(struct iwl_priv *priv); int iwlagn_hw_valid_rtc_data_addr(u32 addr); @@ -146,4 +148,26 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv); int iwlagn_txq_ctx_reset(struct iwl_priv *priv); void iwlagn_txq_ctx_stop(struct iwl_priv *priv); +static inline u32 iwl_tx_status_to_mac80211(u32 status) +{ + status &= TX_STATUS_MSK; + + switch (status) { + case TX_STATUS_SUCCESS: + case TX_STATUS_DIRECT_DONE: + return IEEE80211_TX_STAT_ACK; + case TX_STATUS_FAIL_DEST_PS: + return IEEE80211_TX_STAT_TX_FILTERED; + default: + return 0; + } +} + +static inline bool iwl_is_tx_success(u32 status) +{ + status &= TX_STATUS_MSK; + return (status == TX_STATUS_SUCCESS) || + (status == TX_STATUS_DIRECT_DONE); +} + #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 74d6887c7500..82a9378f72e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -1662,7 +1662,7 @@ struct iwl_tx_cmd { struct ieee80211_hdr hdr[0]; } __attribute__ ((packed)); -/* TX command response is sent after *all* transmission attempts. +/* TX command response is sent after *3945* transmission attempts. * * NOTES: * @@ -1689,25 +1689,66 @@ struct iwl_tx_cmd { * command FIFO has been cleared. The host must then deactivate the TX Abort * control line. Receiving is still allowed in this case. */ +enum { + TX_3945_STATUS_SUCCESS = 0x01, + TX_3945_STATUS_DIRECT_DONE = 0x02, + TX_3945_STATUS_FAIL_SHORT_LIMIT = 0x82, + TX_3945_STATUS_FAIL_LONG_LIMIT = 0x83, + TX_3945_STATUS_FAIL_FIFO_UNDERRUN = 0x84, + TX_3945_STATUS_FAIL_MGMNT_ABORT = 0x85, + TX_3945_STATUS_FAIL_NEXT_FRAG = 0x86, + TX_3945_STATUS_FAIL_LIFE_EXPIRE = 0x87, + TX_3945_STATUS_FAIL_DEST_PS = 0x88, + TX_3945_STATUS_FAIL_ABORTED = 0x89, + TX_3945_STATUS_FAIL_BT_RETRY = 0x8a, + TX_3945_STATUS_FAIL_STA_INVALID = 0x8b, + TX_3945_STATUS_FAIL_FRAG_DROPPED = 0x8c, + TX_3945_STATUS_FAIL_TID_DISABLE = 0x8d, + TX_3945_STATUS_FAIL_FRAME_FLUSHED = 0x8e, + TX_3945_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, + TX_3945_STATUS_FAIL_TX_LOCKED = 0x90, + TX_3945_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91, +}; + +/* + * TX command response is sent after *agn* transmission attempts. + * + * both postpone and abort status are expected behavior from uCode. there is + * no special operation required from driver; except for RFKILL_FLUSH, + * which required tx flush host command to flush all the tx frames in queues + */ enum { TX_STATUS_SUCCESS = 0x01, TX_STATUS_DIRECT_DONE = 0x02, + /* postpone TX */ + TX_STATUS_POSTPONE_DELAY = 0x40, + TX_STATUS_POSTPONE_FEW_BYTES = 0x41, + TX_STATUS_POSTPONE_BT_PRIO = 0x42, + TX_STATUS_POSTPONE_QUIET_PERIOD = 0x43, + TX_STATUS_POSTPONE_CALC_TTAK = 0x44, + /* abort TX */ + TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY = 0x81, TX_STATUS_FAIL_SHORT_LIMIT = 0x82, TX_STATUS_FAIL_LONG_LIMIT = 0x83, TX_STATUS_FAIL_FIFO_UNDERRUN = 0x84, - TX_STATUS_FAIL_MGMNT_ABORT = 0x85, - TX_STATUS_FAIL_NEXT_FRAG = 0x86, + TX_STATUS_FAIL_DRAIN_FLOW = 0x85, + TX_STATUS_FAIL_RFKILL_FLUSH = 0x86, TX_STATUS_FAIL_LIFE_EXPIRE = 0x87, TX_STATUS_FAIL_DEST_PS = 0x88, - TX_STATUS_FAIL_ABORTED = 0x89, + TX_STATUS_FAIL_HOST_ABORTED = 0x89, TX_STATUS_FAIL_BT_RETRY = 0x8a, TX_STATUS_FAIL_STA_INVALID = 0x8b, TX_STATUS_FAIL_FRAG_DROPPED = 0x8c, TX_STATUS_FAIL_TID_DISABLE = 0x8d, - TX_STATUS_FAIL_FRAME_FLUSHED = 0x8e, + TX_STATUS_FAIL_FIFO_FLUSHED = 0x8e, TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, - TX_STATUS_FAIL_TX_LOCKED = 0x90, - TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91, + /* uCode drop due to FW drop request */ + TX_STATUS_FAIL_FW_DROP = 0x90, + /* + * uCode drop due to station color mismatch + * between tx command and station table + */ + TX_STATUS_FAIL_STA_COLOR_MISMATCH_DROP = 0x91, }; #define TX_PACKET_MODE_REGULAR 0x0000 @@ -1729,30 +1770,6 @@ enum { TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */ }; -static inline u32 iwl_tx_status_to_mac80211(u32 status) -{ - status &= TX_STATUS_MSK; - - switch (status) { - case TX_STATUS_SUCCESS: - case TX_STATUS_DIRECT_DONE: - return IEEE80211_TX_STAT_ACK; - case TX_STATUS_FAIL_DEST_PS: - return IEEE80211_TX_STAT_TX_FILTERED; - default: - return 0; - } -} - -static inline bool iwl_is_tx_success(u32 status) -{ - status &= TX_STATUS_MSK; - return (status == TX_STATUS_SUCCESS) || - (status == TX_STATUS_DIRECT_DONE); -} - - - /* ******************************* * TX aggregation status ******************************* */ diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index a631afef5e33..aea6a2eee9c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -629,29 +629,36 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) EXPORT_SYMBOL(iwl_tx_cmd_complete); #ifdef CONFIG_IWLWIFI_DEBUG -#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x +#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x +#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x const char *iwl_get_tx_fail_reason(u32 status) { switch (status & TX_STATUS_MSK) { case TX_STATUS_SUCCESS: return "SUCCESS"; - TX_STATUS_ENTRY(SHORT_LIMIT); - TX_STATUS_ENTRY(LONG_LIMIT); - TX_STATUS_ENTRY(FIFO_UNDERRUN); - TX_STATUS_ENTRY(MGMNT_ABORT); - TX_STATUS_ENTRY(NEXT_FRAG); - TX_STATUS_ENTRY(LIFE_EXPIRE); - TX_STATUS_ENTRY(DEST_PS); - TX_STATUS_ENTRY(ABORTED); - TX_STATUS_ENTRY(BT_RETRY); - TX_STATUS_ENTRY(STA_INVALID); - TX_STATUS_ENTRY(FRAG_DROPPED); - TX_STATUS_ENTRY(TID_DISABLE); - TX_STATUS_ENTRY(FRAME_FLUSHED); - TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL); - TX_STATUS_ENTRY(TX_LOCKED); - TX_STATUS_ENTRY(NO_BEACON_ON_RADAR); + TX_STATUS_POSTPONE(DELAY); + TX_STATUS_POSTPONE(FEW_BYTES); + TX_STATUS_POSTPONE(BT_PRIO); + TX_STATUS_POSTPONE(QUIET_PERIOD); + TX_STATUS_POSTPONE(CALC_TTAK); + TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY); + TX_STATUS_FAIL(SHORT_LIMIT); + TX_STATUS_FAIL(LONG_LIMIT); + TX_STATUS_FAIL(FIFO_UNDERRUN); + TX_STATUS_FAIL(DRAIN_FLOW); + TX_STATUS_FAIL(RFKILL_FLUSH); + TX_STATUS_FAIL(LIFE_EXPIRE); + TX_STATUS_FAIL(DEST_PS); + TX_STATUS_FAIL(HOST_ABORTED); + TX_STATUS_FAIL(BT_RETRY); + TX_STATUS_FAIL(STA_INVALID); + TX_STATUS_FAIL(FRAG_DROPPED); + TX_STATUS_FAIL(TID_DISABLE); + TX_STATUS_FAIL(FIFO_FLUSHED); + TX_STATUS_FAIL(INSUFFICIENT_CF_POLL); + TX_STATUS_FAIL(FW_DROP); + TX_STATUS_FAIL(STA_COLOR_MISMATCH_DROP); } return "UNKNOWN"; -- cgit v1.2.3 From 4c8d1913ac1baab64080c1030cb94e24cbd9a0f8 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 31 Mar 2010 18:16:52 -0700 Subject: iwlwifi: small changes in comments REPLY_TX_LINK_QUALITY_CMD was used by 4965, 5000 series and up Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 82a9378f72e2..d830086ca195 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -106,7 +106,7 @@ enum { REPLY_TX = 0x1c, REPLY_RATE_SCALE = 0x47, /* 3945 only */ REPLY_LEDS_CMD = 0x48, - REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */ + REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* for 4965 and up */ /* WiMAX coexistence */ COEX_PRIORITY_TABLE_CMD = 0x5a, /* for 5000 series and up */ -- cgit v1.2.3 From f875f5183b8f511161eddcbb4e9a1aada33d4aaf Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Mon, 5 Apr 2010 10:43:10 -0700 Subject: iwlwifi: fix compile warnings when compiling without debug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: CC [M] drivers/net/wireless/iwlwifi/iwl-agn-rs.o drivers/net/wireless/iwlwifi/iwl-agn-rs.c: In function ‘rs_get_rate’: drivers/net/wireless/iwlwifi/iwl-agn-rs.c:2419: warning: unused variable ‘priv’ CC [M] drivers/net/wireless/iwlwifi/iwl-sta.o drivers/net/wireless/iwlwifi/iwl-sta.c: In function ‘iwl_send_add_sta’: drivers/net/wireless/iwlwifi/iwl-sta.c:197: warning: unused variable ‘sta_id’ drivers/net/wireless/iwlwifi/iwl-3945.c: In function ‘iwl3945_rx_reply_rx’: drivers/net/wireless/iwlwifi/iwl-3945.c:601: warning: unused variable ‘rx_stats_noise_diff’ drivers/net/wireless/iwlwifi/iwl-3945.c:600: warning: unused variable ‘rx_stats_sig_avg’ drivers/net/wireless/iwlwifi/iwl-3945-rs.c: In function ‘rs_get_rate’: drivers/net/wireless/iwlwifi/iwl-3945-rs.c:650: warning: unused variable ‘priv’ Reported-by: Luis R. Rodriguez Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 9e411dc0e5e1..80e9bbc7884a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -647,7 +647,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, unsigned long flags; u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; s8 max_rate_idx = -1; - struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); IWL_DEBUG_RATE(priv, "enter\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index ae5efc376b91..15de649888d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -597,8 +597,8 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); - u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg); - u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff); + u16 rx_stats_sig_avg __maybe_unused = le16_to_cpu(rx_stats->sig_avg); + u16 rx_stats_noise_diff __maybe_unused = le16_to_cpu(rx_stats->noise_diff); u8 network_packet; rx_status.flag = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 0c3c76803c5e..3c1cd417bbc5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2409,7 +2409,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb = txrc->skb; struct ieee80211_supported_band *sband = txrc->sband; - struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_lq_sta *lq_sta = priv_sta; int rate_idx; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 6876f7c59368..9b4d527bd3f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -194,7 +194,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, .flags = flags, .data = data, }; - u8 sta_id = sta->sta.sta_id; + u8 sta_id __maybe_unused = sta->sta.sta_id; IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n", sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); -- cgit v1.2.3 From 57e40d36e59f828f43d60b2662041991dcd78044 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 9 Mar 2010 15:36:10 -0800 Subject: iwlwifi: fix compiler warning Check return code on iwl_send_cmd_pdu() to get rid of compiler warning. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-sta.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 9b4d527bd3f8..d86ecd2f9ec2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -425,6 +425,7 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) .reserved1 = 0, }; u32 rate_flags; + int ret = 0; /* Set up the rate scaling to start at selected rate, fall back * all the way down to 1M in IEEE order, and then spin on 1M */ @@ -458,8 +459,10 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) /* Update the rate scaling for control frame Tx to AP */ link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; - iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, + ret = iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, sizeof(link_cmd), &link_cmd); + if (ret) + IWL_ERR(priv, "REPLY_TX_LINK_QUALITY_CMD failed (%d)\n", ret); } /* -- cgit v1.2.3 From 470058e0ad82fcfaaffd57307d8bf8c094e8e9d7 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Fri, 2 Apr 2010 13:38:54 -0700 Subject: iwlwifi: avoid Tx queue memory allocation in interface down We used to free all the Tx queues memory when interface is brought down and reallocate them again in interface up. This requires order-4 allocation for txq->cmd[]. In situations like s2ram, this usually leads to allocation failure in the memory subsystem. The patch fixed this problem by allocating the Tx queues memory only at the first time. Later iwl_down/iwl_up only initialize but don't free and reallocate them. The memory is freed at the device removal time. BTW, we have already done this for the Rx queue. This fixed bug https://bugzilla.kernel.org/show_bug.cgi?id=15551 Signed-off-by: Zhu Yi Acked-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 11 ++++++--- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 39 ++++++++++++++++++++++-------- drivers/net/wireless/iwlwifi/iwl-agn.h | 3 ++- drivers/net/wireless/iwlwifi/iwl-tx.c | 20 +++++++++++++++ 4 files changed, 58 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 384b45c519f1..c465c8590833 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -512,10 +512,13 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); - /* Allocate and init all Tx and Command queues */ - ret = iwlagn_txq_ctx_reset(priv); - if (ret) - return ret; + /* Allocate or reset and init all Tx and Command queues */ + if (!priv->txq) { + ret = iwlagn_txq_ctx_alloc(priv); + if (ret) + return ret; + } else + iwlagn_txq_ctx_reset(priv); set_bit(STATUS_INIT, &priv->status); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index a76e14351b5a..3077eac58880 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -809,8 +809,7 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) /* Tx queues */ if (priv->txq) { - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; - txq_id++) + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) if (txq_id == IWL_CMD_QUEUE_NUM) iwl_cmd_queue_free(priv); else @@ -825,15 +824,15 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) } /** - * iwlagn_txq_ctx_reset - Reset TX queue context - * Destroys all DMA structures and initialize them again + * iwlagn_txq_ctx_alloc - allocate TX queue context + * Allocate all Tx DMA structures and initialize them * * @param priv * @return error code */ -int iwlagn_txq_ctx_reset(struct iwl_priv *priv) +int iwlagn_txq_ctx_alloc(struct iwl_priv *priv) { - int ret = 0; + int ret; int txq_id, slots_num; unsigned long flags; @@ -891,8 +890,31 @@ int iwlagn_txq_ctx_reset(struct iwl_priv *priv) return ret; } +void iwlagn_txq_ctx_reset(struct iwl_priv *priv) +{ + int txq_id, slots_num; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + /* Turn off all Tx DMA fifos */ + priv->cfg->ops->lib->txq_set_sched(priv, 0); + + /* Tell NIC where to find the "keep warm" buffer */ + iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); + + spin_unlock_irqrestore(&priv->lock, flags); + + /* Alloc and init all Tx queues, including the command queue (#4) */ + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { + slots_num = txq_id == IWL_CMD_QUEUE_NUM ? + TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; + iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); + } +} + /** - * iwlagn_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory + * iwlagn_txq_ctx_stop - Stop all Tx DMA channels */ void iwlagn_txq_ctx_stop(struct iwl_priv *priv) { @@ -912,9 +934,6 @@ void iwlagn_txq_ctx_stop(struct iwl_priv *priv) 1000); } spin_unlock_irqrestore(&priv->lock, flags); - - /* Deallocate memory for all Tx queues */ - iwlagn_hw_txq_ctx_free(priv); } /* diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 608060abe80c..5d3142287e14 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -145,7 +145,8 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv); -int iwlagn_txq_ctx_reset(struct iwl_priv *priv); +int iwlagn_txq_ctx_alloc(struct iwl_priv *priv); +void iwlagn_txq_ctx_reset(struct iwl_priv *priv); void iwlagn_txq_ctx_stop(struct iwl_priv *priv); static inline u32 iwl_tx_status_to_mac80211(u32 status) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index aea6a2eee9c3..c3c6505a8c69 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -394,6 +394,26 @@ out_free_arrays: } EXPORT_SYMBOL(iwl_tx_queue_init); +void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, + int slots_num, u32 txq_id) +{ + int actual_slots = slots_num; + + if (txq_id == IWL_CMD_QUEUE_NUM) + actual_slots++; + + memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots); + + txq->need_update = 0; + + /* Initialize queue's high/low-water marks, and head/tail indexes */ + iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); + + /* Tell device where to find queue */ + priv->cfg->ops->lib->txq_init(priv, txq); +} +EXPORT_SYMBOL(iwl_tx_queue_reset); + /*************** HOST COMMAND QUEUE FUNCTIONS *****/ /** -- cgit v1.2.3 From 5988f385b4cffa9ca72c5be0188e5f4c9ef46d82 Mon Sep 17 00:00:00 2001 From: Quintin Pitts Date: Fri, 9 Apr 2010 21:37:38 +0200 Subject: p54pci: prevent stuck rx-ring on slow system This patch fixes an old problem, which - under certain circumstances - could cause the device to become unresponsive. most of p54pci's rx-ring management is implemented in just two distinct standalone functions. p54p_check_rx_ring takes care of processing incoming data, while p54p_refill_rx_ring tries to replenish all depleted communication buffers. This has always worked fine on my fast machine, but now I know there is a hidden race... The most likely candidate here is ring_control->device_idx. Quintin Pitts had already analyzed the culprit and posted a patch back in Oct 2009. But sadly, no one's picked up on this. ( https://patchwork.kernel.org/patch/53079/ [2 & 3] ). This patch does the same way, except that it also prioritize rx data processing, simply because tx routines *can* wait. Reported-by: Sean Young Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=11386 Reported-by: Quintin Pitts Signed-off-by: Quintin Pitts Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54pci.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index ed4bdffdd63e..aa29663bf6c9 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -131,7 +131,7 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev) static void p54p_refill_rx_ring(struct ieee80211_hw *dev, int ring_index, struct p54p_desc *ring, u32 ring_limit, - struct sk_buff **rx_buf) + struct sk_buff **rx_buf, u32 index) { struct p54p_priv *priv = dev->priv; struct p54p_ring_control *ring_control = priv->ring_control; @@ -139,7 +139,7 @@ static void p54p_refill_rx_ring(struct ieee80211_hw *dev, idx = le32_to_cpu(ring_control->host_idx[ring_index]); limit = idx; - limit -= le32_to_cpu(ring_control->device_idx[ring_index]); + limit -= le32_to_cpu(index); limit = ring_limit - limit; i = idx % ring_limit; @@ -231,7 +231,7 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index, i %= ring_limit; } - p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf); + p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf, *index); } static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, @@ -276,14 +276,6 @@ static void p54p_tasklet(unsigned long dev_id) struct p54p_priv *priv = dev->priv; struct p54p_ring_control *ring_control = priv->ring_control; - p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt, - ARRAY_SIZE(ring_control->tx_mgmt), - priv->tx_buf_mgmt); - - p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data, - ARRAY_SIZE(ring_control->tx_data), - priv->tx_buf_data); - p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt, ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt); @@ -292,6 +284,14 @@ static void p54p_tasklet(unsigned long dev_id) wmb(); P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); + + p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt, + ARRAY_SIZE(ring_control->tx_mgmt), + priv->tx_buf_mgmt); + + p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data, + ARRAY_SIZE(ring_control->tx_data), + priv->tx_buf_data); } static irqreturn_t p54p_interrupt(int irq, void *dev_id) @@ -444,10 +444,10 @@ static int p54p_open(struct ieee80211_hw *dev) priv->rx_idx_mgmt = priv->tx_idx_mgmt = 0; p54p_refill_rx_ring(dev, 0, priv->ring_control->rx_data, - ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data); + ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data, 0); p54p_refill_rx_ring(dev, 2, priv->ring_control->rx_mgmt, - ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt); + ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt, 0); P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma)); P54P_READ(ring_control_base); -- cgit v1.2.3 From 06855ef4c8cf3d86d831c6317ca6a3563d271350 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sun, 11 Apr 2010 14:31:07 +0200 Subject: rt2x00: Let RF chipset decide the RF channel switch method to use in rt2800. It seems that the distinction between RF channel switch method is solely based on the RF chipset that is used. Refactor the channel switch decision to just take the RF chipset into account, thereby greatly simplifying the check. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index ec3ec786f350..6fdec1536db7 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -717,10 +717,10 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev, rt2x00dev->lna_gain = lna_gain; } -static void rt2800_config_channel_rt2x(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf, - struct rf_channel *rf, - struct channel_info *info) +static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) { rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); @@ -786,10 +786,10 @@ static void rt2800_config_channel_rt2x(struct rt2x00_dev *rt2x00dev, rt2800_rf_write(rt2x00dev, 4, rf->rf4); } -static void rt2800_config_channel_rt3x(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf, - struct rf_channel *rf, - struct channel_info *info) +static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) { u8 rfcsr; @@ -826,16 +826,13 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, unsigned int tx_pin; u8 bbp; - if ((rt2x00_rt(rt2x00dev, RT3070) || - rt2x00_rt(rt2x00dev, RT3090) || - rt2x00_rt(rt2x00dev, RT2872)) && - (rt2x00_rf(rt2x00dev, RF2020) || - rt2x00_rf(rt2x00dev, RF3020) || - rt2x00_rf(rt2x00dev, RF3021) || - rt2x00_rf(rt2x00dev, RF3022))) - rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info); + if (rt2x00_rf(rt2x00dev, RF2020) || + rt2x00_rf(rt2x00dev, RF3020) || + rt2x00_rf(rt2x00dev, RF3021) || + rt2x00_rf(rt2x00dev, RF3022)) + rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); else - rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info); + rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); /* * Change BBP settings -- cgit v1.2.3 From fab799c3b275a207215dfef91c0ac716f12c8727 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sun, 11 Apr 2010 14:31:08 +0200 Subject: rt2x00: Update rt2800 register definitions towards latest definitions. Definitions taken from the latest rt2860 / rt2870 / rt3070 / rt3090 Ralink vendor drivers. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 55 +++++++++++++++++++++++++++++++-- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 2 files changed, 54 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 74c0433dba37..455dc3ffb256 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -56,6 +56,7 @@ #define RF3021 0x0007 #define RF3022 0x0008 #define RF3052 0x0009 +#define RF3320 0x000b /* * Chipset version. @@ -90,9 +91,15 @@ #define NUM_TX_QUEUES 4 /* - * USB registers. + * Registers. */ +/* + * OPT_14: Unknown register used by rt3xxx devices. + */ +#define OPT_14_CSR 0x0114 +#define OPT_14_CSR_BIT0 FIELD32(0x00000001) + /* * INT_SOURCE_CSR: Interrupt source register. * Write one to clear corresponding bit. @@ -397,6 +404,31 @@ */ #define EFUSE_DATA3 0x059c +/* + * LDO_CFG0 + */ +#define LDO_CFG0 0x05d4 +#define LDO_CFG0_DELAY3 FIELD32(0x000000ff) +#define LDO_CFG0_DELAY2 FIELD32(0x0000ff00) +#define LDO_CFG0_DELAY1 FIELD32(0x00ff0000) +#define LDO_CFG0_BGSEL FIELD32(0x03000000) +#define LDO_CFG0_LDO_CORE_VLEVEL FIELD32(0x1c000000) +#define LD0_CFG0_LDO25_LEVEL FIELD32(0x60000000) +#define LDO_CFG0_LDO25_LARGEA FIELD32(0x80000000) + +/* + * GPIO_SWITCH + */ +#define GPIO_SWITCH 0x05dc +#define GPIO_SWITCH_0 FIELD32(0x00000001) +#define GPIO_SWITCH_1 FIELD32(0x00000002) +#define GPIO_SWITCH_2 FIELD32(0x00000004) +#define GPIO_SWITCH_3 FIELD32(0x00000008) +#define GPIO_SWITCH_4 FIELD32(0x00000010) +#define GPIO_SWITCH_5 FIELD32(0x00000020) +#define GPIO_SWITCH_6 FIELD32(0x00000040) +#define GPIO_SWITCH_7 FIELD32(0x00000080) + /* * MAC Control/Status Registers(CSR). * Some values are set in TU, whereas 1 TU == 1024 us. @@ -1491,6 +1523,14 @@ struct mac_iveiv_entry { #define BBP4_TX_BF FIELD8(0x01) #define BBP4_BANDWIDTH FIELD8(0x18) +/* + * BBP 138: Unknown + */ +#define BBP138_RX_ADC1 FIELD8(0x02) +#define BBP138_RX_ADC2 FIELD8(0x04) +#define BBP138_TX_DAC1 FIELD8(0x20) +#define BBP138_TX_DAC2 FIELD8(0x40) + /* * RFCSR registers * The wordsize of the RFCSR is 8 bits. @@ -1499,7 +1539,8 @@ struct mac_iveiv_entry { /* * RFCSR 6: */ -#define RFCSR6_R FIELD8(0x03) +#define RFCSR6_R1 FIELD8(0x03) +#define RFCSR6_R2 FIELD8(0x40) /* * RFCSR 7: @@ -1511,6 +1552,14 @@ struct mac_iveiv_entry { */ #define RFCSR12_TX_POWER FIELD8(0x1f) +/* + * RFCSR 17: + */ +#define RFCSR17_R1 FIELD8(0x07) +#define RFCSR17_R2 FIELD8(0x08) +#define RFCSR17_R3 FIELD8(0x20) + + /* * RFCSR 22: */ @@ -1603,6 +1652,8 @@ struct mac_iveiv_entry { #define EEPROM_NIC_WPS_PBC FIELD16(0x0080) #define EEPROM_NIC_BW40M_BG FIELD16(0x0100) #define EEPROM_NIC_BW40M_A FIELD16(0x0200) +#define EEPROM_NIC_ANT_DIVERSITY FIELD16(0x0800) +#define EEPROM_NIC_DAC_TEST FIELD16(0x8000) /* * EEPROM frequency diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 6fdec1536db7..394c8e490c9a 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -797,7 +797,7 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3); rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2); + rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2); rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); -- cgit v1.2.3 From e148b4c82a6269aa19476e4865afe8aa84360c8f Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sun, 11 Apr 2010 14:31:09 +0200 Subject: rt2x00: Align RT chipset definitions with vendor driver. Only include definitions for RT chipsets that are also used inside the Ralink vendor drivers. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 43 ++++++++++++++++++++++++++++++--- drivers/net/wireless/rt2x00/rt2800lib.c | 22 ++++++----------- drivers/net/wireless/rt2x00/rt2x00.h | 7 +++--- 3 files changed, 50 insertions(+), 22 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 455dc3ffb256..4d5871b01cac 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -1536,6 +1536,15 @@ struct mac_iveiv_entry { * The wordsize of the RFCSR is 8 bits. */ +/* + * RFCSR 1: + */ +#define RFCSR1_RF_BLOCK_EN FIELD8(0x01) +#define RFCSR1_RX0_PD FIELD8(0x04) +#define RFCSR1_TX0_PD FIELD8(0x08) +#define RFCSR1_RX1_PD FIELD8(0x10) +#define RFCSR1_TX1_PD FIELD8(0x20) + /* * RFCSR 6: */ @@ -1552,13 +1561,27 @@ struct mac_iveiv_entry { */ #define RFCSR12_TX_POWER FIELD8(0x1f) +/* + * RFCSR 15: + */ +#define RFCSR15_TX_LO2_EN FIELD8(0x08) + /* * RFCSR 17: */ -#define RFCSR17_R1 FIELD8(0x07) -#define RFCSR17_R2 FIELD8(0x08) -#define RFCSR17_R3 FIELD8(0x20) +#define RFCSR17_TXMIXER_GAIN FIELD8(0x07) +#define RFCSR17_TX_LO1_EN FIELD8(0x08) +#define RFCSR17_R FIELD8(0x20) +/* + * RFCSR 20: + */ +#define RFCSR20_RX_LO1_EN FIELD8(0x08) + +/* + * RFCSR 21: + */ +#define RFCSR21_RX_LO2_EN FIELD8(0x08) /* * RFCSR 22: @@ -1570,6 +1593,14 @@ struct mac_iveiv_entry { */ #define RFCSR23_FREQ_OFFSET FIELD8(0x7f) +/* + * RFCSR 27: + */ +#define RFCSR27_R1 FIELD8(0x03) +#define RFCSR27_R2 FIELD8(0x04) +#define RFCSR27_R3 FIELD8(0x30) +#define RFCSR27_R4 FIELD8(0x40) + /* * RFCSR 30: */ @@ -1709,6 +1740,12 @@ struct mac_iveiv_entry { #define EEPROM_RSSI_BG2_OFFSET2 FIELD16(0x00ff) #define EEPROM_RSSI_BG2_LNA_A1 FIELD16(0xff00) +/* + * EEPROM TXMIXER GAIN BG offset (note overlaps with EEPROM RSSI BG2). + */ +#define EEPROM_TXMIXER_GAIN_BG 0x0024 +#define EEPROM_TXMIXER_GAIN_BG_VAL FIELD16(0x0007) + /* * EEPROM RSSI A offset */ diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 394c8e490c9a..2ab88840a3e5 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1209,10 +1209,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); if ((rt2x00_rt(rt2x00dev, RT2872) && (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION)) || - rt2x00_rt(rt2x00dev, RT2880) || rt2x00_rt(rt2x00dev, RT2883) || - rt2x00_rt(rt2x00dev, RT2890) || - rt2x00_rt(rt2x00dev, RT3052) || (rt2x00_rt(rt2x00dev, RT3070) && (rt2x00_rev(rt2x00dev) < RT3070_VERSION))) rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); @@ -1503,6 +1500,12 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) (rt2x00_rev(rt2x00dev) > RT2860D_VERSION)) rt2800_bbp_write(rt2x00dev, 84, 0x19); + if (rt2x00_rt(rt2x00dev, RT2872)) { + rt2800_bbp_write(rt2x00dev, 31, 0x08); + rt2800_bbp_write(rt2x00dev, 78, 0x0e); + rt2800_bbp_write(rt2x00dev, 80, 0x08); + } + if (rt2x00_is_usb(rt2x00dev) && rt2x00_rt(rt2x00dev, RT3070) && (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) { @@ -1511,12 +1514,6 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 105, 0x05); } - if (rt2x00_rt(rt2x00dev, RT3052)) { - rt2800_bbp_write(rt2x00dev, 31, 0x08); - rt2800_bbp_write(rt2x00dev, 78, 0x0e); - rt2800_bbp_write(rt2x00dev, 80, 0x08); - } - for (i = 0; i < EEPROM_BBP_SIZE; i++) { rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); @@ -1772,9 +1769,7 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) } else if (rt2x00_rt(rt2x00dev, RT2860) || rt2x00_rt(rt2x00dev, RT2870) || rt2x00_rt(rt2x00dev, RT2872) || - rt2x00_rt(rt2x00dev, RT2880) || - (rt2x00_rt(rt2x00dev, RT2883) && - (rt2x00_rev(rt2x00dev) < RT2883_VERSION))) { + rt2x00_rt(rt2x00dev, RT2872)) { /* * There is a max of 2 RX streams for RT28x0 series */ @@ -1879,10 +1874,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) if (!rt2x00_rt(rt2x00dev, RT2860) && !rt2x00_rt(rt2x00dev, RT2870) && !rt2x00_rt(rt2x00dev, RT2872) && - !rt2x00_rt(rt2x00dev, RT2880) && !rt2x00_rt(rt2x00dev, RT2883) && - !rt2x00_rt(rt2x00dev, RT2890) && - !rt2x00_rt(rt2x00dev, RT3052) && !rt2x00_rt(rt2x00dev, RT3070) && !rt2x00_rt(rt2x00dev, RT3071) && !rt2x00_rt(rt2x00dev, RT3090) && diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index d9daa9c406fa..16aa850d3700 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -177,16 +177,15 @@ struct rt2x00_chip { #define RT2573 0x2573 #define RT2860 0x2860 /* 2.4GHz PCI/CB */ #define RT2870 0x2870 -#define RT2872 0x2872 -#define RT2880 0x2880 /* WSOC */ +#define RT2872 0x2872 /* WSOC */ #define RT2883 0x2883 /* WSOC */ -#define RT2890 0x2890 /* 2.4GHz PCIe */ -#define RT3052 0x3052 /* WSOC */ #define RT3070 0x3070 #define RT3071 0x3071 #define RT3090 0x3090 /* 2.4GHz PCIe */ #define RT3390 0x3390 #define RT3572 0x3572 +#define RT3593 0x3593 /* PCIe */ +#define RT3883 0x3883 /* WSOC */ u16 rf; u16 rev; -- cgit v1.2.3 From 8d0c9b65c904c6943566ccd2919c6a5ee6292c6b Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sun, 11 Apr 2010 14:31:10 +0200 Subject: rt2x00: Refactor rt2800 version constants. The rt2800 version constants are inconsistent, and the version number don't mean a lot of things anyway. Refactor the constants to have some more meaningful names, and introduce and use some new helpers to check these chipset revisions. At the same time rename to revision, as they are more revision numbers rather than version numbers. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 18 +++++++++++------- drivers/net/wireless/rt2x00/rt2800lib.c | 30 ++++++++++-------------------- drivers/net/wireless/rt2x00/rt2x00.h | 22 ++++++++++++++++++++-- 3 files changed, 41 insertions(+), 29 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 4d5871b01cac..ec893721cc80 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -59,13 +59,17 @@ #define RF3320 0x000b /* - * Chipset version. - */ -#define RT2860C_VERSION 0x0100 -#define RT2860D_VERSION 0x0101 -#define RT2880E_VERSION 0x0200 -#define RT2883_VERSION 0x0300 -#define RT3070_VERSION 0x0200 + * Chipset revisions. + */ +#define REV_RT2860C 0x0100 +#define REV_RT2860D 0x0101 +#define REV_RT2870D 0x0101 +#define REV_RT2872E 0x0200 +#define REV_RT3070E 0x0200 +#define REV_RT3070F 0x0201 +#define REV_RT3071E 0x0211 +#define REV_RT3090E 0x0211 +#define REV_RT3390E 0x0211 /* * Signal information. diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 2ab88840a3e5..8a4ed7642bcf 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -896,8 +896,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); rt2800_bbp_write(rt2x00dev, 3, bbp); - if (rt2x00_rt(rt2x00dev, RT2860) && - (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) { + if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { if (conf_is_ht40(conf)) { rt2800_bbp_write(rt2x00dev, 69, 0x1a); rt2800_bbp_write(rt2x00dev, 70, 0x0a); @@ -1060,8 +1059,7 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) { if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { if (rt2x00_is_usb(rt2x00dev) && - rt2x00_rt(rt2x00dev, RT3070) && - (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) + rt2x00_rt_rev(rt2x00dev, RT3070, REV_RT3070E)) return 0x1c + (2 * rt2x00dev->lna_gain); else return 0x2e + rt2x00dev->lna_gain; @@ -1092,8 +1090,7 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner); void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, const u32 count) { - if (rt2x00_rt(rt2x00dev, RT2860) && - (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) + if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) return; /* @@ -1179,8 +1176,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); if (rt2x00_is_usb(rt2x00dev) && - rt2x00_rt(rt2x00dev, RT3070) && - (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) { + rt2x00_rt_rev(rt2x00dev, RT3070, REV_RT3070E)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); @@ -1207,11 +1203,9 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); - if ((rt2x00_rt(rt2x00dev, RT2872) && - (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION)) || + if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) || rt2x00_rt(rt2x00dev, RT2883) || - (rt2x00_rt(rt2x00dev, RT3070) && - (rt2x00_rev(rt2x00dev) < RT3070_VERSION))) + rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E)) rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); else rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); @@ -1490,14 +1484,12 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0x00); rt2800_bbp_write(rt2x00dev, 105, 0x05); - if (rt2x00_rt(rt2x00dev, RT2860) && - (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) { + if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { rt2800_bbp_write(rt2x00dev, 69, 0x16); rt2800_bbp_write(rt2x00dev, 73, 0x12); } - if (rt2x00_rt(rt2x00dev, RT2860) && - (rt2x00_rev(rt2x00dev) > RT2860D_VERSION)) + if (rt2x00_rt_rev_gte(rt2x00dev, RT2860, REV_RT2860D)) rt2800_bbp_write(rt2x00dev, 84, 0x19); if (rt2x00_rt(rt2x00dev, RT2872)) { @@ -1507,8 +1499,7 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) } if (rt2x00_is_usb(rt2x00dev) && - rt2x00_rt(rt2x00dev, RT3070) && - (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) { + rt2x00_rt_rev(rt2x00dev, RT3070, REV_RT3070E)) { rt2800_bbp_write(rt2x00dev, 70, 0x0a); rt2800_bbp_write(rt2x00dev, 84, 0x99); rt2800_bbp_write(rt2x00dev, 105, 0x05); @@ -1594,8 +1585,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) u8 bbp; if (rt2x00_is_usb(rt2x00dev) && - rt2x00_rt(rt2x00dev, RT3070) && - (rt2x00_rev(rt2x00dev) != RT3070_VERSION)) + !rt2x00_rt_rev(rt2x00dev, RT3070, REV_RT3070E)) return 0; if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 16aa850d3700..4de505b98331 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -929,12 +929,12 @@ static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); } -static inline char rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt) +static inline bool rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt) { return (rt2x00dev->chip.rt == rt); } -static inline char rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) +static inline bool rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) { return (rt2x00dev->chip.rf == rf); } @@ -944,6 +944,24 @@ static inline u16 rt2x00_rev(struct rt2x00_dev *rt2x00dev) return rt2x00dev->chip.rev; } +static inline bool rt2x00_rt_rev(struct rt2x00_dev *rt2x00dev, + const u16 rt, const u16 rev) +{ + return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) == rev); +} + +static inline bool rt2x00_rt_rev_lt(struct rt2x00_dev *rt2x00dev, + const u16 rt, const u16 rev) +{ + return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) < rev); +} + +static inline bool rt2x00_rt_rev_gte(struct rt2x00_dev *rt2x00dev, + const u16 rt, const u16 rev) +{ + return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) >= rev); +} + static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, enum rt2x00_chip_intf intf) { -- cgit v1.2.3 From a9dce1494af33534867b8c7fab7351274fd651ca Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sun, 11 Apr 2010 14:31:11 +0200 Subject: rt2x00: Align rt2800 register initialization with vendor driver. Align the rt2800 register initializations with the latest versions of the Ralink vendor driver. This patch is also preparation for the addition of support for RT3070 / RT3071 / RT3090 / RT3390 based devices. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 130 +++++++++++++++++++++++--------- drivers/net/wireless/rt2x00/rt2800pci.c | 13 ---- 2 files changed, 95 insertions(+), 48 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 8a4ed7642bcf..1890b9aea492 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -359,11 +359,6 @@ static int rt2800_blink_set(struct led_classdev *led_cdev, rt2800_register_read(led->rt2x00dev, LED_CFG, ®); rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); - rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); - rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); - rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 3); - rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); - rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); rt2800_register_write(led->rt2x00dev, LED_CFG, reg); return 0; @@ -609,10 +604,6 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp) { u32 reg; - rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); - rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20); - rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); - rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, !!erp->short_preamble); @@ -631,15 +622,12 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp) rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); - rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); - rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); - rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); @@ -984,10 +972,6 @@ static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev, libconf->conf->short_frame_max_tx_count); rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, libconf->conf->long_frame_max_tx_count); - rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); - rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); - rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); - rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg); } @@ -1110,6 +1094,14 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) u32 reg; unsigned int i; + 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); + if (rt2x00_is_usb(rt2x00dev)) { /* * Wait until BBP and RF are ready. @@ -1129,8 +1121,25 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); - } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) + } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { + /* + * Reset DMA indexes + */ + rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); + rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); + rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); + + rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); + rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); + rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); + } rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); @@ -1175,6 +1184,13 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + rt2800_config_filter(rt2x00dev, FIF_ALLMULTI); + + rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); + rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, 9); + rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); + rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); + if (rt2x00_is_usb(rt2x00dev) && rt2x00_rt_rev(rt2x00dev, RT3070, REV_RT3070E)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); @@ -1198,6 +1214,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); rt2x00_set_field32(®, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9); + rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 32); rt2x00_set_field32(®, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10); rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); @@ -1213,38 +1230,61 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 0); rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg); + rt2800_register_read(rt2x00dev, LED_CFG, ®); + rt2x00_set_field32(®, LED_CFG_ON_PERIOD, 70); + rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, 30); + rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); + rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); + rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 3); + rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); + rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); + rt2800_register_write(rt2x00dev, LED_CFG, reg); + rt2800_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f); + rt2800_register_read(rt2x00dev, TX_RTY_CFG, ®); + rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, 15); + rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, 31); + rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); + rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); + rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); + rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); + rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg); + rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); rt2x00_set_field32(®, AUTO_RSP_CFG_AUTORESPONDER, 1); + rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, 1); rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MMODE, 0); rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MREF, 0); + rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, 1); rt2x00_set_field32(®, AUTO_RSP_CFG_DUAL_CTS_EN, 0); rt2x00_set_field32(®, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0); rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg); rt2800_register_read(rt2x00dev, CCK_PROT_CFG, ®); - rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_RATE, 8); + rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_RATE, 3); rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_CTRL, 0); rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV, 1); rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1); rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1); rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1); - rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 0); rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1); - rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 0); + rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, 1); rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg); rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®); - rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_RATE, 8); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_RATE, 3); rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, 0); rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV, 1); rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1); rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1); rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1); - rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 0); rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1); - rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 0); + rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, 1); rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); rt2800_register_read(rt2x00dev, MM20_PROT_CFG, ®); @@ -1257,11 +1297,13 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0); rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1); rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0); + rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, 0); rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg); rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®); rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084); - rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, + !rt2x00_is_usb(rt2x00dev)); rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV, 1); rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1); rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); @@ -1269,6 +1311,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1); rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1); rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, 0); rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg); rt2800_register_read(rt2x00dev, GF20_PROT_CFG, ®); @@ -1281,6 +1324,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0); rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1); rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0); + rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, 0); rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg); rt2800_register_read(rt2x00dev, GF40_PROT_CFG, ®); @@ -1293,6 +1337,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1); rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1); rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, 0); rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg); if (rt2x00_is_usb(rt2x00dev)) { @@ -1322,6 +1367,15 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg); rt2800_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca); + + rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); + rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, 32); + rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, 32); + rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); + rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, 314); + rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); + rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); + rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); /* @@ -1471,26 +1525,32 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 65, 0x2c); rt2800_bbp_write(rt2x00dev, 66, 0x38); - rt2800_bbp_write(rt2x00dev, 69, 0x12); + + if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { + rt2800_bbp_write(rt2x00dev, 69, 0x16); + rt2800_bbp_write(rt2x00dev, 73, 0x12); + } else { + rt2800_bbp_write(rt2x00dev, 69, 0x12); + rt2800_bbp_write(rt2x00dev, 73, 0x10); + } + rt2800_bbp_write(rt2x00dev, 70, 0x0a); - rt2800_bbp_write(rt2x00dev, 73, 0x10); rt2800_bbp_write(rt2x00dev, 81, 0x37); rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 83, 0x6a); - rt2800_bbp_write(rt2x00dev, 84, 0x99); + + if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D) || + rt2x00_rt_rev(rt2x00dev, RT2870, REV_RT2870D)) + rt2800_bbp_write(rt2x00dev, 84, 0x19); + else + rt2800_bbp_write(rt2x00dev, 84, 0x99); + rt2800_bbp_write(rt2x00dev, 86, 0x00); rt2800_bbp_write(rt2x00dev, 91, 0x04); rt2800_bbp_write(rt2x00dev, 92, 0x00); rt2800_bbp_write(rt2x00dev, 103, 0x00); rt2800_bbp_write(rt2x00dev, 105, 0x05); - - if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { - rt2800_bbp_write(rt2x00dev, 69, 0x16); - rt2800_bbp_write(rt2x00dev, 73, 0x12); - } - - if (rt2x00_rt_rev_gte(rt2x00dev, RT2860, REV_RT2860D)) - rt2800_bbp_write(rt2x00dev, 84, 0x19); + rt2800_bbp_write(rt2x00dev, 106, 0x35); if (rt2x00_rt(rt2x00dev, RT2872)) { rt2800_bbp_write(rt2x00dev, 31, 0x08); diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index a2b37d38d400..2131f8f0c502 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -347,19 +347,6 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) struct queue_entry_priv_pci *entry_priv; u32 reg; - rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); - rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); - - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); - /* * Initialize registers. */ -- cgit v1.2.3 From 8cdd15e0063edbe002945ba93faf80e79c947610 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sun, 11 Apr 2010 14:31:12 +0200 Subject: rt2x00: Finish rt3070 support in rt2800 register initialization. rt2x00 had preliminary support for RT3070 based devices, but the support was incomplete. Update the RT3070 register initialization to be similar to the latest Ralink vendor driver. With this patch my rt3070 based devices start showing a sign of life. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 133 +++++++++++++++++--------------- 1 file changed, 71 insertions(+), 62 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 1890b9aea492..7d1cb7ea0952 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1042,8 +1042,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_stats); static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) { if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { - if (rt2x00_is_usb(rt2x00dev) && - rt2x00_rt_rev(rt2x00dev, RT3070, REV_RT3070E)) + if (rt2x00_rt(rt2x00dev, RT3070)) return 0x1c + (2 * rt2x00dev->lna_gain); else return 0x2e + rt2x00dev->lna_gain; @@ -1191,11 +1190,16 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); - if (rt2x00_is_usb(rt2x00dev) && - rt2x00_rt_rev(rt2x00dev, RT3070, REV_RT3070E)) { + if (rt2x00_rt(rt2x00dev, RT3070)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); - rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); - rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); + + if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000002c); + } else { + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); + } } else { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); @@ -1535,7 +1539,15 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) } rt2800_bbp_write(rt2x00dev, 70, 0x0a); - rt2800_bbp_write(rt2x00dev, 81, 0x37); + + if (rt2x00_rt(rt2x00dev, RT3070)) { + rt2800_bbp_write(rt2x00dev, 79, 0x13); + rt2800_bbp_write(rt2x00dev, 80, 0x05); + rt2800_bbp_write(rt2x00dev, 81, 0x33); + } else { + rt2800_bbp_write(rt2x00dev, 81, 0x37); + } + rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 83, 0x6a); @@ -1548,7 +1560,12 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 86, 0x00); rt2800_bbp_write(rt2x00dev, 91, 0x04); rt2800_bbp_write(rt2x00dev, 92, 0x00); - rt2800_bbp_write(rt2x00dev, 103, 0x00); + + if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F)) + rt2800_bbp_write(rt2x00dev, 103, 0xc0); + else + rt2800_bbp_write(rt2x00dev, 103, 0x00); + rt2800_bbp_write(rt2x00dev, 105, 0x05); rt2800_bbp_write(rt2x00dev, 106, 0x35); @@ -1558,13 +1575,6 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 80, 0x08); } - if (rt2x00_is_usb(rt2x00dev) && - rt2x00_rt_rev(rt2x00dev, RT3070, REV_RT3070E)) { - rt2800_bbp_write(rt2x00dev, 70, 0x0a); - rt2800_bbp_write(rt2x00dev, 84, 0x99); - rt2800_bbp_write(rt2x00dev, 105, 0x05); - } - for (i = 0; i < EEPROM_BBP_SIZE; i++) { rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); @@ -1643,18 +1653,12 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) { u8 rfcsr; u8 bbp; + u32 reg; + u16 eeprom; - if (rt2x00_is_usb(rt2x00dev) && - !rt2x00_rt_rev(rt2x00dev, RT3070, REV_RT3070E)) + if (!rt2x00_rt(rt2x00dev, RT3070)) return 0; - if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { - if (!rt2x00_rf(rt2x00dev, RF3020) && - !rt2x00_rf(rt2x00dev, RF3021) && - !rt2x00_rf(rt2x00dev, RF3022)) - return 0; - } - /* * Init RF calibration. */ @@ -1665,13 +1669,13 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); - if (rt2x00_is_usb(rt2x00dev)) { + if (rt2x00_rt(rt2x00dev, RT3070)) { rt2800_rfcsr_write(rt2x00dev, 4, 0x40); rt2800_rfcsr_write(rt2x00dev, 5, 0x03); rt2800_rfcsr_write(rt2x00dev, 6, 0x02); rt2800_rfcsr_write(rt2x00dev, 7, 0x70); rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); - rt2800_rfcsr_write(rt2x00dev, 10, 0x71); + rt2800_rfcsr_write(rt2x00dev, 10, 0x41); rt2800_rfcsr_write(rt2x00dev, 11, 0x21); rt2800_rfcsr_write(rt2x00dev, 12, 0x7b); rt2800_rfcsr_write(rt2x00dev, 14, 0x90); @@ -1684,48 +1688,25 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); rt2800_rfcsr_write(rt2x00dev, 24, 0x16); rt2800_rfcsr_write(rt2x00dev, 25, 0x01); - rt2800_rfcsr_write(rt2x00dev, 27, 0x03); rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); - } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { - rt2800_rfcsr_write(rt2x00dev, 0, 0x50); - rt2800_rfcsr_write(rt2x00dev, 1, 0x01); - rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); - rt2800_rfcsr_write(rt2x00dev, 3, 0x75); - rt2800_rfcsr_write(rt2x00dev, 4, 0x40); - rt2800_rfcsr_write(rt2x00dev, 5, 0x03); - rt2800_rfcsr_write(rt2x00dev, 6, 0x02); - rt2800_rfcsr_write(rt2x00dev, 7, 0x50); - rt2800_rfcsr_write(rt2x00dev, 8, 0x39); - rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); - rt2800_rfcsr_write(rt2x00dev, 10, 0x60); - rt2800_rfcsr_write(rt2x00dev, 11, 0x21); - rt2800_rfcsr_write(rt2x00dev, 12, 0x75); - rt2800_rfcsr_write(rt2x00dev, 13, 0x75); - rt2800_rfcsr_write(rt2x00dev, 14, 0x90); - rt2800_rfcsr_write(rt2x00dev, 15, 0x58); - rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); - rt2800_rfcsr_write(rt2x00dev, 17, 0x92); - rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); - rt2800_rfcsr_write(rt2x00dev, 19, 0x02); - rt2800_rfcsr_write(rt2x00dev, 20, 0xba); - rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); - rt2800_rfcsr_write(rt2x00dev, 22, 0x00); - rt2800_rfcsr_write(rt2x00dev, 23, 0x31); - rt2800_rfcsr_write(rt2x00dev, 24, 0x08); - rt2800_rfcsr_write(rt2x00dev, 25, 0x01); - rt2800_rfcsr_write(rt2x00dev, 26, 0x25); - rt2800_rfcsr_write(rt2x00dev, 27, 0x23); - rt2800_rfcsr_write(rt2x00dev, 28, 0x13); - rt2800_rfcsr_write(rt2x00dev, 29, 0x83); + } + + if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { + rt2800_register_read(rt2x00dev, LDO_CFG0, ®); + rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); + rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); + rt2800_register_write(rt2x00dev, LDO_CFG0, reg); } /* * Set RX Filter calibration for 20MHz and 40MHz */ - rt2x00dev->calibration[0] = - rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16); - rt2x00dev->calibration[1] = - rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19); + if (rt2x00_rt(rt2x00dev, RT3070)) { + rt2x00dev->calibration[0] = + rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16); + rt2x00dev->calibration[1] = + rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19); + } /* * Set back to initial state @@ -1743,6 +1724,34 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0); rt2800_bbp_write(rt2x00dev, 4, bbp); + if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) + rt2800_rfcsr_write(rt2x00dev, 27, 0x03); + + rt2800_register_read(rt2x00dev, OPT_14_CSR, ®); + rt2x00_set_field32(®, OPT_14_CSR_BIT0, 1); + rt2800_register_write(rt2x00dev, OPT_14_CSR, reg); + + rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0); + rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_TXMIXER_GAIN_BG_VAL) >= 1) + rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN, + rt2x00_get_field16(eeprom, + EEPROM_TXMIXER_GAIN_BG_VAL)); + rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); + + if (rt2x00_rt(rt2x00dev, RT3070)) { + rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr); + if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) + rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3); + else + rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0); + rt2x00_set_field8(&rfcsr, RFCSR27_R2, 0); + rt2x00_set_field8(&rfcsr, RFCSR27_R3, 0); + rt2x00_set_field8(&rfcsr, RFCSR27_R4, 0); + rt2800_rfcsr_write(rt2x00dev, 27, rfcsr); + } + return 0; } EXPORT_SYMBOL_GPL(rt2800_init_rfcsr); -- cgit v1.2.3 From d5385bfc59c737d1eae77cc48d662daf4ddddae8 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sun, 11 Apr 2010 14:31:13 +0200 Subject: rt2x00: Add rt3071 support in rt2800 register initialization. Add RT3071 specific register initializations to rt2x00, based on the latest Ralink rt3070 vendor driver. With this patch my RT3071 based devices start showing a sign of life. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 102 +++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 7d1cb7ea0952..fe7171f408ba 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1042,7 +1042,8 @@ EXPORT_SYMBOL_GPL(rt2800_link_stats); static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) { if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { - if (rt2x00_rt(rt2x00dev, RT3070)) + if (rt2x00_rt(rt2x00dev, RT3070) || + rt2x00_rt(rt2x00dev, RT3071)) return 0x1c + (2 * rt2x00dev->lna_gain); else return 0x2e + rt2x00dev->lna_gain; @@ -1091,6 +1092,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner); int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) { u32 reg; + u16 eeprom; unsigned int i; rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); @@ -1190,7 +1192,22 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); - if (rt2x00_rt(rt2x00dev, RT3070)) { + if (rt2x00_rt(rt2x00dev, RT3071)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); + if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E)) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) + rt2800_register_write(rt2x00dev, TX_SW_CFG2, + 0x0000002c); + else + rt2800_register_write(rt2x00dev, TX_SW_CFG2, + 0x0000000f); + } else { + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); + } + rt2800_register_write(rt2x00dev, TX_SW_CFG2, reg); + } else if (rt2x00_rt(rt2x00dev, RT3070)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { @@ -1540,7 +1557,8 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 70, 0x0a); - if (rt2x00_rt(rt2x00dev, RT3070)) { + if (rt2x00_rt(rt2x00dev, RT3070) || + rt2x00_rt(rt2x00dev, RT3071)) { rt2800_bbp_write(rt2x00dev, 79, 0x13); rt2800_bbp_write(rt2x00dev, 80, 0x05); rt2800_bbp_write(rt2x00dev, 81, 0x33); @@ -1561,7 +1579,8 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 91, 0x04); rt2800_bbp_write(rt2x00dev, 92, 0x00); - if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F)) + if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) || + rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E)) rt2800_bbp_write(rt2x00dev, 103, 0xc0); else rt2800_bbp_write(rt2x00dev, 103, 0x00); @@ -1569,6 +1588,18 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 105, 0x05); rt2800_bbp_write(rt2x00dev, 106, 0x35); + if (rt2x00_rt(rt2x00dev, RT3071)) { + rt2800_bbp_read(rt2x00dev, 138, &value); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) + value |= 0x20; + if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) + value &= ~0x02; + + rt2800_bbp_write(rt2x00dev, 138, value); + } + if (rt2x00_rt(rt2x00dev, RT2872)) { rt2800_bbp_write(rt2x00dev, 31, 0x08); rt2800_bbp_write(rt2x00dev, 78, 0x0e); @@ -1656,7 +1687,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) u32 reg; u16 eeprom; - if (!rt2x00_rt(rt2x00dev, RT3070)) + if (!rt2x00_rt(rt2x00dev, RT3070) && + !rt2x00_rt(rt2x00dev, RT3071)) return 0; /* @@ -1669,7 +1701,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); - if (rt2x00_rt(rt2x00dev, RT3070)) { + if (rt2x00_rt(rt2x00dev, RT3070) || + rt2x00_rt(rt2x00dev, RT3071)) { rt2800_rfcsr_write(rt2x00dev, 4, 0x40); rt2800_rfcsr_write(rt2x00dev, 5, 0x03); rt2800_rfcsr_write(rt2x00dev, 6, 0x02); @@ -1696,6 +1729,23 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); rt2800_register_write(rt2x00dev, LDO_CFG0, reg); + } else if (rt2x00_rt(rt2x00dev, RT3071)) { + rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1); + rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + + rt2800_rfcsr_write(rt2x00dev, 31, 0x14); + + rt2800_register_read(rt2x00dev, LDO_CFG0, ®); + rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); + if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E)) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) + rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); + else + rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); + } + rt2800_register_write(rt2x00dev, LDO_CFG0, reg); } /* @@ -1706,6 +1756,11 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16); rt2x00dev->calibration[1] = rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19); + } else if (rt2x00_rt(rt2x00dev, RT3071)) { + rt2x00dev->calibration[0] = + rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13); + rt2x00dev->calibration[1] = + rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x15); } /* @@ -1724,7 +1779,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0); rt2800_bbp_write(rt2x00dev, 4, bbp); - if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) + if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || + rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E)) rt2800_rfcsr_write(rt2x00dev, 27, 0x03); rt2800_register_read(rt2x00dev, OPT_14_CSR, ®); @@ -1733,6 +1789,11 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0); + if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E)) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) + rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); + } rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_TXMIXER_GAIN_BG_VAL) >= 1) rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN, @@ -1740,9 +1801,32 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) EEPROM_TXMIXER_GAIN_BG_VAL)); rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); - if (rt2x00_rt(rt2x00dev, RT3070)) { + if (rt2x00_rt(rt2x00dev, RT3071)) { + rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); + rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); + rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); + rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 15, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR15_TX_LO2_EN, 0); + rt2800_rfcsr_write(rt2x00dev, 15, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR20_RX_LO1_EN, 0); + rt2800_rfcsr_write(rt2x00dev, 20, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR21_RX_LO2_EN, 0); + rt2800_rfcsr_write(rt2x00dev, 21, rfcsr); + } + + if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071)) { rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr); - if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) + if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || + rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E)) rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3); else rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0); -- cgit v1.2.3 From 64522957ce35df995dfd73bee548304f2a39cc3e Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sun, 11 Apr 2010 14:31:14 +0200 Subject: rt2x00: Add rt3090 support in rt2800 register initialization. Add RT3090 specific register initializations to rt2x00, based on the latest Ralink rt3090 vendor driver. Untested as I don't actually own an RT3090 based device, but given experiences on rt3070/rt3071 very hopeful that this will actually work.. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 54 ++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 14 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index fe7171f408ba..d74608228a99 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1043,7 +1043,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) { if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { if (rt2x00_rt(rt2x00dev, RT3070) || - rt2x00_rt(rt2x00dev, RT3071)) + rt2x00_rt(rt2x00dev, RT3071) || + rt2x00_rt(rt2x00dev, RT3090)) return 0x1c + (2 * rt2x00dev->lna_gain); else return 0x2e + rt2x00dev->lna_gain; @@ -1192,10 +1193,12 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); - if (rt2x00_rt(rt2x00dev, RT3071)) { + if (rt2x00_rt(rt2x00dev, RT3071) || + rt2x00_rt(rt2x00dev, RT3090)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); - if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E)) { + if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || + rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) { rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) rt2800_register_write(rt2x00dev, TX_SW_CFG2, @@ -1558,7 +1561,8 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 70, 0x0a); if (rt2x00_rt(rt2x00dev, RT3070) || - rt2x00_rt(rt2x00dev, RT3071)) { + rt2x00_rt(rt2x00dev, RT3071) || + rt2x00_rt(rt2x00dev, RT3090)) { rt2800_bbp_write(rt2x00dev, 79, 0x13); rt2800_bbp_write(rt2x00dev, 80, 0x05); rt2800_bbp_write(rt2x00dev, 81, 0x33); @@ -1580,7 +1584,8 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 92, 0x00); if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) || - rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E)) + rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) || + rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E)) rt2800_bbp_write(rt2x00dev, 103, 0xc0); else rt2800_bbp_write(rt2x00dev, 103, 0x00); @@ -1588,7 +1593,8 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 105, 0x05); rt2800_bbp_write(rt2x00dev, 106, 0x35); - if (rt2x00_rt(rt2x00dev, RT3071)) { + if (rt2x00_rt(rt2x00dev, RT3071) || + rt2x00_rt(rt2x00dev, RT3090)) { rt2800_bbp_read(rt2x00dev, 138, &value); rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); @@ -1688,7 +1694,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) u16 eeprom; if (!rt2x00_rt(rt2x00dev, RT3070) && - !rt2x00_rt(rt2x00dev, RT3071)) + !rt2x00_rt(rt2x00dev, RT3071) && + !rt2x00_rt(rt2x00dev, RT3090)) return 0; /* @@ -1702,7 +1709,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); if (rt2x00_rt(rt2x00dev, RT3070) || - rt2x00_rt(rt2x00dev, RT3071)) { + rt2x00_rt(rt2x00dev, RT3071) || + rt2x00_rt(rt2x00dev, RT3090)) { rt2800_rfcsr_write(rt2x00dev, 4, 0x40); rt2800_rfcsr_write(rt2x00dev, 5, 0x03); rt2800_rfcsr_write(rt2x00dev, 6, 0x02); @@ -1729,7 +1737,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); rt2800_register_write(rt2x00dev, LDO_CFG0, reg); - } else if (rt2x00_rt(rt2x00dev, RT3071)) { + } else if (rt2x00_rt(rt2x00dev, RT3071) || + rt2x00_rt(rt2x00dev, RT3090)) { rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1); rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); @@ -1738,7 +1747,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_register_read(rt2x00dev, LDO_CFG0, ®); rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); - if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E)) { + if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || + rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) { rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); @@ -1756,7 +1766,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16); rt2x00dev->calibration[1] = rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19); - } else if (rt2x00_rt(rt2x00dev, RT3071)) { + } else if (rt2x00_rt(rt2x00dev, RT3071) || + rt2x00_rt(rt2x00dev, RT3090)) { rt2x00dev->calibration[0] = rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13); rt2x00dev->calibration[1] = @@ -1780,7 +1791,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 4, bbp); if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || - rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E)) + rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || + rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) rt2800_rfcsr_write(rt2x00dev, 27, 0x03); rt2800_register_read(rt2x00dev, OPT_14_CSR, ®); @@ -1789,7 +1801,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0); - if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E)) { + if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || + rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) { rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); @@ -1801,7 +1814,20 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) EEPROM_TXMIXER_GAIN_BG_VAL)); rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); - if (rt2x00_rt(rt2x00dev, RT3071)) { + if (rt2x00_rt(rt2x00dev, RT3090)) { + rt2800_bbp_read(rt2x00dev, 138, &bbp); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) + rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0); + if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) + rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1); + + rt2800_bbp_write(rt2x00dev, 138, bbp); + } + + if (rt2x00_rt(rt2x00dev, RT3071) || + rt2x00_rt(rt2x00dev, RT3090)) { rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); -- cgit v1.2.3 From cc78e904bd960196233e2cd6a49068bba8787527 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sun, 11 Apr 2010 14:31:15 +0200 Subject: rt2x00: Add rt3390 support in rt2800 register initialization. Add RT3390 specific register initializations to rt2x00, based on the latest Ralink rt3390 vendor driver. Untested as I don't actually own an RT3390 based device, but given experiences on rt3070/rt3071 very hopeful that this will actually work.. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 70 +++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index d74608228a99..638600092f19 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1044,7 +1044,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071) || - rt2x00_rt(rt2x00dev, RT3090)) + rt2x00_rt(rt2x00dev, RT3090) || + rt2x00_rt(rt2x00dev, RT3390)) return 0x1c + (2 * rt2x00dev->lna_gain); else return 0x2e + rt2x00dev->lna_gain; @@ -1194,11 +1195,13 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); if (rt2x00_rt(rt2x00dev, RT3071) || - rt2x00_rt(rt2x00dev, RT3090)) { + rt2x00_rt(rt2x00dev, RT3090) || + rt2x00_rt(rt2x00dev, RT3390)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || - rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) { + rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || + rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) rt2800_register_write(rt2x00dev, TX_SW_CFG2, @@ -1562,7 +1565,8 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071) || - rt2x00_rt(rt2x00dev, RT3090)) { + rt2x00_rt(rt2x00dev, RT3090) || + rt2x00_rt(rt2x00dev, RT3390)) { rt2800_bbp_write(rt2x00dev, 79, 0x13); rt2800_bbp_write(rt2x00dev, 80, 0x05); rt2800_bbp_write(rt2x00dev, 81, 0x33); @@ -1585,7 +1589,8 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) || rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) || - rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E)) + rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) || + rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E)) rt2800_bbp_write(rt2x00dev, 103, 0xc0); else rt2800_bbp_write(rt2x00dev, 103, 0x00); @@ -1594,7 +1599,8 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 106, 0x35); if (rt2x00_rt(rt2x00dev, RT3071) || - rt2x00_rt(rt2x00dev, RT3090)) { + rt2x00_rt(rt2x00dev, RT3090) || + rt2x00_rt(rt2x00dev, RT3390)) { rt2800_bbp_read(rt2x00dev, 138, &value); rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); @@ -1695,7 +1701,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) if (!rt2x00_rt(rt2x00dev, RT3070) && !rt2x00_rt(rt2x00dev, RT3071) && - !rt2x00_rt(rt2x00dev, RT3090)) + !rt2x00_rt(rt2x00dev, RT3090) && + !rt2x00_rt(rt2x00dev, RT3390)) return 0; /* @@ -1730,6 +1737,39 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 24, 0x16); rt2800_rfcsr_write(rt2x00dev, 25, 0x01); rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); + } else if (rt2x00_rt(rt2x00dev, RT3390)) { + rt2800_rfcsr_write(rt2x00dev, 0, 0xa0); + rt2800_rfcsr_write(rt2x00dev, 1, 0xe1); + rt2800_rfcsr_write(rt2x00dev, 2, 0xf1); + rt2800_rfcsr_write(rt2x00dev, 3, 0x62); + rt2800_rfcsr_write(rt2x00dev, 4, 0x40); + rt2800_rfcsr_write(rt2x00dev, 5, 0x8b); + rt2800_rfcsr_write(rt2x00dev, 6, 0x42); + rt2800_rfcsr_write(rt2x00dev, 7, 0x34); + rt2800_rfcsr_write(rt2x00dev, 8, 0x00); + rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); + rt2800_rfcsr_write(rt2x00dev, 10, 0x61); + rt2800_rfcsr_write(rt2x00dev, 11, 0x21); + rt2800_rfcsr_write(rt2x00dev, 12, 0x3b); + rt2800_rfcsr_write(rt2x00dev, 13, 0xe0); + rt2800_rfcsr_write(rt2x00dev, 14, 0x90); + rt2800_rfcsr_write(rt2x00dev, 15, 0x53); + rt2800_rfcsr_write(rt2x00dev, 16, 0xe0); + rt2800_rfcsr_write(rt2x00dev, 17, 0x94); + rt2800_rfcsr_write(rt2x00dev, 18, 0x5c); + rt2800_rfcsr_write(rt2x00dev, 19, 0x4a); + rt2800_rfcsr_write(rt2x00dev, 20, 0xb2); + rt2800_rfcsr_write(rt2x00dev, 21, 0xf6); + rt2800_rfcsr_write(rt2x00dev, 22, 0x00); + rt2800_rfcsr_write(rt2x00dev, 23, 0x14); + rt2800_rfcsr_write(rt2x00dev, 24, 0x08); + rt2800_rfcsr_write(rt2x00dev, 25, 0x3d); + rt2800_rfcsr_write(rt2x00dev, 26, 0x85); + rt2800_rfcsr_write(rt2x00dev, 27, 0x00); + rt2800_rfcsr_write(rt2x00dev, 28, 0x41); + rt2800_rfcsr_write(rt2x00dev, 29, 0x8f); + rt2800_rfcsr_write(rt2x00dev, 30, 0x20); + rt2800_rfcsr_write(rt2x00dev, 31, 0x0f); } if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { @@ -1756,6 +1796,10 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); } rt2800_register_write(rt2x00dev, LDO_CFG0, reg); + } else if (rt2x00_rt(rt2x00dev, RT3390)) { + rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); + rt2x00_set_field32(®, GPIO_SWITCH_5, 0); + rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); } /* @@ -1767,7 +1811,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2x00dev->calibration[1] = rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19); } else if (rt2x00_rt(rt2x00dev, RT3071) || - rt2x00_rt(rt2x00dev, RT3090)) { + rt2x00_rt(rt2x00dev, RT3090) || + rt2x00_rt(rt2x00dev, RT3390)) { rt2x00dev->calibration[0] = rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13); rt2x00dev->calibration[1] = @@ -1792,7 +1837,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || - rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) + rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || + rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) rt2800_rfcsr_write(rt2x00dev, 27, 0x03); rt2800_register_read(rt2x00dev, OPT_14_CSR, ®); @@ -1802,7 +1848,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0); if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || - rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) { + rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || + rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); @@ -1827,7 +1874,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) } if (rt2x00_rt(rt2x00dev, RT3071) || - rt2x00_rt(rt2x00dev, RT3090)) { + rt2x00_rt(rt2x00dev, RT3090) || + rt2x00_rt(rt2x00dev, RT3390)) { rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); -- cgit v1.2.3 From 0edc9a6709d8e7d4f26c7f2a4b5ebdb641f8dfa0 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Mon, 12 Apr 2010 16:38:47 +0900 Subject: ath5k: Use high bitrates for ACK/CTS There was a confusion in the usage of the bits AR5K_STA_ID1_ACKCTS_6MB and AR5K_STA_ID1_BASE_RATE_11B. If they are set (1), we will get lower bitrates for ACK and CTS. Therefore ath5k_hw_set_ack_bitrate_high(ah, false) actually resulted in high bitrates, which i think is what we want anyways. Cleared the confusion and added some documentation. Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 3 +-- drivers/net/wireless/ath/ath5k/pcu.c | 4 ++-- drivers/net/wireless/ath/ath5k/reg.h | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index f7f57c1cca7d..3f59bc2d7912 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2558,8 +2558,7 @@ ath5k_init(struct ath5k_softc *sc) for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) ath5k_hw_reset_key(ah, i); - /* Set ack to be sent at low bit-rates */ - ath5k_hw_set_ack_bitrate_high(ah, false); + ath5k_hw_set_ack_bitrate_high(ah, true); ret = 0; done: mmiowb(); diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 710870ea179b..174412fc81f8 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -154,9 +154,9 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) else { u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; if (high) - AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); - else AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); + else + AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); } } diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 45d62e915e4c..55b4ac6d236f 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -1139,8 +1139,8 @@ #define AR5K_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */ #define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */ #define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS */ -#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS */ -#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate for ACK/CTS [5211+] */ +#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Rate to use for ACK/CTS. 0: highest mandatory rate <= RX rate; 1: 1Mbps in B mode */ +#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* 802.11b base rate. 0: 1, 2, 5.5 and 11Mbps; 1: 1 and 2Mbps. [5211+] */ #define AR5K_STA_ID1_SELFGEN_DEF_ANT 0x04000000 /* Use def. antenna for self generated frames */ #define AR5K_STA_ID1_CRYPT_MIC_EN 0x08000000 /* Enable MIC */ #define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Look up key when key id != 0 */ -- cgit v1.2.3 From 87d77c4ef132599eb3a6c49520719d39f7341efd Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Mon, 12 Apr 2010 16:38:52 +0900 Subject: ath5k: treat RXORN as non-fatal We get RXORN interrupts when all receive buffers are full. This is not necessarily a fatal situation. It can also happen when the bus is busy or the CPU is not fast enough to process all frames. Older chipsets apparently need a reset to come out of this situration, but on newer chips we can treat RXORN like RX, as going thru a full reset does more harm than good, there. The exact chip revisions which need a reset are unknown - this guess AR5K_SREV_AR5212 ("venice") is copied from the HAL. Inspired by openwrt 413-rxorn.patch: "treat rxorn like rx, reset after rxorn seems to do more harm than good" Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 15 ++++++++++++++- drivers/net/wireless/ath/ath5k/base.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 3f59bc2d7912..92327423325f 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2705,7 +2705,20 @@ ath5k_intr(int irq, void *dev_id) */ tasklet_schedule(&sc->restq); } else if (unlikely(status & AR5K_INT_RXORN)) { - tasklet_schedule(&sc->restq); + /* + * Receive buffers are full. Either the bus is busy or + * the CPU is not fast enough to process all received + * frames. + * Older chipsets need a reset to come out of this + * condition, but we treat it as RX for newer chips. + * We don't know exactly which versions need a reset - + * this guess is copied from the HAL. + */ + sc->stats.rxorn_intr++; + if (ah->ah_mac_srev < AR5K_SREV_AR5212) + tasklet_schedule(&sc->restq); + else + tasklet_schedule(&sc->rxtq); } else { if (status & AR5K_INT_SWBA) { tasklet_hi_schedule(&sc->beacontq); diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 53a5651c57a2..56221bc7c8cd 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -135,6 +135,7 @@ struct ath5k_statistics { unsigned int beacons; unsigned int mib_intr; + unsigned int rxorn_intr; }; #if CHAN_DEBUG -- cgit v1.2.3 From f28a7b30cdaa936bdbdc0a2018241936fb56cae6 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 13 Apr 2010 00:28:53 +0800 Subject: ath9k-htc:respect usb buffer cacheline alignment in ath9k_hif_usb_alloc_rx_urbs In ath9k_hif_usb_alloc_rx_urbs, ath9k-htc will pass skb->data into usb hcd and usb hcd will do dma mapping and unmapping to the buffer pointed by skb->data, so we should pass a cache-line aligned address. This patch replace __dev_alloc_skb with alloc_skb to make skb->data pointed to a cacheline aligned address simply since ath9k-htc does not skb_push on the skb and pass it to mac80211, also use kfree_skb to free the skbs allocated by alloc_skb(we can use kfree_skb safely in hardirq context since skb->destructor is NULL always in the path). Signed-off-by: Ming Lei Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index e2117e7222e7..178b11a8403a 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -467,7 +467,7 @@ resubmit: return; free: - dev_kfree_skb_any(skb); + kfree_skb(skb); } static void ath9k_hif_usb_reg_in_cb(struct urb *urb) @@ -625,7 +625,7 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) } /* Allocate buffer */ - skb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL); + skb = alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL); if (!skb) { ret = -ENOMEM; goto err_skb; @@ -657,7 +657,7 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) return 0; err_submit: - dev_kfree_skb_any(skb); + kfree_skb(skb); err_skb: usb_free_urb(urb); err_urb: -- cgit v1.2.3 From e6c6d33cb7d18721e56ce4bb5a0e22593956ef14 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 13 Apr 2010 00:29:05 +0800 Subject: ath9k-htc:respect usb buffer cacheline alignment in reg in path In ath9k-htc register in path, ath9k-htc will pass skb->data into usb hcd and usb hcd will do dma mapping and unmapping to the buffer pointed by skb->data, so we should pass a cache-line aligned address. This patch replace __dev_alloc_skb with alloc_skb to make skb->data pointed to a cacheline aligned address simply since ath9k-htc does not skb_push on the skb and pass it to mac80211, also use kfree_skb to free the skb allocated by alloc_skb(we can use kfree_skb safely in hardirq context since skb->destructor is NULL always in the path). Signed-off-by: Ming Lei Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 10 +++++----- drivers/net/wireless/ath/ath9k/htc_hst.c | 7 +++++-- drivers/net/wireless/ath/ath9k/wmi.c | 4 ++-- 3 files changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 178b11a8403a..259de170ea25 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -499,7 +499,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) if (likely(urb->actual_length != 0)) { skb_put(skb, urb->actual_length); - nskb = __dev_alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); + nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); if (!nskb) goto resubmit; @@ -510,7 +510,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret) { - dev_kfree_skb_any(nskb); + kfree_skb(nskb); goto free; } @@ -530,7 +530,7 @@ resubmit: return; free: - dev_kfree_skb_any(skb); + kfree_skb(skb); urb->context = NULL; } @@ -670,7 +670,7 @@ static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev) if (hif_dev->reg_in_urb) { usb_kill_urb(hif_dev->reg_in_urb); if (hif_dev->reg_in_urb->context) - dev_kfree_skb_any((void *)hif_dev->reg_in_urb->context); + kfree_skb((void *)hif_dev->reg_in_urb->context); usb_free_urb(hif_dev->reg_in_urb); hif_dev->reg_in_urb = NULL; } @@ -684,7 +684,7 @@ static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev) if (hif_dev->reg_in_urb == NULL) return -ENOMEM; - skb = __dev_alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); + skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); if (!skb) goto err; diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 24d7b886fe23..d1fa5bd6bdbb 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -374,7 +374,10 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, epid = htc_hdr->endpoint_id; if (epid >= ENDPOINT_MAX) { - dev_kfree_skb_any(skb); + if (pipe_id != USB_REG_IN_PIPE) + dev_kfree_skb_any(skb); + else + kfree_skb(skb); return; } @@ -403,7 +406,7 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, break; } - dev_kfree_skb_any(skb); + kfree_skb(skb); } else { if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 818dea0164ec..acb66544a2aa 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -169,7 +169,7 @@ void ath9k_wmi_tasklet(unsigned long data) break; } - dev_kfree_skb_any(skb); + kfree_skb(skb); } static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) @@ -207,7 +207,7 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, ath9k_wmi_rsp_callback(wmi, skb); free_skb: - dev_kfree_skb_any(skb); + kfree_skb(skb); } static void ath9k_wmi_ctrl_tx(void *priv, struct sk_buff *skb, -- cgit v1.2.3 From 0fa35a5836df2b8f285d6f53dfb4316c34621f88 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 13 Apr 2010 00:29:15 +0800 Subject: ath9k-htc:respect usb buffer cacheline alignment in reg out path In ath9k-htc register out path, ath9k-htc will pass skb->data into usb hcd and usb hcd will do dma mapping and unmapping to the buffer pointed by skb->data, so we should pass a cache-line aligned address. This patch replace __dev_alloc_skb with alloc_skb to make skb->data pointed to a cacheline aligned address simply since ath9k-htc does not skb_push on the skb and pass it to mac80211, also use kfree_skb to free the skb allocated by alloc_skb(we can use kfree_skb safely in hardirq context since skb->destructor is NULL always in the path). Signed-off-by: Sujith Signed-off-by: Ming Lei Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 2 +- drivers/net/wireless/ath/ath9k/htc_hst.c | 21 ++++++++++++--------- drivers/net/wireless/ath/ath9k/wmi.c | 6 +++--- 3 files changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 259de170ea25..3d8f0f468f8d 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -53,7 +53,7 @@ static void hif_usb_regout_cb(struct urb *urb) return; free: - dev_kfree_skb_any(cmd->skb); + kfree_skb(cmd->skb); kfree(cmd); } diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index d1fa5bd6bdbb..587d98ed0989 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -146,7 +146,7 @@ static int htc_config_pipe_credits(struct htc_target *target) struct htc_config_pipe_msg *cp_msg; int ret, time_left; - skb = dev_alloc_skb(50 + sizeof(struct htc_frame_hdr)); + skb = alloc_skb(50 + sizeof(struct htc_frame_hdr), GFP_ATOMIC); if (!skb) { dev_err(target->dev, "failed to allocate send buffer\n"); return -ENOMEM; @@ -174,7 +174,7 @@ static int htc_config_pipe_credits(struct htc_target *target) return 0; err: - dev_kfree_skb(skb); + kfree_skb(skb); return -EINVAL; } @@ -184,7 +184,7 @@ static int htc_setup_complete(struct htc_target *target) struct htc_comp_msg *comp_msg; int ret = 0, time_left; - skb = dev_alloc_skb(50 + sizeof(struct htc_frame_hdr)); + skb = alloc_skb(50 + sizeof(struct htc_frame_hdr), GFP_ATOMIC); if (!skb) { dev_err(target->dev, "failed to allocate send buffer\n"); return -ENOMEM; @@ -210,7 +210,7 @@ static int htc_setup_complete(struct htc_target *target) return 0; err: - dev_kfree_skb(skb); + kfree_skb(skb); return -EINVAL; } @@ -250,8 +250,8 @@ int htc_connect_service(struct htc_target *target, endpoint->dl_pipeid = service_to_dlpipe(service_connreq->service_id); endpoint->ep_callbacks = service_connreq->ep_callbacks; - skb = dev_alloc_skb(sizeof(struct htc_conn_svc_msg) + - sizeof(struct htc_frame_hdr)); + skb = alloc_skb(sizeof(struct htc_conn_svc_msg) + + sizeof(struct htc_frame_hdr), GFP_ATOMIC); if (!skb) { dev_err(target->dev, "Failed to allocate buf to send" "service connect req\n"); @@ -282,7 +282,7 @@ int htc_connect_service(struct htc_target *target, *conn_rsp_epid = target->conn_rsp_epid; return 0; err: - dev_kfree_skb(skb); + kfree_skb(skb); return ret; } @@ -321,7 +321,7 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, struct sk_buff *skb, bool txok) { struct htc_endpoint *endpoint; - struct htc_frame_hdr *htc_hdr; + struct htc_frame_hdr *htc_hdr = NULL; if (htc_handle->htc_flags & HTC_OP_CONFIG_PIPE_CREDITS) { complete(&htc_handle->cmd_wait); @@ -349,7 +349,10 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, return; ret: /* HTC-generated packets are freed here. */ - dev_kfree_skb_any(skb); + if (htc_hdr && htc_hdr->endpoint_id != ENDPOINT0) + dev_kfree_skb_any(skb); + else + kfree_skb(skb); } /* diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index acb66544a2aa..f2ff18cf3e60 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -213,7 +213,7 @@ free_skb: static void ath9k_wmi_ctrl_tx(void *priv, struct sk_buff *skb, enum htc_endpoint_id epid, bool txok) { - dev_kfree_skb_any(skb); + kfree_skb(skb); } int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi, @@ -269,7 +269,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, if (!wmi) return -EINVAL; - skb = dev_alloc_skb(headroom + cmd_len); + skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC); if (!skb) return -ENOMEM; @@ -313,7 +313,7 @@ out: ath_print(common, ATH_DBG_WMI, "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id)); mutex_unlock(&wmi->op_mutex); - dev_kfree_skb_any(skb); + kfree_skb(skb); return ret; } -- cgit v1.2.3 From f8e1d0803d2db9ef0116941a4ce46069a2009ea6 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 13 Apr 2010 00:29:27 +0800 Subject: ath9k-htc: fix lockdep warning and kernel warning after unplugging ar9271 usb device This patch fixes two warnings below after unplugging ar9271 usb device: -one is a kernel warning[1] -another is a lockdep warning[2] The root reason is that __skb_queue_purge can't be executed in hardirq context, so the patch forks ath9k_skb_queue_purge(ath9k version of _skb_queue_purge), which frees skb with dev_kfree_skb_any which can be run in hardirq context safely, then prevent the lockdep warning and kernel warning after unplugging ar9271 usb device. [1] kernel warning [ 602.894005] ------------[ cut here ]------------ [ 602.894005] WARNING: at net/core/skbuff.c:398 skb_release_head_state+0x71/0x87() [ 602.894005] Hardware name: 6475EK2 [ 602.894005] Modules linked in: ath9k_htc ath9k ath9k_common ath9k_hw ath bridge stp llc sunrpc ipv6 cpufreq_ondemand acpi_cpufreq freq_table kvm_intel kvm arc4 ecb mac80211 snd_hda_codec_conexant snd_hda_intel snd_hda_codec snd_hwdep thinkpad_acpi snd_pcm snd_timer hwmon iTCO_wdt snd e1000e pcspkr i2c_i801 usbhid iTCO_vendor_support wmi cfg80211 yenta_socket rsrc_nonstatic pata_acpi snd_page_alloc soundcore uhci_hcd ohci_hcd ehci_hcd usbcore i915 drm_kms_helper drm i2c_algo_bit i2c_core video output [last unloaded: ath] [ 602.894005] Pid: 2506, comm: ping Tainted: G W 2.6.34-rc3-wl #20 [ 602.894005] Call Trace: [ 602.894005] [] warn_slowpath_common+0x7c/0x94 [ 602.894005] [] ? __skb_queue_purge+0x43/0x4a [ath9k_htc] [ 602.894005] [] warn_slowpath_null+0x14/0x16 [ 602.894005] [] skb_release_head_state+0x71/0x87 [ 602.894005] [] __kfree_skb+0x16/0x81 [ 602.894005] [] kfree_skb+0x7e/0x86 [ 602.894005] [] __skb_queue_purge+0x43/0x4a [ath9k_htc] [ 602.894005] [] __hif_usb_tx+0x1c1/0x21b [ath9k_htc] [ 602.894005] [] hif_usb_tx_cb+0x12f/0x154 [ath9k_htc] [ 602.894005] [] usb_hcd_giveback_urb+0x91/0xc5 [usbcore] [ 602.894005] [] ehci_urb_done+0x7a/0x8b [ehci_hcd] [ 602.894005] [] qh_completions+0x2ee/0x376 [ehci_hcd] [ 602.894005] [] ehci_work+0x95/0x76e [ehci_hcd] [ 602.894005] [] ? ehci_irq+0x2f/0x1d4 [ehci_hcd] [ 602.894005] [] ehci_irq+0x1a6/0x1d4 [ehci_hcd] [ 602.894005] [] ? __rcu_process_callbacks+0x7a/0x2df [ 602.894005] [] ? handle_fasteoi_irq+0x22/0xd2 [ 602.894005] [] usb_hcd_irq+0x4a/0xa7 [usbcore] [ 602.894005] [] handle_IRQ_event+0x77/0x14f [ 602.894005] [] ? skb_release_data+0xc9/0xce [ 602.894005] [] handle_fasteoi_irq+0x92/0xd2 [ 602.894005] [] handle_irq+0x88/0x91 [ 602.894005] [] do_IRQ+0x63/0xc9 [ 602.894005] [] ? ip_flush_pending_frames+0x4d/0x5c [ 602.894005] [] ret_from_intr+0x0/0x16 [ 602.894005] [] ? __delete_object+0x5a/0xb1 [ 602.894005] [] ? _raw_write_unlock_irqrestore+0x47/0x7e [ 602.894005] [] ? _raw_write_unlock_irqrestore+0x4c/0x7e [ 602.894005] [] __delete_object+0x5a/0xb1 [ 602.894005] [] delete_object_full+0x25/0x31 [ 602.894005] [] kmemleak_free+0x26/0x45 [ 602.894005] [] kfree+0xaa/0x149 [ 602.894005] [] ? sock_def_write_space+0x84/0x89 [ 602.894005] [] ? ip_flush_pending_frames+0x4d/0x5c [ 602.894005] [] skb_release_data+0xc9/0xce [ 602.894005] [] __kfree_skb+0x1e/0x81 [ 602.894005] [] kfree_skb+0x7e/0x86 [ 602.894005] [] ip_flush_pending_frames+0x4d/0x5c [ 602.894005] [] raw_sendmsg+0x653/0x709 [ 602.894005] [] inet_sendmsg+0x54/0x5d [ 602.894005] [] ? sock_recvmsg+0xc6/0xdf [ 602.894005] [] sock_sendmsg+0xc0/0xd9 [ 602.894005] [] ? might_fault+0x68/0xb8 [ 602.894005] [] ? might_fault+0xb1/0xb8 [ 602.894005] [] ? copy_from_user+0x2f/0x31 [ 602.894005] [] ? verify_iovec+0x54/0x91 [ 602.894005] [] sys_sendmsg+0x1da/0x241 [ 602.894005] [] ? finish_task_switch+0x0/0xc9 [ 602.894005] [] ? finish_task_switch+0x0/0xc9 [ 602.894005] [] ? trace_hardirqs_on_caller+0x16/0x150 [ 602.894005] [] ? _raw_spin_unlock_irq+0x56/0x63 [ 602.894005] [] ? finish_task_switch+0xa4/0xc9 [ 602.894005] [] ? finish_task_switch+0x0/0xc9 [ 602.894005] [] ? need_resched+0x23/0x2d [ 602.894005] [] ? trace_hardirqs_on_caller+0x16/0x150 [ 602.894005] [] ? trace_hardirqs_on_thunk+0x3a/0x3f [ 602.894005] [] system_call_fastpath+0x16/0x1b [ 602.894005] ---[ end trace 91ba2d8dc7826839 ]--- [2] lockdep warning [ 169.363215] ====================================================== [ 169.365390] [ INFO: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected ] [ 169.366334] 2.6.34-rc3-wl #20 [ 169.366872] ------------------------------------------------------ [ 169.366872] khubd/78 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: [ 169.366872] (clock-AF_INET){++.?..}, at: [] sock_def_write_space+0x1e/0x89 [ 169.366872] [ 169.366872] and this task is already holding: [ 169.366872] (&(&hif_dev->tx.tx_lock)->rlock){-.-...}, at: [] hif_usb_stop+0x24/0x53 [ath9k_htc] [ 169.366872] which would create a new lock dependency: [ 169.366872] (&(&hif_dev->tx.tx_lock)->rlock){-.-...} -> (clock-AF_INET){++.?..} [ 169.366872] [ 169.366872] but this new dependency connects a HARDIRQ-irq-safe lock: [ 169.366872] (&(&hif_dev->tx.tx_lock)->rlock){-.-...} [ 169.366872] ... which became HARDIRQ-irq-safe at: [ 169.366872] [] __lock_acquire+0x2c6/0xd2b [ 169.366872] [] lock_acquire+0xec/0x119 [ 169.366872] [] _raw_spin_lock+0x40/0x73 [ 169.366872] [] hif_usb_tx_cb+0x5e/0x154 [ath9k_htc] [ 169.366872] [] usb_hcd_giveback_urb+0x91/0xc5 [usbcore] [ 169.366872] [] ehci_urb_done+0x7a/0x8b [ehci_hcd] [ 169.366872] [] qh_completions+0x2ee/0x376 [ehci_hcd] [ 169.366872] [] ehci_work+0x95/0x76e [ehci_hcd] [ 169.366872] [] ehci_irq+0x1a6/0x1d4 [ehci_hcd] [ 169.366872] [] usb_hcd_irq+0x4a/0xa7 [usbcore] [ 169.366872] [] handle_IRQ_event+0x77/0x14f [ 169.366872] [] handle_fasteoi_irq+0x92/0xd2 [ 169.366872] [] handle_irq+0x88/0x91 [ 169.366872] [] do_IRQ+0x63/0xc9 [ 169.366872] [] ret_from_intr+0x0/0x16 [ 169.366872] [] cpuidle_idle_call+0xa7/0x115 [ 169.366872] [] cpu_idle+0x68/0xc4 [ 169.366872] [] rest_init+0x104/0x10b [ 169.366872] [] start_kernel+0x3f1/0x3fc [ 169.366872] [] x86_64_start_reservations+0xb3/0xb7 [ 169.366872] [] x86_64_start_kernel+0xf8/0x107 [ 169.366872] [ 169.366872] to a HARDIRQ-irq-unsafe lock: [ 169.366872] (clock-AF_INET){++.?..} [ 169.366872] ... which became HARDIRQ-irq-unsafe at: [ 169.366872] ... [] __lock_acquire+0x33a/0xd2b [ 169.366872] [] lock_acquire+0xec/0x119 [ 169.366872] [] _raw_write_lock_bh+0x45/0x7a [ 169.366872] [] tcp_close+0x165/0x34d [ 169.366872] [] inet_release+0x55/0x5c [ 169.366872] [] sock_release+0x1f/0x6e [ 169.366872] [] sock_close+0x27/0x2b [ 169.366872] [] __fput+0x125/0x1ca [ 169.366872] [] fput+0x1a/0x1c [ 169.366872] [] filp_close+0x68/0x72 [ 169.366872] [] sys_close+0xad/0xe7 [ 169.366872] [] system_call_fastpath+0x16/0x1b (Trimmed at the "other info that might help us debug this" line in the interest of brevity... -- JWL) Signed-off-by: Ming Lei Acked-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 3d8f0f468f8d..fe994e229898 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -149,6 +149,13 @@ static void hif_usb_tx_cb(struct urb *urb) } } +static inline void ath9k_skb_queue_purge(struct sk_buff_head *list) +{ + struct sk_buff *skb; + while ((skb = __skb_dequeue(list)) != NULL) + dev_kfree_skb_any(skb); +} + /* TX lock has to be taken */ static int __hif_usb_tx(struct hif_device_usb *hif_dev) { @@ -207,7 +214,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC); if (ret) { tx_buf->len = tx_buf->offset = 0; - __skb_queue_purge(&tx_buf->skb_queue); + ath9k_skb_queue_purge(&tx_buf->skb_queue); __skb_queue_head_init(&tx_buf->skb_queue); list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); hif_dev->tx.tx_buf_cnt++; @@ -274,7 +281,7 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id) unsigned long flags; spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); - __skb_queue_purge(&hif_dev->tx.tx_skb_queue); + ath9k_skb_queue_purge(&hif_dev->tx.tx_skb_queue); hif_dev->tx.tx_skb_cnt = 0; hif_dev->tx.flags |= HIF_USB_TX_STOP; spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); -- cgit v1.2.3 From afa5ec27f4d69952d4ae11f182258bf53d85fcf5 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Tue, 13 Apr 2010 01:21:40 +0300 Subject: wl1251: don't require NVS data when EEPROM is used If EEPROM is used, NVS data is now loaded but ignored. Stop loading it to avoid need of dummy NVS file for modules with EEPROM. Signed-off-by: Grazvydas Ignotas Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 0155653b7105..7b8b21212bf7 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -201,8 +201,8 @@ static int wl1251_chip_wakeup(struct wl1251 *wl) goto out; } - /* No NVS from netlink, try to get it from the filesystem */ - if (wl->nvs == NULL) { + if (wl->nvs == NULL && !wl->use_eeprom) { + /* No NVS from netlink, try to get it from the filesystem */ ret = wl1251_fetch_nvs(wl); if (ret < 0) goto out; -- cgit v1.2.3 From 94d0bbe849190255b93fede8eb46809a38f9b8bf Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 13 Apr 2010 18:10:26 +0200 Subject: ar9170usb: add a couple more USB IDs This patch adds the following 5 entries to the usbid device table: * Netgear WNA1000 * Proxim ORiNOCO Dual Band 802.11n USB Adapter * 3Com Dual Band 802.11n USB Adapter * H3C Dual Band 802.11n USB Adapter * WNC Generic 11n USB dongle CC: Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/usb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 6b1cb706e410..0259bb46247d 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -66,18 +66,28 @@ static struct usb_device_id ar9170_usb_ids[] = { { USB_DEVICE(0x0cf3, 0x1001) }, /* TP-Link TL-WN821N v2 */ { USB_DEVICE(0x0cf3, 0x1002) }, + /* 3Com Dual Band 802.11n USB Adapter */ + { USB_DEVICE(0x0cf3, 0x1010) }, + /* H3C Dual Band 802.11n USB Adapter */ + { USB_DEVICE(0x0cf3, 0x1011) }, /* Cace Airpcap NX */ { USB_DEVICE(0xcace, 0x0300) }, /* D-Link DWA 160 A1 */ { USB_DEVICE(0x07d1, 0x3c10) }, /* D-Link DWA 160 A2 */ { USB_DEVICE(0x07d1, 0x3a09) }, + /* Netgear WNA1000 */ + { USB_DEVICE(0x0846, 0x9040) }, /* Netgear WNDA3100 */ { USB_DEVICE(0x0846, 0x9010) }, /* Netgear WN111 v2 */ { USB_DEVICE(0x0846, 0x9001) }, /* Zydas ZD1221 */ { USB_DEVICE(0x0ace, 0x1221) }, + /* Proxim ORiNOCO 802.11n USB */ + { USB_DEVICE(0x1435, 0x0804) }, + /* WNC Generic 11n USB Dongle */ + { USB_DEVICE(0x1435, 0x0326) }, /* ZyXEL NWD271N */ { USB_DEVICE(0x0586, 0x3417) }, /* Z-Com UB81 BG */ -- cgit v1.2.3 From a5e944f1d955f3819503348426763e21e0413ba6 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Wed, 14 Apr 2010 12:16:00 +0200 Subject: wireless: rt2x00: rt2800usb: identify Sitecom devices A very useful information was provided by Sitecom R&D guys: Please find the information regarding our latest Ralink adapters below; WL-302 - VID: 0x0DF6, PID: 0x002D - Ralink RT2771 WL-315 - VID: 0x0DF6, PID: 0x0039 - Ralink RT2770 WL-319 - VID: 0x182D, PID: 0x0037 - Ralink RT2860 WL-321 - VID: 0x0DF6, PID: 0x003B - Ralink RT2770 WL-324 - VID: 0x0DF6, PID: 0x003D - Ralink RT2870 WL-329 - VID: 0x0DF6, PID: 0x0041 - Ralink RT3572 WL-343 - VID: 0x0DF6, PID: 0x003E - Ralink RT3070 WL-344 - VID: 0x0DF6, PID: 0x0040 - Ralink RT3071 WL-345 - VID: 0x0DF6, PID: 0x0042 - Ralink RT3072 WL-608 - VID: 0x0DF6, PID: 0x003F - Ralink RT2070 Note: PID: 0x003C, 0x004A, and 0x004D: --these products do not exist; devices were never produced/shipped-- The WL-349v4 USB dongle (0x0df6,0x0050) will be shipped soon (it isn't available yet), and uses a Ralink RT3370 chipset. Signed-off-by: Xose Vazquez Perez Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 39877880869a..4c12f2ffe223 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -876,6 +876,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, /* SMC */ { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -975,6 +977,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -1002,6 +1005,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zinwell */ { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, #endif @@ -1075,13 +1079,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Qcom */ { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Sitecom */ - { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) }, /* SMC */ { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, -- cgit v1.2.3 From 61c2a80b960361a930a4e3c4c0df694713b9dafd Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Wed, 14 Apr 2010 13:05:48 +0300 Subject: wl1251: read default MAC address from EEPROM when available Some wl1251 hardware configurations (like in WG7210 module) have EEPROM attached where NVS data is kept, which includes MAC address. In such configurations, let's read default MAC address from EEPROM, instead of using random one. Signed-off-by: Grazvydas Ignotas Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 63 +++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1251_reg.h | 7 ++++ 2 files changed, 70 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 7b8b21212bf7..390cee7e61a1 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -1195,6 +1195,66 @@ static const struct ieee80211_ops wl1251_ops = { .conf_tx = wl1251_op_conf_tx, }; +static int wl1251_read_eeprom_byte(struct wl1251 *wl, off_t offset, u8 *data) +{ + unsigned long timeout; + + wl1251_reg_write32(wl, EE_ADDR, offset); + wl1251_reg_write32(wl, EE_CTL, EE_CTL_READ); + + /* EE_CTL_READ clears when data is ready */ + timeout = jiffies + msecs_to_jiffies(100); + while (1) { + if (!(wl1251_reg_read32(wl, EE_CTL) & EE_CTL_READ)) + break; + + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; + + msleep(1); + } + + *data = wl1251_reg_read32(wl, EE_DATA); + return 0; +} + +static int wl1251_read_eeprom(struct wl1251 *wl, off_t offset, + u8 *data, size_t len) +{ + size_t i; + int ret; + + wl1251_reg_write32(wl, EE_START, 0); + + for (i = 0; i < len; i++) { + ret = wl1251_read_eeprom_byte(wl, offset + i, &data[i]); + if (ret < 0) + return ret; + } + + return 0; +} + +static int wl1251_read_eeprom_mac(struct wl1251 *wl) +{ + u8 mac[ETH_ALEN]; + int i, ret; + + wl1251_set_partition(wl, 0, 0, REGISTERS_BASE, REGISTERS_DOWN_SIZE); + + ret = wl1251_read_eeprom(wl, 0x1c, mac, sizeof(mac)); + if (ret < 0) { + wl1251_warning("failed to read MAC address from EEPROM"); + return ret; + } + + /* MAC is stored in reverse order */ + for (i = 0; i < ETH_ALEN; i++) + wl->mac_addr[i] = mac[ETH_ALEN - i - 1]; + + return 0; +} + static int wl1251_register_hw(struct wl1251 *wl) { int ret; @@ -1241,6 +1301,9 @@ int wl1251_init_ieee80211(struct wl1251 *wl) wl->hw->queues = 4; + if (wl->use_eeprom) + wl1251_read_eeprom_mac(wl); + ret = wl1251_register_hw(wl); if (ret) goto out; diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl12xx/wl1251_reg.h index 0ca3b4326056..d16edd9bf06c 100644 --- a/drivers/net/wireless/wl12xx/wl1251_reg.h +++ b/drivers/net/wireless/wl12xx/wl1251_reg.h @@ -46,7 +46,14 @@ #define SOR_CFG (REGISTERS_BASE + 0x0800) #define ECPU_CTRL (REGISTERS_BASE + 0x0804) #define HI_CFG (REGISTERS_BASE + 0x0808) + +/* EEPROM registers */ #define EE_START (REGISTERS_BASE + 0x080C) +#define EE_CTL (REGISTERS_BASE + 0x2000) +#define EE_DATA (REGISTERS_BASE + 0x2004) +#define EE_ADDR (REGISTERS_BASE + 0x2008) + +#define EE_CTL_READ 2 #define CHIP_ID_B (REGISTERS_BASE + 0x5674) -- cgit v1.2.3 From 410866930ea1929b0fdfb533dd84ddaa234b06e4 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Thu, 15 Apr 2010 09:13:13 +0200 Subject: rt2x00: add txdesc parameter to write_tx_data Extend the write_tx_data callback with a txdesc parameter to allow access to the tx desciptor while preparing the tx data. Signed-off-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 3 ++- drivers/net/wireless/rt2x00/rt2x00pci.c | 3 ++- drivers/net/wireless/rt2x00/rt2x00pci.h | 3 ++- drivers/net/wireless/rt2x00/rt2x00queue.c | 3 ++- drivers/net/wireless/rt2x00/rt2x00usb.c | 3 ++- drivers/net/wireless/rt2x00/rt2x00usb.h | 3 ++- 6 files changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 4de505b98331..4f9b666f7a7f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -549,7 +549,8 @@ struct rt2x00lib_ops { void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, struct txentry_desc *txdesc); - int (*write_tx_data) (struct queue_entry *entry); + int (*write_tx_data) (struct queue_entry *entry, + struct txentry_desc *txdesc); void (*write_beacon) (struct queue_entry *entry); int (*get_tx_data_len) (struct queue_entry *entry); void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 047123b766fc..2fe9f295351f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -62,7 +62,8 @@ EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read); /* * TX data handlers. */ -int rt2x00pci_write_tx_data(struct queue_entry *entry) +int rt2x00pci_write_tx_data(struct queue_entry *entry, + struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct queue_entry_priv_pci *entry_priv = entry->priv_data; diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 8149ff68410a..51bcef3839ce 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -92,7 +92,8 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, * This function will initialize the DMA and skb descriptor * to prepare the entry for the actual TX operation. */ -int rt2x00pci_write_tx_data(struct queue_entry *entry); +int rt2x00pci_write_tx_data(struct queue_entry *entry, + struct txentry_desc *txdesc); /** * struct queue_entry_priv_pci: Per entry PCI specific information diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 0b4801a14601..a68cf90f6c4e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -525,7 +525,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, * call failed. Since we always return NETDEV_TX_OK to mac80211, * this frame will simply be dropped. */ - if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) { + if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry, + &txdesc))) { clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); entry->skb = NULL; return -EIO; diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 0a751e73aa0f..acf3282fc13e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -215,7 +215,8 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) rt2x00lib_txdone(entry, &txdesc); } -int rt2x00usb_write_tx_data(struct queue_entry *entry) +int rt2x00usb_write_tx_data(struct queue_entry *entry, + struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 3da6841b5d42..621d0f829251 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -376,7 +376,8 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev); * This function will initialize the URB and skb descriptor * to prepare the entry for the actual TX operation. */ -int rt2x00usb_write_tx_data(struct queue_entry *entry); +int rt2x00usb_write_tx_data(struct queue_entry *entry, + struct txentry_desc *txdesc); /** * struct queue_entry_priv_usb: Per entry USB specific information -- cgit v1.2.3 From 745b1ae31ba6644a943ec2b6da2d03f00d8b2dd2 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Thu, 15 Apr 2010 09:13:35 +0200 Subject: rt2x00: rt2800pci: fix tx path by not accessing the skb after it was DMA mapped rt2800pci used the callback write_tx_desc to write the tx descriptor but also to update the txwi which is part of the dma mapped skb. Since the memory was already DMA mapped _before_ the call to write_tx_desc the device didn't get the txwi data at all or only sporadically. The call order is basically as follows (from rt2x00queue.c): 1) write_tx_data 2) rt2x00queue_map_txskb 3) write_tx_desc Hence, we shouldn't touch the skb in write_tx_desc anymore. To fix this issue create a new rt2800pci_write_tx_data callback and use it for updating the txwi _before_ the memory gets DMA mapped. The tx descriptor is still written (as before) in write_tx_desc. This patch allows basic TX on an rt305x soc device but I'm pretty sure that it will fix pci based cards as well. I can associate just fine with an AP now but I wasn't able to get a wpa secured connection working yet. Signed-off-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 34 ++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 2131f8f0c502..0e52f174896c 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -613,15 +613,23 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, /* * TX descriptor initialization */ -static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, - struct txentry_desc *txdesc) +static int rt2800pci_write_tx_data(struct queue_entry* entry, + struct txentry_desc *txdesc) { - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txd = skbdesc->desc; - __le32 *txwi = (__le32 *)(skb->data - rt2x00dev->ops->extra_tx_headroom); + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct sk_buff *skb = entry->skb; + struct skb_frame_desc *skbdesc; + int ret; + __le32 *txwi; u32 word; + ret = rt2x00pci_write_tx_data(entry, txdesc); + if (ret) + return ret; + + skbdesc = get_skb_frame_desc(skb); + txwi = (__le32 *)(skb->data - rt2x00dev->ops->extra_tx_headroom); + /* * Initialize TX Info descriptor */ @@ -670,6 +678,18 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); + return 0; +} + + +static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, + struct sk_buff *skb, + struct txentry_desc *txdesc) +{ + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); + __le32 *txd = skbdesc->desc; + u32 word; + /* * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1 * must contains a TXWI structure + 802.11 header + padding + 802.11 @@ -1135,7 +1155,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .reset_tuner = rt2800_reset_tuner, .link_tuner = rt2800_link_tuner, .write_tx_desc = rt2800pci_write_tx_desc, - .write_tx_data = rt2x00pci_write_tx_data, + .write_tx_data = rt2800pci_write_tx_data, .write_beacon = rt2800pci_write_beacon, .kick_tx_queue = rt2800pci_kick_tx_queue, .kill_tx_queue = rt2800pci_kill_tx_queue, -- cgit v1.2.3 From 2fddd880668ee124cb56429f458b74d2772f6cb6 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Thu, 15 Apr 2010 13:25:49 +0200 Subject: wireless: rt2x00: rt2800usb: identify Hawking devices 0x0e66,0x0009 HWUN2 Hawking Technologies Hi-Gain Wireless-150N USB Adapter w/ Upgradable Antenna 0x0e66,0x000b HWDN2 Hawking Technologies Hi-Gain USB Wireless-150N Dish Adapter 0x0e66,0x0013 Hawking Technologies Hi-Gain Wireless-N USB Adapter 0x0e66,0x0017 Hawking Wireless-N Network Adapter 0x0e66,0x0018 Hawking Wireless-N Network Adapter Hawking Technologies Technical Support guys say: All our N adapters use the same chipset. Ralink RT 2870 chipset. Signed-off-by: Xose Vazquez Perez Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 4c12f2ffe223..cfa21ec70ccc 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -848,6 +848,11 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Hawking */ { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0013), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0018), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Linksys */ { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -1057,9 +1062,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Gigabyte */ { USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Hawking */ - { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, /* LevelOne */ { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, -- cgit v1.2.3 From 103823db62ffca028c7a214c80266519d2ea7d8d Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 15 Apr 2010 14:17:07 +0200 Subject: p54pci: fix serious sparse warning This patch fixes a bug which was just recently introduced by ("p54pci: prevent stuck rx-ring on slow system"). make M=drivers/net/wireless/p54 C=2 CF=-D__CHECK_ENDIAN__ CHECK drivers/net/wireless/p54/p54pci.c drivers/net/wireless/p54/p54pci.c:143:11: warning: cast to restricted __le32 CC [M] drivers/net/wireless/p54/p54pci.o Reported-by: Johannes Berg Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index aa29663bf6c9..0a516c8efd20 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -139,7 +139,7 @@ static void p54p_refill_rx_ring(struct ieee80211_hw *dev, idx = le32_to_cpu(ring_control->host_idx[ring_index]); limit = idx; - limit -= le32_to_cpu(index); + limit -= index; limit = ring_limit - limit; i = idx % ring_limit; -- cgit v1.2.3 From 8c00b39f33bc5340be9b053963321eb9ea6a78ee Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Thu, 15 Apr 2010 18:23:23 +0300 Subject: wl1251: register platform_device to pass board data wl1251 is embedded chip that can be connected using SDIO bus, and is not an actual SDIO card. For this reason there is a need to pass some board specific data, like 'EEPROM is attached' flag or power control callback. However currently there is no way to pass this data through SDIO subsystem, so this patch registers dummy platform_device to allow that, until we have a better solution to this. Signed-off-by: Grazvydas Ignotas Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_sdio.c | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c index 2051ef06e9ec..7409c3468e25 100644 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "wl1251.h" @@ -34,6 +36,8 @@ #define SDIO_DEVICE_ID_TI_WL1251 0x9066 #endif +static struct wl12xx_platform_data *wl12xx_board_data; + static struct sdio_func *wl_to_func(struct wl1251 *wl) { return wl->if_priv; @@ -144,6 +148,30 @@ static const struct wl1251_if_operations wl1251_sdio_ops = { .disable_irq = wl1251_sdio_disable_irq, }; +static int wl1251_platform_probe(struct platform_device *pdev) +{ + if (pdev->id != -1) { + wl1251_error("can only handle single device"); + return -ENODEV; + } + + wl12xx_board_data = pdev->dev.platform_data; + return 0; +} + +/* + * Dummy platform_driver for passing platform_data to this driver, + * until we have a way to pass this through SDIO subsystem or + * some other way. + */ +static struct platform_driver wl1251_platform_driver = { + .driver = { + .name = "wl1251_data", + .owner = THIS_MODULE, + }, + .probe = wl1251_platform_probe, +}; + static int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { @@ -169,6 +197,11 @@ static int wl1251_sdio_probe(struct sdio_func *func, wl->if_ops = &wl1251_sdio_ops; wl->set_power = wl1251_sdio_set_power; + if (wl12xx_board_data != NULL) { + wl->set_power = wl12xx_board_data->set_power; + wl->use_eeprom = wl12xx_board_data->use_eeprom; + } + sdio_release_host(func); ret = wl1251_init_ieee80211(wl); if (ret) @@ -208,6 +241,12 @@ static int __init wl1251_sdio_init(void) { int err; + err = platform_driver_register(&wl1251_platform_driver); + if (err) { + wl1251_error("failed to register platform driver: %d", err); + return err; + } + err = sdio_register_driver(&wl1251_sdio_driver); if (err) wl1251_error("failed to register sdio driver: %d", err); @@ -217,6 +256,7 @@ static int __init wl1251_sdio_init(void) static void __exit wl1251_sdio_exit(void) { sdio_unregister_driver(&wl1251_sdio_driver); + platform_driver_unregister(&wl1251_platform_driver); wl1251_notice("unloaded"); } -- cgit v1.2.3 From edbe056a5a70aac20127189ca99d042640fd3366 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 15 Apr 2010 14:00:11 -0500 Subject: rtl818x: Move configuration details to the rtl818x directory In preparation for new rtl818x devices, move the existing rtl818x configuration into the rtl818x directory. Signed-off-by: Larry Finger Acked-by: Hin-Tak Leung Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 85 +--------------------------------- drivers/net/wireless/rtl818x/Kconfig | 88 ++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 84 deletions(-) create mode 100644 drivers/net/wireless/rtl818x/Kconfig (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 588943660755..77500cb7fd26 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -210,90 +210,7 @@ config USB_NET_RNDIS_WLAN If you choose to build a module, it'll be called rndis_wlan. -config RTL8180 - tristate "Realtek 8180/8185 PCI support" - depends on MAC80211 && PCI && EXPERIMENTAL - select EEPROM_93CX6 - ---help--- - This is a driver for RTL8180 and RTL8185 based cards. - These are PCI based chips found in cards such as: - - (RTL8185 802.11g) - A-Link WL54PC - - (RTL8180 802.11b) - Belkin F5D6020 v3 - Belkin F5D6020 v3 - Dlink DWL-610 - Dlink DWL-510 - Netgear MA521 - Level-One WPC-0101 - Acer Aspire 1357 LMi - VCTnet PC-11B1 - Ovislink AirLive WL-1120PCM - Mentor WL-PCI - Linksys WPC11 v4 - TrendNET TEW-288PI - D-Link DWL-520 Rev D - Repotec RP-WP7126 - TP-Link TL-WN250/251 - Zonet ZEW1000 - Longshine LCS-8031-R - HomeLine HLW-PCC200 - GigaFast WF721-AEX - Planet WL-3553 - Encore ENLWI-PCI1-NT - TrendNET TEW-266PC - Gigabyte GN-WLMR101 - Siemens-fujitsu Amilo D1840W - Edimax EW-7126 - PheeNet WL-11PCIR - Tonze PC-2100T - Planet WL-8303 - Dlink DWL-650 v M1 - Edimax EW-7106 - Q-Tec 770WC - Topcom Skyr@cer 4011b - Roper FreeLan 802.11b (edition 2004) - Wistron Neweb Corp CB-200B - Pentagram HorNET - QTec 775WC - TwinMOS Booming B Series - Micronet SP906BB - Sweex LC700010 - Surecom EP-9428 - Safecom SWLCR-1100 - - Thanks to Realtek for their support! - -config RTL8187 - tristate "Realtek 8187 and 8187B USB support" - depends on MAC80211 && USB - select EEPROM_93CX6 - ---help--- - This is a driver for RTL8187 and RTL8187B based cards. - These are USB based chips found in devices such as: - - Netgear WG111v2 - Level 1 WNC-0301USB - Micronet SP907GK V5 - Encore ENUWI-G2 - Trendnet TEW-424UB - ASUS P5B Deluxe/P5K Premium motherboards - Toshiba Satellite Pro series of laptops - Asus Wireless Link - Linksys WUSB54GC-EU v2 - (v1 = rt73usb; v3 is rt2070-based, - use staging/rt3070 or try rt2800usb) - - Thanks to Realtek for their support! - -# If possible, automatically enable LEDs for RTL8187. - -config RTL8187_LEDS - bool - depends on RTL8187 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = RTL8187) - default y +source "drivers/net/wireless/rtl818x/Kconfig" config ADM8211 tristate "ADMtek ADM8211 support" diff --git a/drivers/net/wireless/rtl818x/Kconfig b/drivers/net/wireless/rtl818x/Kconfig new file mode 100644 index 000000000000..17d80fe556de --- /dev/null +++ b/drivers/net/wireless/rtl818x/Kconfig @@ -0,0 +1,88 @@ +# +# RTL818X Wireless LAN device configuration +# +config RTL8180 + tristate "Realtek 8180/8185 PCI support" + depends on MAC80211 && PCI && EXPERIMENTAL + select EEPROM_93CX6 + ---help--- + This is a driver for RTL8180 and RTL8185 based cards. + These are PCI based chips found in cards such as: + + (RTL8185 802.11g) + A-Link WL54PC + + (RTL8180 802.11b) + Belkin F5D6020 v3 + Belkin F5D6020 v3 + Dlink DWL-610 + Dlink DWL-510 + Netgear MA521 + Level-One WPC-0101 + Acer Aspire 1357 LMi + VCTnet PC-11B1 + Ovislink AirLive WL-1120PCM + Mentor WL-PCI + Linksys WPC11 v4 + TrendNET TEW-288PI + D-Link DWL-520 Rev D + Repotec RP-WP7126 + TP-Link TL-WN250/251 + Zonet ZEW1000 + Longshine LCS-8031-R + HomeLine HLW-PCC200 + GigaFast WF721-AEX + Planet WL-3553 + Encore ENLWI-PCI1-NT + TrendNET TEW-266PC + Gigabyte GN-WLMR101 + Siemens-fujitsu Amilo D1840W + Edimax EW-7126 + PheeNet WL-11PCIR + Tonze PC-2100T + Planet WL-8303 + Dlink DWL-650 v M1 + Edimax EW-7106 + Q-Tec 770WC + Topcom Skyr@cer 4011b + Roper FreeLan 802.11b (edition 2004) + Wistron Neweb Corp CB-200B + Pentagram HorNET + QTec 775WC + TwinMOS Booming B Series + Micronet SP906BB + Sweex LC700010 + Surecom EP-9428 + Safecom SWLCR-1100 + + Thanks to Realtek for their support! + +config RTL8187 + tristate "Realtek 8187 and 8187B USB support" + depends on MAC80211 && USB + select EEPROM_93CX6 + ---help--- + This is a driver for RTL8187 and RTL8187B based cards. + These are USB based chips found in devices such as: + + Netgear WG111v2 + Level 1 WNC-0301USB + Micronet SP907GK V5 + Encore ENUWI-G2 + Trendnet TEW-424UB + ASUS P5B Deluxe/P5K Premium motherboards + Toshiba Satellite Pro series of laptops + Asus Wireless Link + Linksys WUSB54GC-EU v2 + (v1 = rt73usb; v3 is rt2070-based, + use staging/rt3070 or try rt2800usb) + + Thanks to Realtek for their support! + +# If possible, automatically enable LEDs for RTL8187. + +config RTL8187_LEDS + bool + depends on RTL8187 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = RTL8187) + default y + -- cgit v1.2.3 From 96021f096e5178582af296a2fbb6df7dbd6b695c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 15 Apr 2010 13:27:44 -0700 Subject: libertas: consolidate SDIO firmware wait code Consolidate a bunch of C&P code that waits for the firmware to be ready. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_sdio.c | 98 ++++++++++++--------------------- 1 file changed, 35 insertions(+), 63 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 33206a98a572..60dc9b64381d 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -314,12 +314,28 @@ out: return ret; } +static int if_sdio_wait_status(struct if_sdio_card *card, const u8 condition) +{ + u8 status; + unsigned long timeout; + int ret = 0; + + timeout = jiffies + HZ; + while (1) { + status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); + if (ret || (status & condition)) + break; + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; + mdelay(1); + } + return ret; +} + static int if_sdio_card_to_host(struct if_sdio_card *card) { int ret; - u8 status; u16 size, type, chunk; - unsigned long timeout; lbs_deb_enter(LBS_DEB_SDIO); @@ -334,19 +350,9 @@ static int if_sdio_card_to_host(struct if_sdio_card *card) goto out; } - timeout = jiffies + HZ; - while (1) { - status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); - if (ret) - goto out; - if (status & IF_SDIO_IO_RDY) - break; - if (time_after(jiffies, timeout)) { - ret = -ETIMEDOUT; - goto out; - } - mdelay(1); - } + ret = if_sdio_wait_status(card, IF_SDIO_IO_RDY); + if (ret) + goto out; /* * The transfer must be in one transaction or the firmware @@ -413,8 +419,6 @@ static void if_sdio_host_to_card_worker(struct work_struct *work) { struct if_sdio_card *card; struct if_sdio_packet *packet; - unsigned long timeout; - u8 status; int ret; unsigned long flags; @@ -434,25 +438,15 @@ static void if_sdio_host_to_card_worker(struct work_struct *work) sdio_claim_host(card->func); - timeout = jiffies + HZ; - while (1) { - status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); - if (ret) - goto release; - if (status & IF_SDIO_IO_RDY) - break; - if (time_after(jiffies, timeout)) { - ret = -ETIMEDOUT; - goto release; - } - mdelay(1); + ret = if_sdio_wait_status(card, IF_SDIO_IO_RDY); + if (ret == 0) { + ret = sdio_writesb(card->func, card->ioport, + packet->buffer, packet->nb); } - ret = sdio_writesb(card->func, card->ioport, - packet->buffer, packet->nb); if (ret) - goto release; -release: + lbs_pr_err("error %d sending packet to firmware\n", ret); + sdio_release_host(card->func); kfree(packet); @@ -465,10 +459,11 @@ release: /* Firmware */ /********************************************************************/ +#define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY) + static int if_sdio_prog_helper(struct if_sdio_card *card) { int ret; - u8 status; const struct firmware *fw; unsigned long timeout; u8 *chunk_buffer; @@ -500,20 +495,9 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) size = fw->size; while (size) { - timeout = jiffies + HZ; - while (1) { - status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); - if (ret) - goto release; - if ((status & IF_SDIO_IO_RDY) && - (status & IF_SDIO_DL_RDY)) - break; - if (time_after(jiffies, timeout)) { - ret = -ETIMEDOUT; - goto release; - } - mdelay(1); - } + ret = if_sdio_wait_status(card, FW_DL_READY_STATUS); + if (ret) + goto release; chunk_size = min(size, (size_t)60); @@ -583,7 +567,6 @@ out: static int if_sdio_prog_real(struct if_sdio_card *card) { int ret; - u8 status; const struct firmware *fw; unsigned long timeout; u8 *chunk_buffer; @@ -615,20 +598,9 @@ static int if_sdio_prog_real(struct if_sdio_card *card) size = fw->size; while (size) { - timeout = jiffies + HZ; - while (1) { - status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); - if (ret) - goto release; - if ((status & IF_SDIO_IO_RDY) && - (status & IF_SDIO_DL_RDY)) - break; - if (time_after(jiffies, timeout)) { - ret = -ETIMEDOUT; - goto release; - } - mdelay(1); - } + ret = if_sdio_wait_status(card, FW_DL_READY_STATUS); + if (ret) + goto release; req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret); if (ret) -- cgit v1.2.3 From ac1a474d71d6cbf94bf26889da5768f5f2b0ca2b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 15 Apr 2010 13:32:58 -0700 Subject: libertas: Davinci platforms need more time loading helper firmware Davinci platforms apparently need more time in-between helper firmware blocks. Even though this is an increased delay, we only take this hit once at initialization time. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_sdio.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 60dc9b64381d..68cc407054e3 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -499,6 +499,11 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) if (ret) goto release; + /* On some platforms (like Davinci) the chip needs more time + * between helper blocks. + */ + mdelay(2); + chunk_size = min(size, (size_t)60); *((__le32*)chunk_buffer) = cpu_to_le32(chunk_size); -- cgit v1.2.3 From d70357d56942fa587e39505547cb69e10a8d59a0 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:06 -0400 Subject: ath9k_hw: start building an abstraction layer for hardware routines ath9k supports the AR5008, AR9001 and AR9002 family of Atheros chipsets, all 802.11n. The new breed of 802.11n chips, the AR9003 family will be supported as well soon. To help with its support we're going to add a few callbacks for hardware routines which differ considerably instead of adding branch checks for the revision at runtime. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/common.h | 1 + drivers/net/wireless/ath/ath9k/hw-ops.h | 31 ++++++++ drivers/net/wireless/ath/ath9k/hw.c | 125 ++++++++++++++++++++++---------- drivers/net/wireless/ath/ath9k/hw.h | 47 +++++++++++- drivers/net/wireless/ath/ath9k/init.c | 7 +- 5 files changed, 166 insertions(+), 45 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/hw-ops.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 72a835d9e97f..1a87283a0941 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -20,6 +20,7 @@ #include "../debug.h" #include "hw.h" +#include "hw-ops.h" /* Common header for Atheros 802.11n base driver cores */ diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h new file mode 100644 index 000000000000..ee33146cda15 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef ATH9K_HW_OPS_H +#define ATH9K_HW_OPS_H + +#include "hw.h" + +/* Hardware core and driver accessible callbacks */ + +static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah, + int restore, + int power_off) +{ + ath9k_hw_ops(ah)->config_pci_powersave(ah, restore, power_off); +} + +#endif /* ATH9K_HW_OPS_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 3b9f4c1f8d4e..a55db3bc13e6 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -18,6 +18,7 @@ #include #include "hw.h" +#include "hw-ops.h" #include "rc.h" #include "initvals.h" @@ -25,6 +26,8 @@ #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 +static void ar9002_hw_attach_ops(struct ath_hw *ah); + static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan); @@ -45,6 +48,25 @@ static void __exit ath9k_exit(void) } module_exit(ath9k_exit); +/* Private hardware callbacks */ + +static void ath9k_hw_init_cal_settings(struct ath_hw *ah) +{ + ath9k_hw_private_ops(ah)->init_cal_settings(ah); +} + +static void ath9k_hw_init_mode_regs(struct ath_hw *ah) +{ + ath9k_hw_private_ops(ah)->init_mode_regs(ah); +} + +static bool ath9k_hw_macversion_supported(struct ath_hw *ah) +{ + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + + return priv_ops->macversion_supported(ah->hw_version.macVersion); +} + /********************/ /* Helper Functions */ /********************/ @@ -368,7 +390,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) if (num_possible_cpus() > 1) ah->config.serialize_regmode = SER_REG_MODE_AUTO; } -EXPORT_SYMBOL(ath9k_hw_init); static void ath9k_hw_init_defaults(struct ath_hw *ah) { @@ -532,27 +553,7 @@ static int ath9k_hw_post_init(struct ath_hw *ah) return 0; } -static bool ath9k_hw_devid_supported(u16 devid) -{ - switch (devid) { - case AR5416_DEVID_PCI: - case AR5416_DEVID_PCIE: - case AR5416_AR9100_DEVID: - case AR9160_DEVID_PCI: - case AR9280_DEVID_PCI: - case AR9280_DEVID_PCIE: - case AR9285_DEVID_PCIE: - case AR5416_DEVID_AR9287_PCI: - case AR5416_DEVID_AR9287_PCIE: - case AR2427_DEVID_PCIE: - return true; - default: - break; - } - return false; -} - -static bool ath9k_hw_macversion_supported(u32 macversion) +static bool ar9002_hw_macversion_supported(u32 macversion) { switch (macversion) { case AR_SREV_VERSION_5416_PCI: @@ -570,7 +571,7 @@ static bool ath9k_hw_macversion_supported(u32 macversion) return false; } -static void ath9k_hw_init_cal_settings(struct ath_hw *ah) +static void ar9002_hw_init_cal_settings(struct ath_hw *ah) { if (AR_SREV_9160_10_OR_LATER(ah)) { if (AR_SREV_9280_10_OR_LATER(ah)) { @@ -594,7 +595,7 @@ static void ath9k_hw_init_cal_settings(struct ath_hw *ah) } } -static void ath9k_hw_init_mode_regs(struct ath_hw *ah) +static void ar9002_hw_init_mode_regs(struct ath_hw *ah) { if (AR_SREV_9271(ah)) { INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271, @@ -854,20 +855,12 @@ static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah) "needs fixup for AR_AN_TOP2 register\n"); } -int ath9k_hw_init(struct ath_hw *ah) +/* Called for all hardware families */ +static int __ath9k_hw_init(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); int r = 0; - if (common->bus_ops->ath_bus_type != ATH_USB) { - if (!ath9k_hw_devid_supported(ah->hw_version.devid)) { - ath_print(common, ATH_DBG_FATAL, - "Unsupported device ID: 0x%0x\n", - ah->hw_version.devid); - return -EOPNOTSUPP; - } - } - ath9k_hw_init_defaults(ah); ath9k_hw_init_config(ah); @@ -877,6 +870,8 @@ int ath9k_hw_init(struct ath_hw *ah) return -EIO; } + ar9002_hw_attach_ops(ah); + if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { ath_print(common, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); return -EIO; @@ -901,7 +896,7 @@ int ath9k_hw_init(struct ath_hw *ah) else ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD; - if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) { + if (!ath9k_hw_macversion_supported(ah)) { ath_print(common, ATH_DBG_FATAL, "Mac Chip Rev 0x%02x.%x is not supported by " "this driver\n", ah->hw_version.macVersion, @@ -918,6 +913,7 @@ int ath9k_hw_init(struct ath_hw *ah) if (AR_SREV_9271(ah)) ah->is_pciexpress = false; + /* XXX: move this to its own hw op */ ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); ath9k_hw_init_cal_settings(ah); @@ -979,6 +975,45 @@ int ath9k_hw_init(struct ath_hw *ah) return 0; } +int ath9k_hw_init(struct ath_hw *ah) +{ + int ret; + struct ath_common *common = ath9k_hw_common(ah); + + /* These are all the AR5008/AR9001/AR9002 hardware family of chipsets */ + switch (ah->hw_version.devid) { + case AR5416_DEVID_PCI: + case AR5416_DEVID_PCIE: + case AR5416_AR9100_DEVID: + case AR9160_DEVID_PCI: + case AR9280_DEVID_PCI: + case AR9280_DEVID_PCIE: + case AR9285_DEVID_PCIE: + case AR5416_DEVID_AR9287_PCI: + case AR5416_DEVID_AR9287_PCIE: + case AR2427_DEVID_PCIE: + break; + default: + if (common->bus_ops->ath_bus_type == ATH_USB) + break; + ath_print(common, ATH_DBG_FATAL, + "Hardware device ID 0x%04x not supported\n", + ah->hw_version.devid); + return -EOPNOTSUPP; + } + + ret = __ath9k_hw_init(ah); + if (ret) { + ath_print(common, ATH_DBG_FATAL, + "Unable to initialize hardware; " + "initialization status: %d\n", ret); + return ret; + } + + return 0; +} +EXPORT_SYMBOL(ath9k_hw_init); + static void ath9k_hw_init_bb(struct ath_hw *ah, struct ath9k_channel *chan) { @@ -2500,7 +2535,9 @@ EXPORT_SYMBOL(ath9k_hw_setpower); * Programming the SerDes must go through the same 288 bit serial shift * register as the other analog registers. Hence the 9 writes. */ -void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off) +static void ar9002_hw_configpcipowersave(struct ath_hw *ah, + int restore, + int power_off) { u8 i; u32 val; @@ -2518,7 +2555,7 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off) /* * AR9280 2.0 or later chips use SerDes values from the * initvals.h initialized depending on chipset during - * ath9k_hw_init() + * __ath9k_hw_init() */ for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), @@ -2622,7 +2659,6 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off) } } } -EXPORT_SYMBOL(ath9k_hw_configpcipowersave); /**********************/ /* Interrupt Handling */ @@ -3917,3 +3953,16 @@ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len) hw_name[used] = '\0'; } EXPORT_SYMBOL(ath9k_hw_name); + +/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */ +static void ar9002_hw_attach_ops(struct ath_hw *ah) +{ + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + struct ath_hw_ops *ops = ath9k_hw_ops(ah); + + priv_ops->init_cal_settings = ar9002_hw_init_cal_settings; + priv_ops->init_mode_regs = ar9002_hw_init_mode_regs; + priv_ops->macversion_supported = ar9002_hw_macversion_supported; + + ops->config_pci_powersave = ar9002_hw_configpcipowersave; +} diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index f4821cf33b87..dfe8502866bb 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -440,6 +440,36 @@ struct ath_gen_timer_table { } timer_mask; }; +/** + * struct ath_hw_private_ops - callbacks used internally by hardware code + * + * This structure contains private callbacks designed to only be used internally + * by the hardware core. + * + * @init_cal_settings: Initializes calibration settings + * @init_mode_regs: Initializes mode registers + * @macversion_supported: If this specific mac revision is supported + */ +struct ath_hw_private_ops { + void (*init_cal_settings)(struct ath_hw *ah); + void (*init_mode_regs)(struct ath_hw *ah); + bool (*macversion_supported)(u32 macversion); +}; + +/** + * struct ath_hw_ops - callbacks used by hardware code and driver code + * + * This structure contains callbacks designed to to be used internally by + * hardware code and also by the lower level driver. + * + * @config_pci_powersave: + */ +struct ath_hw_ops { + void (*config_pci_powersave)(struct ath_hw *ah, + int restore, + int power_off); +}; + struct ath_hw { struct ieee80211_hw *hw; struct ath_common common; @@ -540,6 +570,11 @@ struct ath_hw { void (*ath9k_hw_spur_mitigate_freq)(struct ath_hw *ah, struct ath9k_channel *chan); + /* Private to hardware code */ + struct ath_hw_private_ops private_ops; + /* Accessed by the lower level driver */ + struct ath_hw_ops ops; + /* Used to program the radio on non single-chip devices */ u32 *analogBank0Data; u32 *analogBank1Data; @@ -619,6 +654,16 @@ static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah) return &(ath9k_hw_common(ah)->regulatory); } +static inline struct ath_hw_private_ops *ath9k_hw_private_ops(struct ath_hw *ah) +{ + return &ah->private_ops; +} + +static inline struct ath_hw_ops *ath9k_hw_ops(struct ath_hw *ah) +{ + return &ah->ops; +} + /* Initialization, Detach, Reset */ const char *ath9k_hw_probe(u16 vendorid, u16 devid); void ath9k_hw_deinit(struct ath_hw *ah); @@ -681,8 +726,6 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); -void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off); - /* Interrupt Handling */ bool ath9k_hw_intrpend(struct ath_hw *ah); bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 6063f5463708..62682cc2e216 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -566,13 +566,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, ath_read_cachesize(common, &csz); common->cachelsz = csz << 2; /* convert to bytes */ + /* Initializes the hardware for all supported chipsets */ ret = ath9k_hw_init(ah); - if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to initialize hardware; " - "initialization status: %d\n", ret); + if (ret) goto err_hw; - } ret = ath9k_init_debug(ah); if (ret) { -- cgit v1.2.3 From b0550327da7fcab5b4b0f09a450432ee9ae4ca19 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Apr 2010 17:38:07 -0400 Subject: ath9k_hw: add silicon revision macros for AR9300 AR9300 will be the first device supported of the AR9003 family. AR9300 1.0 hardware exists but it is not going to be sold anywhere so we completely skip its support. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/reg.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 7e36ad7421b7..5ab6d6e5d6e8 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -759,6 +759,8 @@ #define AR_SREV_VERSION_9271 0x140 #define AR_SREV_REVISION_9271_10 0 #define AR_SREV_REVISION_9271_11 1 +#define AR_SREV_VERSION_9300 0x1c0 +#define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */ #define AR_SREV_5416(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ @@ -844,6 +846,15 @@ #define AR_SREV_9271_11(_ah) \ (AR_SREV_9271(_ah) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11)) +#define AR_SREV_9300(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300)) +#define AR_SREV_9300_20(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \ + ((_ah)->hw_version.macRev == AR_SREV_REVISION_9300_20)) +#define AR_SREV_9300_20_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9300) || \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9300_20))) #define AR_SREV_9285E_20(_ah) \ (AR_SREV_9285_12_OR_LATER(_ah) && \ -- cgit v1.2.3 From 086a864c9a3ad3c70d68dfb87892c5613a09906c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Apr 2010 17:38:08 -0400 Subject: ath9k_hw: add a macro for abstracting generic timer access Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/reg.h | 38 +++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 5ab6d6e5d6e8..68d55a2e7f78 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1610,24 +1610,26 @@ enum { #define AR_FIRST_NDP_TIMER 7 #define AR_NDP2_PERIOD 0x81a0 #define AR_NDP2_TIMER_MODE 0x81c0 -#define AR_NEXT_TBTT_TIMER 0x8200 -#define AR_NEXT_DMA_BEACON_ALERT 0x8204 -#define AR_NEXT_SWBA 0x8208 -#define AR_NEXT_CFP 0x8208 -#define AR_NEXT_HCF 0x820C -#define AR_NEXT_TIM 0x8210 -#define AR_NEXT_DTIM 0x8214 -#define AR_NEXT_QUIET_TIMER 0x8218 -#define AR_NEXT_NDP_TIMER 0x821C - -#define AR_BEACON_PERIOD 0x8220 -#define AR_DMA_BEACON_PERIOD 0x8224 -#define AR_SWBA_PERIOD 0x8228 -#define AR_HCF_PERIOD 0x822C -#define AR_TIM_PERIOD 0x8230 -#define AR_DTIM_PERIOD 0x8234 -#define AR_QUIET_PERIOD 0x8238 -#define AR_NDP_PERIOD 0x823C + +#define AR_GEN_TIMERS(_i) (0x8200 + ((_i) << 2)) +#define AR_NEXT_TBTT_TIMER AR_GEN_TIMERS(0) +#define AR_NEXT_DMA_BEACON_ALERT AR_GEN_TIMERS(1) +#define AR_NEXT_SWBA AR_GEN_TIMERS(2) +#define AR_NEXT_CFP AR_GEN_TIMERS(2) +#define AR_NEXT_HCF AR_GEN_TIMERS(3) +#define AR_NEXT_TIM AR_GEN_TIMERS(4) +#define AR_NEXT_DTIM AR_GEN_TIMERS(5) +#define AR_NEXT_QUIET_TIMER AR_GEN_TIMERS(6) +#define AR_NEXT_NDP_TIMER AR_GEN_TIMERS(7) + +#define AR_BEACON_PERIOD AR_GEN_TIMERS(8) +#define AR_DMA_BEACON_PERIOD AR_GEN_TIMERS(9) +#define AR_SWBA_PERIOD AR_GEN_TIMERS(10) +#define AR_HCF_PERIOD AR_GEN_TIMERS(11) +#define AR_TIM_PERIOD AR_GEN_TIMERS(12) +#define AR_DTIM_PERIOD AR_GEN_TIMERS(13) +#define AR_QUIET_PERIOD AR_GEN_TIMERS(14) +#define AR_NDP_PERIOD AR_GEN_TIMERS(15) #define AR_TIMER_MODE 0x8240 #define AR_TBTT_TIMER_EN 0x00000001 -- cgit v1.2.3 From 0bef631c5a029e67b908872649b94c9251260a92 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Apr 2010 17:38:09 -0400 Subject: ath9k_hw: fix a missing hex prefix for a register mask This is not a stable code fix as this register is not used anywhere. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 68d55a2e7f78..c1e58da02403 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1544,7 +1544,7 @@ enum { #define AR_TSFOOR_THRESHOLD 0x813c #define AR_TSFOOR_THRESHOLD_VAL 0x0000FFFF -#define AR_PHY_ERR_EIFS_MASK 8144 +#define AR_PHY_ERR_EIFS_MASK 0x8144 #define AR_PHY_ERR_3 0x8168 #define AR_PHY_ERR_3_COUNT 0x00FFFFFF -- cgit v1.2.3 From 2c5204aa83c3a21c5c3e044342dadf4520cc4558 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Apr 2010 17:38:10 -0400 Subject: ath9k_hw: add simple register abstraction for some AR9300 registers Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/reg.h | 42 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index c1e58da02403..d56b4eada165 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -20,7 +20,7 @@ #include "../reg.h" #define AR_CR 0x0008 -#define AR_CR_RXE 0x00000004 +#define AR_CR_RXE (AR_SREV_9300_20_OR_LATER(ah) ? 0x0000000c : 0x00000004) #define AR_CR_RXD 0x00000020 #define AR_CR_SWI 0x00000040 @@ -232,7 +232,6 @@ #define AR_ISR_S5_TIMER_THRESH 0x0007FE00 #define AR_ISR_S5_TIM_TIMER 0x00000010 #define AR_ISR_S5_DTIM_TIMER 0x00000020 -#define AR_ISR_S5_S 0x00d8 #define AR_IMR_S5 0x00b8 #define AR_IMR_S5_TIM_TIMER 0x00000010 #define AR_IMR_S5_DTIM_TIMER 0x00000020 @@ -240,7 +239,6 @@ #define AR_ISR_S5_GENTIMER_TRIG_S 0 #define AR_ISR_S5_GENTIMER_THRESH 0xFF800000 #define AR_ISR_S5_GENTIMER_THRESH_S 16 -#define AR_ISR_S5_S 0x00d8 #define AR_IMR_S5_GENTIMER_TRIG 0x0000FF80 #define AR_IMR_S5_GENTIMER_TRIG_S 0 #define AR_IMR_S5_GENTIMER_THRESH 0xFF800000 @@ -332,10 +330,10 @@ #define AR_ISR_S1_QCU_TXEOL 0x03FF0000 #define AR_ISR_S1_QCU_TXEOL_S 16 -#define AR_ISR_S2_S 0x00cc -#define AR_ISR_S3_S 0x00d0 -#define AR_ISR_S4_S 0x00d4 -#define AR_ISR_S5_S 0x00d8 +#define AR_ISR_S2_S (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d0 : 0x00cc) +#define AR_ISR_S3_S (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d4 : 0x00d0) +#define AR_ISR_S4_S (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d8 : 0x00d4) +#define AR_ISR_S5_S (AR_SREV_9300_20_OR_LATER(ah) ? 0x00dc : 0x00d8) #define AR_DMADBG_0 0x00e0 #define AR_DMADBG_1 0x00e4 #define AR_DMADBG_2 0x00e8 @@ -968,19 +966,21 @@ enum { #define AR9287_GPIO_IN_VAL_S 11 #define AR9271_GPIO_IN_VAL 0xFFFF0000 #define AR9271_GPIO_IN_VAL_S 16 +#define AR9300_GPIO_IN_VAL 0x0001FFFF +#define AR9300_GPIO_IN_VAL_S 0 -#define AR_GPIO_OE_OUT 0x404c +#define AR_GPIO_OE_OUT (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c) #define AR_GPIO_OE_OUT_DRV 0x3 #define AR_GPIO_OE_OUT_DRV_NO 0x0 #define AR_GPIO_OE_OUT_DRV_LOW 0x1 #define AR_GPIO_OE_OUT_DRV_HI 0x2 #define AR_GPIO_OE_OUT_DRV_ALL 0x3 -#define AR_GPIO_INTR_POL 0x4050 -#define AR_GPIO_INTR_POL_VAL 0x00001FFF +#define AR_GPIO_INTR_POL (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050) +#define AR_GPIO_INTR_POL_VAL 0x0001FFFF #define AR_GPIO_INTR_POL_VAL_S 0 -#define AR_GPIO_INPUT_EN_VAL 0x4054 +#define AR_GPIO_INPUT_EN_VAL (AR_SREV_9300_20_OR_LATER(ah) ? 0x405c : 0x4054) #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004 #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2 #define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008 @@ -998,13 +998,13 @@ enum { #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 #define AR_GPIO_JTAG_DISABLE 0x00020000 -#define AR_GPIO_INPUT_MUX1 0x4058 +#define AR_GPIO_INPUT_MUX1 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4060 : 0x4058) #define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 #define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 #define AR_GPIO_INPUT_MUX1_BT_PRIORITY 0x00000f00 #define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S 8 -#define AR_GPIO_INPUT_MUX2 0x405c +#define AR_GPIO_INPUT_MUX2 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4064 : 0x405c) #define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f #define AR_GPIO_INPUT_MUX2_CLK25_S 0 #define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0 @@ -1012,13 +1012,13 @@ enum { #define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00 #define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8 -#define AR_GPIO_OUTPUT_MUX1 0x4060 -#define AR_GPIO_OUTPUT_MUX2 0x4064 -#define AR_GPIO_OUTPUT_MUX3 0x4068 +#define AR_GPIO_OUTPUT_MUX1 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4068 : 0x4060) +#define AR_GPIO_OUTPUT_MUX2 (AR_SREV_9300_20_OR_LATER(ah) ? 0x406c : 0x4064) +#define AR_GPIO_OUTPUT_MUX3 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4070 : 0x4068) -#define AR_INPUT_STATE 0x406c +#define AR_INPUT_STATE (AR_SREV_9300_20_OR_LATER(ah) ? 0x4074 : 0x406c) -#define AR_EEPROM_STATUS_DATA 0x407c +#define AR_EEPROM_STATUS_DATA (AR_SREV_9300_20_OR_LATER(ah) ? 0x4084 : 0x407c) #define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff #define AR_EEPROM_STATUS_DATA_VAL_S 0 #define AR_EEPROM_STATUS_DATA_BUSY 0x00010000 @@ -1026,11 +1026,11 @@ enum { #define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000 #define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000 -#define AR_OBS 0x4080 +#define AR_OBS (AR_SREV_9300_20_OR_LATER(ah) ? 0x4088 : 0x4080) -#define AR_GPIO_PDPU 0x4088 +#define AR_GPIO_PDPU (AR_SREV_9300_20_OR_LATER(ah) ? 0x4090 : 0x4088) -#define AR_PCIE_MSI 0x4094 +#define AR_PCIE_MSI (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094) #define AR_PCIE_MSI_ENABLE 0x00000001 -- cgit v1.2.3 From 783dfca1fceb0140e629d671b67e4be7e8dc7f8d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Apr 2010 17:38:11 -0400 Subject: ath9k_hw: add support for GPIO differences on AR9003 Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 4 +++- drivers/net/wireless/ath/ath9k/reg.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index a55db3bc13e6..6f7faf08b925 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -3440,7 +3440,9 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) if (gpio >= ah->caps.num_gpio_pins) return 0xffffffff; - if (AR_SREV_9271(ah)) + if (AR_SREV_9300_20_OR_LATER(ah)) + return MS_REG_READ(AR9300, gpio) != 0; + else if (AR_SREV_9271(ah)) return MS_REG_READ(AR9271, gpio) != 0; else if (AR_SREV_9287_10_OR_LATER(ah)) return MS_REG_READ(AR9287, gpio) != 0; diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index d56b4eada165..d52489149167 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -954,6 +954,7 @@ enum { #define AR9285_NUM_GPIO 12 #define AR9287_NUM_GPIO 11 #define AR9271_NUM_GPIO 16 +#define AR9300_NUM_GPIO 17 #define AR_GPIO_IN_OUT 0x4048 #define AR_GPIO_IN_VAL 0x0FFFC000 -- cgit v1.2.3 From 42d5bc3faabcc9d7ea1cfe9237d71ef7dce386e3 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:12 -0400 Subject: ath9k_hw: AR9003 does not have AR_RC_AHB skip its setting AR9003 does not have a reset control for AHB. Signed-off-by: Luis R. Rodriguez Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 6f7faf08b925..57c59b6ad5ea 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1697,11 +1697,16 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) if (tmpReg & (AR_INTR_SYNC_LOCAL_TIMEOUT | AR_INTR_SYNC_RADM_CPL_TIMEOUT)) { + u32 val; REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); - REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); - } else { + + val = AR_RC_HOSTIF; + if (!AR_SREV_9300_20_OR_LATER(ah)) + val |= AR_RC_AHB; + REG_WRITE(ah, AR_RC, val); + + } else if (!AR_SREV_9300_20_OR_LATER(ah)) REG_WRITE(ah, AR_RC, AR_RC_AHB); - } rst_flags = AR_RTC_RC_MAC_WARM; if (type == ATH9K_RESET_COLD) @@ -1732,7 +1737,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); - if (!AR_SREV_9100(ah)) + if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) REG_WRITE(ah, AR_RC, AR_RC_AHB); REG_WRITE(ah, AR_RTC_RESET, 0); @@ -2413,15 +2418,24 @@ EXPORT_SYMBOL(ath9k_hw_keyisvalid); /* Power Management (Chipset) */ /******************************/ +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, force chip to sleep. + */ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) { REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); if (setChip) { + /* + * Clear the RTC force wake bit to allow the + * mac to go to sleep. + */ REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); - if (!AR_SREV_9100(ah)) + if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); + /* Shutdown chip. Active low */ if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah)) REG_CLR_BIT(ah, (AR_RTC_RESET), AR_RTC_RESET_EN); -- cgit v1.2.3 From aed1baf1ab10f4b6bd40952a9deb791dbba48f3a Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:13 -0400 Subject: ath9k_hw: remove wrapper ath9k_hw_write_regs() This is used only once by ath9k_hw_process_ini() to write an array of phy registers through REG_WRITE_ARRAY(), but we already call REG_WRITE_ARRAY() multiple times on the same caller so just remove this pointless wrapper. We'll eventually just move the ath9k_hw_process_ini() caller as an callback to abstract away between different hardware families. Although this change is subtle I should note that this does change the delay pattern on writing the next series of registers. REG_WRITE_ARRAY() uses a counter for each register write and does a udelay(1) every 64 writes. By removing this call it means that the counter is processed for all the iniBB_RfGain registers and is incremented on ath9k_hw_process_ini(), before this the after the call ath9k_hw_write_regs() was made the register counter was kept at the same index number prior to the call. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 +- drivers/net/wireless/ath/ath9k/phy.c | 15 --------------- drivers/net/wireless/ath/ath9k/phy.h | 3 --- 3 files changed, 1 insertion(+), 19 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 57c59b6ad5ea..6f447cdbd05c 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1483,7 +1483,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, modesIndex, regWrites); } - ath9k_hw_write_regs(ah, freqIndex, regWrites); + REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c index c3b59390fe38..02d40dfd3a91 100644 --- a/drivers/net/wireless/ath/ath9k/phy.c +++ b/drivers/net/wireless/ath/ath9k/phy.c @@ -41,21 +41,6 @@ #include "hw.h" -/** - * ath9k_hw_write_regs - ?? - * - * @ah: atheros hardware structure - * @freqIndex: - * @regWrites: - * - * Used for both the chipsets with an external AR2133/AR5133 radios and - * single-chip devices. - */ -void ath9k_hw_write_regs(struct ath_hw *ah, u32 freqIndex, int regWrites) -{ - REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); -} - /** * ath9k_hw_ar9280_set_channel - set channel on single-chip device * @ah: atheros hardware structure diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 0132e4c9a9f9..4b6e494bd984 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -17,9 +17,6 @@ #ifndef PHY_H #define PHY_H -/* Common between single chip and non single-chip solutions */ -void ath9k_hw_write_regs(struct ath_hw *ah, u32 freqIndex, int regWrites); - /* Single chip radio settings */ int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan); void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); -- cgit v1.2.3 From 8fe6536850ae49609704a263cbc7542133536922 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:14 -0400 Subject: ath9k_hw: Move some RF ops to the private callbacks The PHY split is easier done in a few steps. First move the RF ops to the private ops and rename them accordingly. We split PHY stuff up first for the AR5008 and AR9002 families. There are some callbacks that AR9002 share with the AR5008 familiy so we set those first, if AR9002 has some different callbacks it will override them upon hardware init. Signed-off-by: Felix Fietkau Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Makefile | 3 +- drivers/net/wireless/ath/ath9k/ani.c | 1 + drivers/net/wireless/ath/ath9k/ar5008_phy.c | 991 +++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9002_phy.c | 450 ++++++++++++ drivers/net/wireless/ath/ath9k/ar9002_phy.h | 581 ++++++++++++++++ drivers/net/wireless/ath/ath9k/calib.c | 1 + drivers/net/wireless/ath/ath9k/eeprom_4k.c | 1 + drivers/net/wireless/ath/ath9k/eeprom_9287.c | 1 + drivers/net/wireless/ath/ath9k/eeprom_def.c | 1 + drivers/net/wireless/ath/ath9k/hw-ops.h | 113 +++ drivers/net/wireless/ath/ath9k/hw.c | 467 +------------ drivers/net/wireless/ath/ath9k/hw.h | 46 +- drivers/net/wireless/ath/ath9k/init.c | 2 +- drivers/net/wireless/ath/ath9k/phy.c | 961 -------------------------- drivers/net/wireless/ath/ath9k/phy.h | 576 +--------------- 15 files changed, 2208 insertions(+), 1987 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/ar5008_phy.c create mode 100644 drivers/net/wireless/ath/ath9k/ar9002_phy.c create mode 100644 drivers/net/wireless/ath/ath9k/ar9002_phy.h delete mode 100644 drivers/net/wireless/ath/ath9k/phy.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 97133beda269..db63ba298049 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -14,13 +14,14 @@ ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o obj-$(CONFIG_ATH9K) += ath9k.o ath9k_hw-y:= hw.o \ + ar9002_phy.o \ + ar5008_phy.o \ eeprom.o \ eeprom_def.o \ eeprom_4k.o \ eeprom_9287.o \ calib.o \ ani.o \ - phy.o \ btcoex.o \ mac.o \ diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 2a0cd64c2bfb..031802c8c125 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -15,6 +15,7 @@ */ #include "hw.h" +#include "ar9002_phy.h" static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, struct ath9k_channel *chan) diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c new file mode 100644 index 000000000000..982b0d3877f8 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -0,0 +1,991 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" +#include "hw-ops.h" +#include "../regd.h" +#include "ar9002_phy.h" + +/* All code below is for non single-chip solutions */ + +/** + * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters + * @rfbuf: + * @reg32: + * @numBits: + * @firstBit: + * @column: + * + * Performs analog "swizzling" of parameters into their location. + * Used on external AR2133/AR5133 radios. + */ +static void ar5008_hw_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, + u32 numBits, u32 firstBit, + u32 column) +{ + u32 tmp32, mask, arrayEntry, lastBit; + int32_t bitPosition, bitsLeft; + + tmp32 = ath9k_hw_reverse_bits(reg32, numBits); + arrayEntry = (firstBit - 1) / 8; + bitPosition = (firstBit - 1) % 8; + bitsLeft = numBits; + while (bitsLeft > 0) { + lastBit = (bitPosition + bitsLeft > 8) ? + 8 : bitPosition + bitsLeft; + mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << + (column * 8); + rfBuf[arrayEntry] &= ~mask; + rfBuf[arrayEntry] |= ((tmp32 << bitPosition) << + (column * 8)) & mask; + bitsLeft -= 8 - bitPosition; + tmp32 = tmp32 >> (8 - bitPosition); + bitPosition = 0; + arrayEntry++; + } +} + +/* + * Fix on 2.4 GHz band for orientation sensitivity issue by increasing + * rf_pwd_icsyndiv. + * + * Theoretical Rules: + * if 2 GHz band + * if forceBiasAuto + * if synth_freq < 2412 + * bias = 0 + * else if 2412 <= synth_freq <= 2422 + * bias = 1 + * else // synth_freq > 2422 + * bias = 2 + * else if forceBias > 0 + * bias = forceBias & 7 + * else + * no change, use value from ini file + * else + * no change, invalid band + * + * 1st Mod: + * 2422 also uses value of 2 + * + * + * 2nd Mod: + * Less than 2412 uses value of 0, 2412 and above uses value of 2 + */ +static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq) +{ + struct ath_common *common = ath9k_hw_common(ah); + u32 tmp_reg; + int reg_writes = 0; + u32 new_bias = 0; + + if (!AR_SREV_5416(ah) || synth_freq >= 3000) + return; + + BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); + + if (synth_freq < 2412) + new_bias = 0; + else if (synth_freq < 2422) + new_bias = 1; + else + new_bias = 2; + + /* pre-reverse this field */ + tmp_reg = ath9k_hw_reverse_bits(new_bias, 3); + + ath_print(common, ATH_DBG_CONFIG, + "Force rf_pwd_icsyndiv to %1d on %4d\n", + new_bias, synth_freq); + + /* swizzle rf_pwd_icsyndiv */ + ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3); + + /* write Bank 6 with new params */ + REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes); +} + +/** + * ar5008_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios + * @ah: atheros hardware stucture + * @chan: + * + * For the external AR2133/AR5133 radios, takes the MHz channel value and set + * the channel value. Assumes writes enabled to analog bus and bank6 register + * cache in ah->analogBank6Data. + */ +static int ar5008_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) +{ + struct ath_common *common = ath9k_hw_common(ah); + u32 channelSel = 0; + u32 bModeSynth = 0; + u32 aModeRefSel = 0; + u32 reg32 = 0; + u16 freq; + struct chan_centers centers; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + freq = centers.synth_center; + + if (freq < 4800) { + u32 txctl; + + if (((freq - 2192) % 5) == 0) { + channelSel = ((freq - 672) * 2 - 3040) / 10; + bModeSynth = 0; + } else if (((freq - 2224) % 5) == 0) { + channelSel = ((freq - 704) * 2 - 3040) / 10; + bModeSynth = 1; + } else { + ath_print(common, ATH_DBG_FATAL, + "Invalid channel %u MHz\n", freq); + return -EINVAL; + } + + channelSel = (channelSel << 2) & 0xff; + channelSel = ath9k_hw_reverse_bits(channelSel, 8); + + txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + + REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); + } + + } else if ((freq % 20) == 0 && freq >= 5120) { + channelSel = + ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8); + aModeRefSel = ath9k_hw_reverse_bits(1, 2); + } else if ((freq % 10) == 0) { + channelSel = + ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8); + if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) + aModeRefSel = ath9k_hw_reverse_bits(2, 2); + else + aModeRefSel = ath9k_hw_reverse_bits(1, 2); + } else if ((freq % 5) == 0) { + channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); + aModeRefSel = ath9k_hw_reverse_bits(1, 2); + } else { + ath_print(common, ATH_DBG_FATAL, + "Invalid channel %u MHz\n", freq); + return -EINVAL; + } + + ar5008_hw_force_bias(ah, freq); + + reg32 = + (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 5) | 0x1; + + REG_WRITE(ah, AR_PHY(0x37), reg32); + + ah->curchan = chan; + ah->curchan_rad_index = -1; + + return 0; +} + +/** + * ar5008_hw_spur_mitigate - convert baseband spur frequency for external radios + * @ah: atheros hardware structure + * @chan: + * + * For non single-chip solutions. Converts to baseband spur frequency given the + * input channel frequency and compute register settings below. + */ +static void ar5008_hw_spur_mitigate(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + int bb_spur = AR_NO_SPUR; + int bin, cur_bin; + int spur_freq_sd; + int spur_delta_phase; + int denominator; + int upper, lower, cur_vit_mask; + int tmp, new; + int i; + int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 + }; + int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 + }; + int inc[4] = { 0, 100, 0, 0 }; + + int8_t mask_m[123]; + int8_t mask_p[123]; + int8_t mask_amt; + int tmp_mask; + int cur_bb_spur; + bool is2GHz = IS_CHAN_2GHZ(chan); + + memset(&mask_m, 0, sizeof(int8_t) * 123); + memset(&mask_p, 0, sizeof(int8_t) * 123); + + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { + cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); + if (AR_NO_SPUR == cur_bb_spur) + break; + cur_bb_spur = cur_bb_spur - (chan->channel * 10); + if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { + bb_spur = cur_bb_spur; + break; + } + } + + if (AR_NO_SPUR == bb_spur) + return; + + bin = bb_spur * 32; + + tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); + new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | + AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + + REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new); + + new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | + AR_PHY_SPUR_REG_ENABLE_MASK_PPM | + AR_PHY_SPUR_REG_MASK_RATE_SELECT | + AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | + SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); + REG_WRITE(ah, AR_PHY_SPUR_REG, new); + + spur_delta_phase = ((bb_spur * 524288) / 100) & + AR_PHY_TIMING11_SPUR_DELTA_PHASE; + + denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; + spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; + + new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | + SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | + SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); + REG_WRITE(ah, AR_PHY_TIMING11, new); + + cur_bin = -6000; + upper = bin + 100; + lower = bin - 100; + + for (i = 0; i < 4; i++) { + int pilot_mask = 0; + int chan_mask = 0; + int bp = 0; + for (bp = 0; bp < 30; bp++) { + if ((cur_bin > lower) && (cur_bin < upper)) { + pilot_mask = pilot_mask | 0x1 << bp; + chan_mask = chan_mask | 0x1 << bp; + } + cur_bin += 100; + } + cur_bin += inc[i]; + REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); + REG_WRITE(ah, chan_mask_reg[i], chan_mask); + } + + cur_vit_mask = 6100; + upper = bin + 120; + lower = bin - 120; + + for (i = 0; i < 123; i++) { + if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { + + /* workaround for gcc bug #37014 */ + volatile int tmp_v = abs(cur_vit_mask - bin); + + if (tmp_v < 75) + mask_amt = 1; + else + mask_amt = 0; + if (cur_vit_mask < 0) + mask_m[abs(cur_vit_mask / 100)] = mask_amt; + else + mask_p[cur_vit_mask / 100] = mask_amt; + } + cur_vit_mask -= 100; + } + + tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) + | (mask_m[48] << 26) | (mask_m[49] << 24) + | (mask_m[50] << 22) | (mask_m[51] << 20) + | (mask_m[52] << 18) | (mask_m[53] << 16) + | (mask_m[54] << 14) | (mask_m[55] << 12) + | (mask_m[56] << 10) | (mask_m[57] << 8) + | (mask_m[58] << 6) | (mask_m[59] << 4) + | (mask_m[60] << 2) | (mask_m[61] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); + REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); + + tmp_mask = (mask_m[31] << 28) + | (mask_m[32] << 26) | (mask_m[33] << 24) + | (mask_m[34] << 22) | (mask_m[35] << 20) + | (mask_m[36] << 18) | (mask_m[37] << 16) + | (mask_m[48] << 14) | (mask_m[39] << 12) + | (mask_m[40] << 10) | (mask_m[41] << 8) + | (mask_m[42] << 6) | (mask_m[43] << 4) + | (mask_m[44] << 2) | (mask_m[45] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); + + tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) + | (mask_m[18] << 26) | (mask_m[18] << 24) + | (mask_m[20] << 22) | (mask_m[20] << 20) + | (mask_m[22] << 18) | (mask_m[22] << 16) + | (mask_m[24] << 14) | (mask_m[24] << 12) + | (mask_m[25] << 10) | (mask_m[26] << 8) + | (mask_m[27] << 6) | (mask_m[28] << 4) + | (mask_m[29] << 2) | (mask_m[30] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); + + tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) + | (mask_m[2] << 26) | (mask_m[3] << 24) + | (mask_m[4] << 22) | (mask_m[5] << 20) + | (mask_m[6] << 18) | (mask_m[7] << 16) + | (mask_m[8] << 14) | (mask_m[9] << 12) + | (mask_m[10] << 10) | (mask_m[11] << 8) + | (mask_m[12] << 6) | (mask_m[13] << 4) + | (mask_m[14] << 2) | (mask_m[15] << 0); + REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); + + tmp_mask = (mask_p[15] << 28) + | (mask_p[14] << 26) | (mask_p[13] << 24) + | (mask_p[12] << 22) | (mask_p[11] << 20) + | (mask_p[10] << 18) | (mask_p[9] << 16) + | (mask_p[8] << 14) | (mask_p[7] << 12) + | (mask_p[6] << 10) | (mask_p[5] << 8) + | (mask_p[4] << 6) | (mask_p[3] << 4) + | (mask_p[2] << 2) | (mask_p[1] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); + + tmp_mask = (mask_p[30] << 28) + | (mask_p[29] << 26) | (mask_p[28] << 24) + | (mask_p[27] << 22) | (mask_p[26] << 20) + | (mask_p[25] << 18) | (mask_p[24] << 16) + | (mask_p[23] << 14) | (mask_p[22] << 12) + | (mask_p[21] << 10) | (mask_p[20] << 8) + | (mask_p[19] << 6) | (mask_p[18] << 4) + | (mask_p[17] << 2) | (mask_p[16] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); + + tmp_mask = (mask_p[45] << 28) + | (mask_p[44] << 26) | (mask_p[43] << 24) + | (mask_p[42] << 22) | (mask_p[41] << 20) + | (mask_p[40] << 18) | (mask_p[39] << 16) + | (mask_p[38] << 14) | (mask_p[37] << 12) + | (mask_p[36] << 10) | (mask_p[35] << 8) + | (mask_p[34] << 6) | (mask_p[33] << 4) + | (mask_p[32] << 2) | (mask_p[31] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); + + tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) + | (mask_p[59] << 26) | (mask_p[58] << 24) + | (mask_p[57] << 22) | (mask_p[56] << 20) + | (mask_p[55] << 18) | (mask_p[54] << 16) + | (mask_p[53] << 14) | (mask_p[52] << 12) + | (mask_p[51] << 10) | (mask_p[50] << 8) + | (mask_p[49] << 6) | (mask_p[48] << 4) + | (mask_p[47] << 2) | (mask_p[46] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); +} + +/** + * ar5008_hw_rf_alloc_ext_banks - allocates banks for external radio programming + * @ah: atheros hardware structure + * + * Only required for older devices with external AR2133/AR5133 radios. + */ +static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah) +{ +#define ATH_ALLOC_BANK(bank, size) do { \ + bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \ + if (!bank) { \ + ath_print(common, ATH_DBG_FATAL, \ + "Cannot allocate RF banks\n"); \ + return -ENOMEM; \ + } \ + } while (0); + + struct ath_common *common = ath9k_hw_common(ah); + + BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); + + ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows); + ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows); + ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows); + ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows); + ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows); + ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows); + ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows); + ATH_ALLOC_BANK(ah->addac5416_21, + ah->iniAddac.ia_rows * ah->iniAddac.ia_columns); + ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows); + + return 0; +#undef ATH_ALLOC_BANK +} + + +/** + * ar5008_hw_rf_free_ext_banks - Free memory for analog bank scratch buffers + * @ah: atheros hardware struture + * For the external AR2133/AR5133 radios banks. + */ +static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah) +{ +#define ATH_FREE_BANK(bank) do { \ + kfree(bank); \ + bank = NULL; \ + } while (0); + + BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); + + ATH_FREE_BANK(ah->analogBank0Data); + ATH_FREE_BANK(ah->analogBank1Data); + ATH_FREE_BANK(ah->analogBank2Data); + ATH_FREE_BANK(ah->analogBank3Data); + ATH_FREE_BANK(ah->analogBank6Data); + ATH_FREE_BANK(ah->analogBank6TPCData); + ATH_FREE_BANK(ah->analogBank7Data); + ATH_FREE_BANK(ah->addac5416_21); + ATH_FREE_BANK(ah->bank6Temp); + +#undef ATH_FREE_BANK +} + +/* * + * ar5008_hw_set_rf_regs - programs rf registers based on EEPROM + * @ah: atheros hardware structure + * @chan: + * @modesIndex: + * + * Used for the external AR2133/AR5133 radios. + * + * Reads the EEPROM header info from the device structure and programs + * all rf registers. This routine requires access to the analog + * rf device. This is not required for single-chip devices. + */ +static bool ar5008_hw_set_rf_regs(struct ath_hw *ah, + struct ath9k_channel *chan, + u16 modesIndex) +{ + u32 eepMinorRev; + u32 ob5GHz = 0, db5GHz = 0; + u32 ob2GHz = 0, db2GHz = 0; + int regWrites = 0; + + /* + * Software does not need to program bank data + * for single chip devices, that is AR9280 or anything + * after that. + */ + if (AR_SREV_9280_10_OR_LATER(ah)) + return true; + + /* Setup rf parameters */ + eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); + + /* Setup Bank 0 Write */ + RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); + + /* Setup Bank 1 Write */ + RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); + + /* Setup Bank 2 Write */ + RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); + + /* Setup Bank 6 Write */ + RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, + modesIndex); + { + int i; + for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) { + ah->analogBank6Data[i] = + INI_RA(&ah->iniBank6TPC, i, modesIndex); + } + } + + /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ + if (eepMinorRev >= 2) { + if (IS_CHAN_2GHZ(chan)) { + ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2); + db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2); + ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, + ob2GHz, 3, 197, 0); + ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, + db2GHz, 3, 194, 0); + } else { + ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5); + db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5); + ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, + ob5GHz, 3, 203, 0); + ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, + db5GHz, 3, 200, 0); + } + } + + /* Setup Bank 7 Setup */ + RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); + + /* Write Analog registers */ + REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, + regWrites); + REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data, + regWrites); + REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data, + regWrites); + REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data, + regWrites); + REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data, + regWrites); + REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data, + regWrites); + + return true; +} + +static void ar5008_hw_init_bb(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + u32 synthDelay; + + synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IS_CHAN_B(chan)) + synthDelay = (4 * synthDelay) / 22; + else + synthDelay /= 10; + + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + + udelay(synthDelay + BASE_ACTIVATE_DELAY); +} + +static void ar5008_hw_init_chain_masks(struct ath_hw *ah) +{ + int rx_chainmask, tx_chainmask; + + rx_chainmask = ah->rxchainmask; + tx_chainmask = ah->txchainmask; + + switch (rx_chainmask) { + case 0x5: + REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, + AR_PHY_SWAP_ALT_CHAIN); + case 0x3: + if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) { + REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); + REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7); + break; + } + case 0x1: + case 0x2: + case 0x7: + REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); + REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); + break; + default: + break; + } + + REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); + if (tx_chainmask == 0x5) { + REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, + AR_PHY_SWAP_ALT_CHAIN); + } + if (AR_SREV_9100(ah)) + REG_WRITE(ah, AR_PHY_ANALOG_SWAP, + REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001); +} + +static void ar5008_hw_override_ini(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + u32 val; + + /* + * Set the RX_ABORT and RX_DIS and clear if off only after + * RXE is set for MAC. This prevents frames with corrupted + * descriptor status. + */ + REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); + + if (AR_SREV_9280_10_OR_LATER(ah)) { + val = REG_READ(ah, AR_PCU_MISC_MODE2); + + if (!AR_SREV_9271(ah)) + val &= ~AR_PCU_MISC_MODE2_HWWAR1; + + if (AR_SREV_9287_10_OR_LATER(ah)) + val = val & (~AR_PCU_MISC_MODE2_HWWAR2); + + REG_WRITE(ah, AR_PCU_MISC_MODE2, val); + } + + if (!AR_SREV_5416_20_OR_LATER(ah) || + AR_SREV_9280_10_OR_LATER(ah)) + return; + /* + * Disable BB clock gating + * Necessary to avoid issues on AR5416 2.0 + */ + REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); + + /* + * Disable RIFS search on some chips to avoid baseband + * hang issues. + */ + if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) { + val = REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS); + val &= ~AR_PHY_RIFS_INIT_DELAY; + REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val); + } +} + +static void ar5008_hw_set_channel_regs(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + u32 phymode; + u32 enableDacFifo = 0; + + if (AR_SREV_9285_10_OR_LATER(ah)) + enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) & + AR_PHY_FC_ENABLE_DAC_FIFO); + + phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40 + | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo; + + if (IS_CHAN_HT40(chan)) { + phymode |= AR_PHY_FC_DYN2040_EN; + + if ((chan->chanmode == CHANNEL_A_HT40PLUS) || + (chan->chanmode == CHANNEL_G_HT40PLUS)) + phymode |= AR_PHY_FC_DYN2040_PRI_CH; + + } + REG_WRITE(ah, AR_PHY_TURBO, phymode); + + ath9k_hw_set11nmac2040(ah); + + REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); + REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); +} + + +static int ar5008_hw_process_ini(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + int i, regWrites = 0; + struct ieee80211_channel *channel = chan->chan; + u32 modesIndex, freqIndex; + + switch (chan->chanmode) { + case CHANNEL_A: + case CHANNEL_A_HT20: + modesIndex = 1; + freqIndex = 1; + break; + case CHANNEL_A_HT40PLUS: + case CHANNEL_A_HT40MINUS: + modesIndex = 2; + freqIndex = 1; + break; + case CHANNEL_G: + case CHANNEL_G_HT20: + case CHANNEL_B: + modesIndex = 4; + freqIndex = 2; + break; + case CHANNEL_G_HT40PLUS: + case CHANNEL_G_HT40MINUS: + modesIndex = 3; + freqIndex = 2; + break; + + default: + return -EINVAL; + } + + if (AR_SREV_9287_12_OR_LATER(ah)) { + /* Enable ASYNC FIFO */ + REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, + AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); + REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); + REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, + AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); + REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, + AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); + } + + /* + * Set correct baseband to analog shift setting to + * access analog chips. + */ + REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Write ADDAC shifts */ + REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); + ah->eep_ops->set_addac(ah, chan); + + if (AR_SREV_5416_22_OR_LATER(ah)) { + REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); + } else { + struct ar5416IniArray temp; + u32 addacSize = + sizeof(u32) * ah->iniAddac.ia_rows * + ah->iniAddac.ia_columns; + + /* For AR5416 2.0/2.1 */ + memcpy(ah->addac5416_21, + ah->iniAddac.ia_array, addacSize); + + /* override CLKDRV value at [row, column] = [31, 1] */ + (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0; + + temp.ia_array = ah->addac5416_21; + temp.ia_columns = ah->iniAddac.ia_columns; + temp.ia_rows = ah->iniAddac.ia_rows; + REG_WRITE_ARRAY(&temp, 1, regWrites); + } + + REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); + + for (i = 0; i < ah->iniModes.ia_rows; i++) { + u32 reg = INI_RA(&ah->iniModes, i, 0); + u32 val = INI_RA(&ah->iniModes, i, modesIndex); + + if (reg == AR_AN_TOP2 && ah->need_an_top2_fixup) + val &= ~AR_AN_TOP2_PWDCLKIND; + + REG_WRITE(ah, reg, val); + + if (reg >= 0x7800 && reg < 0x78a0 + && ah->config.analog_shiftreg) { + udelay(100); + } + + DO_DELAY(regWrites); + } + + if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah)) + REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); + + if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) || + AR_SREV_9287_10_OR_LATER(ah)) + REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); + + if (AR_SREV_9271_10(ah)) + REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only, + modesIndex, regWrites); + + /* Write common array parameters */ + for (i = 0; i < ah->iniCommon.ia_rows; i++) { + u32 reg = INI_RA(&ah->iniCommon, i, 0); + u32 val = INI_RA(&ah->iniCommon, i, 1); + + REG_WRITE(ah, reg, val); + + if (reg >= 0x7800 && reg < 0x78a0 + && ah->config.analog_shiftreg) { + udelay(100); + } + + DO_DELAY(regWrites); + } + + if (AR_SREV_9271(ah)) { + if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1) + REG_WRITE_ARRAY(&ah->iniModes_high_power_tx_gain_9271, + modesIndex, regWrites); + else + REG_WRITE_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, + modesIndex, regWrites); + } + + REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); + + if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { + REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, + regWrites); + } + + ar5008_hw_override_ini(ah, chan); + ar5008_hw_set_channel_regs(ah, chan); + ar5008_hw_init_chain_masks(ah); + ath9k_olc_init(ah); + + /* Set TX power */ + ah->eep_ops->set_txpower(ah, chan, + ath9k_regd_get_ctl(regulatory, chan), + channel->max_antenna_gain * 2, + channel->max_power * 2, + min((u32) MAX_RATE_POWER, + (u32) regulatory->power_limit)); + + /* Write analog registers */ + if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { + ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, + "ar5416SetRfRegs failed\n"); + return -EIO; + } + + return 0; +} + +static void ar5008_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan) +{ + u32 rfMode = 0; + + if (chan == NULL) + return; + + rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) + ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; + + if (!AR_SREV_9280_10_OR_LATER(ah)) + rfMode |= (IS_CHAN_5GHZ(chan)) ? + AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; + + if ((AR_SREV_9280_20(ah) || AR_SREV_9300_20_OR_LATER(ah)) + && IS_CHAN_A_5MHZ_SPACED(chan)) + rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); + + REG_WRITE(ah, AR_PHY_MODE, rfMode); +} + +static void ar5008_hw_mark_phy_inactive(struct ath_hw *ah) +{ + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); +} + +static void ar5008_hw_set_delta_slope(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + u32 coef_scaled, ds_coef_exp, ds_coef_man; + u32 clockMhzScaled = 0x64000000; + struct chan_centers centers; + + if (IS_CHAN_HALF_RATE(chan)) + clockMhzScaled = clockMhzScaled >> 1; + else if (IS_CHAN_QUARTER_RATE(chan)) + clockMhzScaled = clockMhzScaled >> 2; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + coef_scaled = clockMhzScaled / centers.synth_center; + + ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, + &ds_coef_exp); + + REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_MAN, ds_coef_man); + REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); + + coef_scaled = (9 * coef_scaled) / 10; + + ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, + &ds_coef_exp); + + REG_RMW_FIELD(ah, AR_PHY_HALFGI, + AR_PHY_HALFGI_DSC_MAN, ds_coef_man); + REG_RMW_FIELD(ah, AR_PHY_HALFGI, + AR_PHY_HALFGI_DSC_EXP, ds_coef_exp); +} + +static bool ar5008_hw_rfbus_req(struct ath_hw *ah) +{ + REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); + return ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, + AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT); +} + +static void ar5008_hw_rfbus_done(struct ath_hw *ah) +{ + u32 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IS_CHAN_B(ah->curchan)) + synthDelay = (4 * synthDelay) / 22; + else + synthDelay /= 10; + + udelay(synthDelay + BASE_ACTIVATE_DELAY); + + REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); +} + +static void ar5008_hw_enable_rfkill(struct ath_hw *ah) +{ + REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, + AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); + + REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, + AR_GPIO_INPUT_MUX2_RFSILENT); + + ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); + REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); +} + +static void ar5008_restore_chainmask(struct ath_hw *ah) +{ + int rx_chainmask = ah->rxchainmask; + + if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) { + REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); + REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); + } +} + +static void ar5008_set_diversity(struct ath_hw *ah, bool value) +{ + u32 v = REG_READ(ah, AR_PHY_CCK_DETECT); + if (value) + v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; + else + v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; + REG_WRITE(ah, AR_PHY_CCK_DETECT, v); +} + +void ar5008_hw_attach_phy_ops(struct ath_hw *ah) +{ + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + + priv_ops->rf_set_freq = ar5008_hw_set_channel; + priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate; + + priv_ops->rf_alloc_ext_banks = ar5008_hw_rf_alloc_ext_banks; + priv_ops->rf_free_ext_banks = ar5008_hw_rf_free_ext_banks; + priv_ops->set_rf_regs = ar5008_hw_set_rf_regs; + priv_ops->set_channel_regs = ar5008_hw_set_channel_regs; + priv_ops->init_bb = ar5008_hw_init_bb; + priv_ops->process_ini = ar5008_hw_process_ini; + priv_ops->set_rfmode = ar5008_hw_set_rfmode; + priv_ops->mark_phy_inactive = ar5008_hw_mark_phy_inactive; + priv_ops->set_delta_slope = ar5008_hw_set_delta_slope; + priv_ops->rfbus_req = ar5008_hw_rfbus_req; + priv_ops->rfbus_done = ar5008_hw_rfbus_done; + priv_ops->enable_rfkill = ar5008_hw_enable_rfkill; + priv_ops->restore_chainmask = ar5008_restore_chainmask; + priv_ops->set_diversity = ar5008_set_diversity; +} diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c new file mode 100644 index 000000000000..29b50ca0a0cc --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: Programming Atheros 802.11n analog front end radios + * + * AR5416 MAC based PCI devices and AR518 MAC based PCI-Express + * devices have either an external AR2133 analog front end radio for single + * band 2.4 GHz communication or an AR5133 analog front end radio for dual + * band 2.4 GHz / 5 GHz communication. + * + * All devices after the AR5416 and AR5418 family starting with the AR9280 + * have their analog front radios, MAC/BB and host PCIe/USB interface embedded + * into a single-chip and require less programming. + * + * The following single-chips exist with a respective embedded radio: + * + * AR9280 - 11n dual-band 2x2 MIMO for PCIe + * AR9281 - 11n single-band 1x2 MIMO for PCIe + * AR9285 - 11n single-band 1x1 for PCIe + * AR9287 - 11n single-band 2x2 MIMO for PCIe + * + * AR9220 - 11n dual-band 2x2 MIMO for PCI + * AR9223 - 11n single-band 2x2 MIMO for PCI + * + * AR9287 - 11n single-band 1x1 MIMO for USB + */ + +#include "hw.h" +#include "ar9002_phy.h" + +/** + * ar9002_hw_set_channel - set channel on single-chip device + * @ah: atheros hardware structure + * @chan: + * + * This is the function to change channel on single-chip devices, that is + * all devices after ar9280. + * + * This function takes the channel value in MHz and sets + * hardware channel value. Assumes writes have been enabled to analog bus. + * + * Actual Expression, + * + * For 2GHz channel, + * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) + * (freq_ref = 40MHz) + * + * For 5GHz channel, + * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) + * (freq_ref = 40MHz/(24>>amodeRefSel)) + */ +static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) +{ + u16 bMode, fracMode, aModeRefSel = 0; + u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; + struct chan_centers centers; + u32 refDivA = 24; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + freq = centers.synth_center; + + reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); + reg32 &= 0xc0000000; + + if (freq < 4800) { /* 2 GHz, fractional mode */ + u32 txctl; + int regWrites = 0; + + bMode = 1; + fracMode = 1; + aModeRefSel = 0; + channelSel = (freq * 0x10000) / 15; + + if (AR_SREV_9287_11_OR_LATER(ah)) { + if (freq == 2484) { + /* Enable channel spreading for channel 14 */ + REG_WRITE_ARRAY(&ah->iniCckfirJapan2484, + 1, regWrites); + } else { + REG_WRITE_ARRAY(&ah->iniCckfirNormal, + 1, regWrites); + } + } else { + txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + /* Enable channel spreading for channel 14 */ + REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); + } + } + } else { + bMode = 0; + fracMode = 0; + + switch (ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) { + case 0: + if ((freq % 20) == 0) + aModeRefSel = 3; + else if ((freq % 10) == 0) + aModeRefSel = 2; + if (aModeRefSel) + break; + case 1: + default: + aModeRefSel = 0; + /* + * Enable 2G (fractional) mode for channels + * which are 5MHz spaced. + */ + fracMode = 1; + refDivA = 1; + channelSel = (freq * 0x8000) / 15; + + /* RefDivA setting */ + REG_RMW_FIELD(ah, AR_AN_SYNTH9, + AR_AN_SYNTH9_REFDIVA, refDivA); + + } + + if (!fracMode) { + ndiv = (freq * (refDivA >> aModeRefSel)) / 60; + channelSel = ndiv & 0x1ff; + channelFrac = (ndiv & 0xfffffe00) * 2; + channelSel = (channelSel << 17) | channelFrac; + } + } + + reg32 = reg32 | + (bMode << 29) | + (fracMode << 28) | (aModeRefSel << 26) | (channelSel); + + REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); + + ah->curchan = chan; + ah->curchan_rad_index = -1; + + return 0; +} + +/** + * ar9002_hw_spur_mitigate - convert baseband spur frequency + * @ah: atheros hardware structure + * @chan: + * + * For single-chip solutions. Converts to baseband spur frequency given the + * input channel frequency and compute register settings below. + */ +static void ar9002_hw_spur_mitigate(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + int bb_spur = AR_NO_SPUR; + int freq; + int bin, cur_bin; + int bb_spur_off, spur_subchannel_sd; + int spur_freq_sd; + int spur_delta_phase; + int denominator; + int upper, lower, cur_vit_mask; + int tmp, newVal; + int i; + int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 + }; + int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 + }; + int inc[4] = { 0, 100, 0, 0 }; + struct chan_centers centers; + + int8_t mask_m[123]; + int8_t mask_p[123]; + int8_t mask_amt; + int tmp_mask; + int cur_bb_spur; + bool is2GHz = IS_CHAN_2GHZ(chan); + + memset(&mask_m, 0, sizeof(int8_t) * 123); + memset(&mask_p, 0, sizeof(int8_t) * 123); + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + freq = centers.synth_center; + + ah->config.spurmode = SPUR_ENABLE_EEPROM; + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { + cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); + + if (is2GHz) + cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; + else + cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; + + if (AR_NO_SPUR == cur_bb_spur) + break; + cur_bb_spur = cur_bb_spur - freq; + + if (IS_CHAN_HT40(chan)) { + if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && + (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { + bb_spur = cur_bb_spur; + break; + } + } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && + (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { + bb_spur = cur_bb_spur; + break; + } + } + + if (AR_NO_SPUR == bb_spur) { + REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, + AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); + return; + } else { + REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, + AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); + } + + bin = bb_spur * 320; + + tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); + + newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | + AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal); + + newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | + AR_PHY_SPUR_REG_ENABLE_MASK_PPM | + AR_PHY_SPUR_REG_MASK_RATE_SELECT | + AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | + SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); + REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); + + if (IS_CHAN_HT40(chan)) { + if (bb_spur < 0) { + spur_subchannel_sd = 1; + bb_spur_off = bb_spur + 10; + } else { + spur_subchannel_sd = 0; + bb_spur_off = bb_spur - 10; + } + } else { + spur_subchannel_sd = 0; + bb_spur_off = bb_spur; + } + + if (IS_CHAN_HT40(chan)) + spur_delta_phase = + ((bb_spur * 262144) / + 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; + else + spur_delta_phase = + ((bb_spur * 524288) / + 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; + + denominator = IS_CHAN_2GHZ(chan) ? 44 : 40; + spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; + + newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | + SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | + SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); + REG_WRITE(ah, AR_PHY_TIMING11, newVal); + + newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; + REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); + + cur_bin = -6000; + upper = bin + 100; + lower = bin - 100; + + for (i = 0; i < 4; i++) { + int pilot_mask = 0; + int chan_mask = 0; + int bp = 0; + for (bp = 0; bp < 30; bp++) { + if ((cur_bin > lower) && (cur_bin < upper)) { + pilot_mask = pilot_mask | 0x1 << bp; + chan_mask = chan_mask | 0x1 << bp; + } + cur_bin += 100; + } + cur_bin += inc[i]; + REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); + REG_WRITE(ah, chan_mask_reg[i], chan_mask); + } + + cur_vit_mask = 6100; + upper = bin + 120; + lower = bin - 120; + + for (i = 0; i < 123; i++) { + if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { + + /* workaround for gcc bug #37014 */ + volatile int tmp_v = abs(cur_vit_mask - bin); + + if (tmp_v < 75) + mask_amt = 1; + else + mask_amt = 0; + if (cur_vit_mask < 0) + mask_m[abs(cur_vit_mask / 100)] = mask_amt; + else + mask_p[cur_vit_mask / 100] = mask_amt; + } + cur_vit_mask -= 100; + } + + tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) + | (mask_m[48] << 26) | (mask_m[49] << 24) + | (mask_m[50] << 22) | (mask_m[51] << 20) + | (mask_m[52] << 18) | (mask_m[53] << 16) + | (mask_m[54] << 14) | (mask_m[55] << 12) + | (mask_m[56] << 10) | (mask_m[57] << 8) + | (mask_m[58] << 6) | (mask_m[59] << 4) + | (mask_m[60] << 2) | (mask_m[61] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); + REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); + + tmp_mask = (mask_m[31] << 28) + | (mask_m[32] << 26) | (mask_m[33] << 24) + | (mask_m[34] << 22) | (mask_m[35] << 20) + | (mask_m[36] << 18) | (mask_m[37] << 16) + | (mask_m[48] << 14) | (mask_m[39] << 12) + | (mask_m[40] << 10) | (mask_m[41] << 8) + | (mask_m[42] << 6) | (mask_m[43] << 4) + | (mask_m[44] << 2) | (mask_m[45] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); + + tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) + | (mask_m[18] << 26) | (mask_m[18] << 24) + | (mask_m[20] << 22) | (mask_m[20] << 20) + | (mask_m[22] << 18) | (mask_m[22] << 16) + | (mask_m[24] << 14) | (mask_m[24] << 12) + | (mask_m[25] << 10) | (mask_m[26] << 8) + | (mask_m[27] << 6) | (mask_m[28] << 4) + | (mask_m[29] << 2) | (mask_m[30] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); + + tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) + | (mask_m[2] << 26) | (mask_m[3] << 24) + | (mask_m[4] << 22) | (mask_m[5] << 20) + | (mask_m[6] << 18) | (mask_m[7] << 16) + | (mask_m[8] << 14) | (mask_m[9] << 12) + | (mask_m[10] << 10) | (mask_m[11] << 8) + | (mask_m[12] << 6) | (mask_m[13] << 4) + | (mask_m[14] << 2) | (mask_m[15] << 0); + REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); + + tmp_mask = (mask_p[15] << 28) + | (mask_p[14] << 26) | (mask_p[13] << 24) + | (mask_p[12] << 22) | (mask_p[11] << 20) + | (mask_p[10] << 18) | (mask_p[9] << 16) + | (mask_p[8] << 14) | (mask_p[7] << 12) + | (mask_p[6] << 10) | (mask_p[5] << 8) + | (mask_p[4] << 6) | (mask_p[3] << 4) + | (mask_p[2] << 2) | (mask_p[1] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); + + tmp_mask = (mask_p[30] << 28) + | (mask_p[29] << 26) | (mask_p[28] << 24) + | (mask_p[27] << 22) | (mask_p[26] << 20) + | (mask_p[25] << 18) | (mask_p[24] << 16) + | (mask_p[23] << 14) | (mask_p[22] << 12) + | (mask_p[21] << 10) | (mask_p[20] << 8) + | (mask_p[19] << 6) | (mask_p[18] << 4) + | (mask_p[17] << 2) | (mask_p[16] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); + + tmp_mask = (mask_p[45] << 28) + | (mask_p[44] << 26) | (mask_p[43] << 24) + | (mask_p[42] << 22) | (mask_p[41] << 20) + | (mask_p[40] << 18) | (mask_p[39] << 16) + | (mask_p[38] << 14) | (mask_p[37] << 12) + | (mask_p[36] << 10) | (mask_p[35] << 8) + | (mask_p[34] << 6) | (mask_p[33] << 4) + | (mask_p[32] << 2) | (mask_p[31] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); + + tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) + | (mask_p[59] << 26) | (mask_p[58] << 24) + | (mask_p[57] << 22) | (mask_p[56] << 20) + | (mask_p[55] << 18) | (mask_p[54] << 16) + | (mask_p[53] << 14) | (mask_p[52] << 12) + | (mask_p[51] << 10) | (mask_p[50] << 8) + | (mask_p[49] << 6) | (mask_p[48] << 4) + | (mask_p[47] << 2) | (mask_p[46] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); +} + +static void ar9002_olc_init(struct ath_hw *ah) +{ + u32 i; + + if (!OLC_FOR_AR9280_20_LATER) + return; + + if (OLC_FOR_AR9287_10_LATER) { + REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9, + AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL); + ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0, + AR9287_AN_TXPC0_TXPCMODE, + AR9287_AN_TXPC0_TXPCMODE_S, + AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE); + udelay(100); + } else { + for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) + ah->originalGain[i] = + MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4), + AR_PHY_TX_GAIN); + ah->PDADCdelta = 0; + } +} + +void ar9002_hw_attach_phy_ops(struct ath_hw *ah) +{ + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + + priv_ops->set_rf_regs = NULL; + priv_ops->rf_alloc_ext_banks = NULL; + priv_ops->rf_free_ext_banks = NULL; + priv_ops->rf_set_freq = ar9002_hw_set_channel; + priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate; + priv_ops->olc_init = ar9002_olc_init; +} diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h new file mode 100644 index 000000000000..4fe204ed3a7c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h @@ -0,0 +1,581 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef AR9002_PHY_H +#define AR9002_PHY_H + +#define AR_PHY_TEST 0x9800 +#define PHY_AGC_CLR 0x10000000 +#define RFSILENT_BB 0x00002000 + +#define AR_PHY_TURBO 0x9804 +#define AR_PHY_FC_TURBO_MODE 0x00000001 +#define AR_PHY_FC_TURBO_SHORT 0x00000002 +#define AR_PHY_FC_DYN2040_EN 0x00000004 +#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008 +#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010 +/* For 25 MHz channel spacing -- not used but supported by hw */ +#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020 +#define AR_PHY_FC_HT_EN 0x00000040 +#define AR_PHY_FC_SHORT_GI_40 0x00000080 +#define AR_PHY_FC_WALSH 0x00000100 +#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200 +#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800 + +#define AR_PHY_TEST2 0x9808 + +#define AR_PHY_TIMING2 0x9810 +#define AR_PHY_TIMING3 0x9814 +#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 +#define AR_PHY_TIMING3_DSC_MAN_S 17 +#define AR_PHY_TIMING3_DSC_EXP 0x0001E000 +#define AR_PHY_TIMING3_DSC_EXP_S 13 + +#define AR_PHY_CHIP_ID_REV_0 0x80 +#define AR_PHY_CHIP_ID_REV_1 0x81 +#define AR_PHY_CHIP_ID_9160_REV_0 0xb0 + +#define AR_PHY_ACTIVE 0x981C +#define AR_PHY_ACTIVE_EN 0x00000001 +#define AR_PHY_ACTIVE_DIS 0x00000000 + +#define AR_PHY_RF_CTL2 0x9824 +#define AR_PHY_TX_END_DATA_START 0x000000FF +#define AR_PHY_TX_END_DATA_START_S 0 +#define AR_PHY_TX_END_PA_ON 0x0000FF00 +#define AR_PHY_TX_END_PA_ON_S 8 + +#define AR_PHY_RF_CTL3 0x9828 +#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000 +#define AR_PHY_TX_END_TO_A2_RX_ON_S 16 + +#define AR_PHY_ADC_CTL 0x982C +#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003 +#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0 +#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000 +#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000 +#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000 +#define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000 +#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16 + +#define AR_PHY_ADC_SERIAL_CTL 0x9830 +#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000 +#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001 + +#define AR_PHY_RF_CTL4 0x9834 +#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000 +#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24 +#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000 +#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16 +#define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00 +#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8 +#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF +#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0 + +#define AR_PHY_TSTDAC_CONST 0x983c + +#define AR_PHY_SETTLING 0x9844 +#define AR_PHY_SETTLING_SWITCH 0x00003F80 +#define AR_PHY_SETTLING_SWITCH_S 7 + +#define AR_PHY_RXGAIN 0x9848 +#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000 +#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12 +#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000 +#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18 +#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80 +#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7 +#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000 +#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14 + +#define AR_PHY_DESIRED_SZ 0x9850 +#define AR_PHY_DESIRED_SZ_ADC 0x000000FF +#define AR_PHY_DESIRED_SZ_ADC_S 0 +#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00 +#define AR_PHY_DESIRED_SZ_PGA_S 8 +#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000 +#define AR_PHY_DESIRED_SZ_TOT_DES_S 20 + +#define AR_PHY_FIND_SIG 0x9858 +#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000 +#define AR_PHY_FIND_SIG_FIRSTEP_S 12 +#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000 +#define AR_PHY_FIND_SIG_FIRPWR_S 18 + +#define AR_PHY_AGC_CTL1 0x985C +#define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80 +#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7 +#define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000 +#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15 + +#define AR_PHY_AGC_CONTROL 0x9860 +#define AR_PHY_AGC_CONTROL_CAL 0x00000001 +#define AR_PHY_AGC_CONTROL_NF 0x00000002 +#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 +#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 +#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 + +#define AR_PHY_CCA 0x9864 +#define AR_PHY_MINCCA_PWR 0x0FF80000 +#define AR_PHY_MINCCA_PWR_S 19 +#define AR_PHY_CCA_THRESH62 0x0007F000 +#define AR_PHY_CCA_THRESH62_S 12 +#define AR9280_PHY_MINCCA_PWR 0x1FF00000 +#define AR9280_PHY_MINCCA_PWR_S 20 +#define AR9280_PHY_CCA_THRESH62 0x000FF000 +#define AR9280_PHY_CCA_THRESH62_S 12 + +#define AR_PHY_SFCORR_LOW 0x986C +#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001 +#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00 +#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8 +#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000 +#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14 +#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000 +#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21 + +#define AR_PHY_SFCORR 0x9868 +#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F +#define AR_PHY_SFCORR_M2COUNT_THR_S 0 +#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000 +#define AR_PHY_SFCORR_M1_THRESH_S 17 +#define AR_PHY_SFCORR_M2_THRESH 0x7F000000 +#define AR_PHY_SFCORR_M2_THRESH_S 24 + +#define AR_PHY_SLEEP_CTR_CONTROL 0x9870 +#define AR_PHY_SLEEP_CTR_LIMIT 0x9874 +#define AR_PHY_SYNTH_CONTROL 0x9874 +#define AR_PHY_SLEEP_SCAL 0x9878 + +#define AR_PHY_PLL_CTL 0x987c +#define AR_PHY_PLL_CTL_40 0xaa +#define AR_PHY_PLL_CTL_40_5413 0x04 +#define AR_PHY_PLL_CTL_44 0xab +#define AR_PHY_PLL_CTL_44_2133 0xeb +#define AR_PHY_PLL_CTL_40_2133 0xea + +#define AR_PHY_SPECTRAL_SCAN 0x9910 /* AR9280 spectral scan configuration register */ +#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1 +#define AR_PHY_SPECTRAL_SCAN_ENA 0x00000001 /* Enable spectral scan, reg 68, bit 0 */ +#define AR_PHY_SPECTRAL_SCAN_ENA_S 0 /* Enable spectral scan, reg 68, bit 0 */ +#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 /* Activate spectral scan reg 68, bit 1*/ +#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 /* Activate spectral scan reg 68, bit 1*/ +#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 /* Interval for FFT reports, reg 68, bits 4-7*/ +#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4 +#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 /* Interval for FFT reports, reg 68, bits 8-15*/ +#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8 +#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 /* Number of reports, reg 68, bits 16-23*/ +#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16 +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 /* Short repeat, reg 68, bit 24*/ +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 /* Short repeat, reg 68, bit 24*/ + +#define AR_PHY_RX_DELAY 0x9914 +#define AR_PHY_SEARCH_START_DELAY 0x9918 +#define AR_PHY_RX_DELAY_DELAY 0x00003FFF + +#define AR_PHY_TIMING_CTRL4(_i) (0x9920 + ((_i) << 12)) +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0 +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0 +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 +#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800 +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000 +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 +#define AR_PHY_TIMING_CTRL4_DO_CAL 0x10000 + +#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000 +#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000 +#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000 +#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000 + +#define AR_PHY_TIMING5 0x9924 +#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE +#define AR_PHY_TIMING5_CYCPWR_THR1_S 1 + +#define AR_PHY_POWER_TX_RATE1 0x9934 +#define AR_PHY_POWER_TX_RATE2 0x9938 +#define AR_PHY_POWER_TX_RATE_MAX 0x993c +#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040 + +#define AR_PHY_FRAME_CTL 0x9944 +#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038 +#define AR_PHY_FRAME_CTL_TX_CLIP_S 3 + +#define AR_PHY_TXPWRADJ 0x994C +#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0 +#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6 +#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000 +#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18 + +#define AR_PHY_RADAR_EXT 0x9940 +#define AR_PHY_RADAR_EXT_ENA 0x00004000 + +#define AR_PHY_RADAR_0 0x9954 +#define AR_PHY_RADAR_0_ENA 0x00000001 +#define AR_PHY_RADAR_0_FFT_ENA 0x80000000 +#define AR_PHY_RADAR_0_INBAND 0x0000003e +#define AR_PHY_RADAR_0_INBAND_S 1 +#define AR_PHY_RADAR_0_PRSSI 0x00000FC0 +#define AR_PHY_RADAR_0_PRSSI_S 6 +#define AR_PHY_RADAR_0_HEIGHT 0x0003F000 +#define AR_PHY_RADAR_0_HEIGHT_S 12 +#define AR_PHY_RADAR_0_RRSSI 0x00FC0000 +#define AR_PHY_RADAR_0_RRSSI_S 18 +#define AR_PHY_RADAR_0_FIRPWR 0x7F000000 +#define AR_PHY_RADAR_0_FIRPWR_S 24 + +#define AR_PHY_RADAR_1 0x9958 +#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000 +#define AR_PHY_RADAR_1_USE_FIR128 0x00400000 +#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000 +#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16 +#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000 +#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000 +#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000 +#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00 +#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8 +#define AR_PHY_RADAR_1_MAXLEN 0x000000FF +#define AR_PHY_RADAR_1_MAXLEN_S 0 + +#define AR_PHY_SWITCH_CHAIN_0 0x9960 +#define AR_PHY_SWITCH_COM 0x9964 + +#define AR_PHY_SIGMA_DELTA 0x996C +#define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003 +#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0 +#define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8 +#define AR_PHY_SIGMA_DELTA_FILT2_S 3 +#define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00 +#define AR_PHY_SIGMA_DELTA_FILT1_S 8 +#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000 +#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13 + +#define AR_PHY_RESTART 0x9970 +#define AR_PHY_RESTART_DIV_GC 0x001C0000 +#define AR_PHY_RESTART_DIV_GC_S 18 + +#define AR_PHY_RFBUS_REQ 0x997C +#define AR_PHY_RFBUS_REQ_EN 0x00000001 + +#define AR_PHY_TIMING7 0x9980 +#define AR_PHY_TIMING8 0x9984 +#define AR_PHY_TIMING8_PILOT_MASK_2 0x000FFFFF +#define AR_PHY_TIMING8_PILOT_MASK_2_S 0 + +#define AR_PHY_BIN_MASK2_1 0x9988 +#define AR_PHY_BIN_MASK2_2 0x998c +#define AR_PHY_BIN_MASK2_3 0x9990 +#define AR_PHY_BIN_MASK2_4 0x9994 + +#define AR_PHY_BIN_MASK_1 0x9900 +#define AR_PHY_BIN_MASK_2 0x9904 +#define AR_PHY_BIN_MASK_3 0x9908 + +#define AR_PHY_MASK_CTL 0x990c + +#define AR_PHY_BIN_MASK2_4_MASK_4 0x00003FFF +#define AR_PHY_BIN_MASK2_4_MASK_4_S 0 + +#define AR_PHY_TIMING9 0x9998 +#define AR_PHY_TIMING10 0x999c +#define AR_PHY_TIMING10_PILOT_MASK_2 0x000FFFFF +#define AR_PHY_TIMING10_PILOT_MASK_2_S 0 + +#define AR_PHY_TIMING11 0x99a0 +#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF +#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0 +#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 +#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 +#define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000 +#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000 + +#define AR_PHY_RX_CHAINMASK 0x99a4 +#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12)) +#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 +#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 + +#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac +#define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000 +#define AR_PHY_9285_ANT_DIV_CTL 0x01000000 +#define AR_PHY_9285_ANT_DIV_CTL_S 24 +#define AR_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000 +#define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S 25 +#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000 +#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27 +#define AR_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000 +#define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S 29 +#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000 +#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30 +#define AR_PHY_9285_ANT_DIV_LNA1 2 +#define AR_PHY_9285_ANT_DIV_LNA2 1 +#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3 +#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0 +#define AR_PHY_9285_ANT_DIV_GAINTB_0 0 +#define AR_PHY_9285_ANT_DIV_GAINTB_1 1 + +#define AR_PHY_EXT_CCA0 0x99b8 +#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF +#define AR_PHY_EXT_CCA0_THRESH62_S 0 + +#define AR_PHY_EXT_CCA 0x99bc +#define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00 +#define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9 +#define AR_PHY_EXT_CCA_THRESH62 0x007F0000 +#define AR_PHY_EXT_CCA_THRESH62_S 16 +#define AR_PHY_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_EXT_MINCCA_PWR_S 23 +#define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000 +#define AR9280_PHY_EXT_MINCCA_PWR_S 16 + +#define AR_PHY_SFCORR_EXT 0x99c0 +#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F +#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0 +#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80 +#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 +#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 + +#define AR_PHY_HALFGI 0x99D0 +#define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0 +#define AR_PHY_HALFGI_DSC_MAN_S 4 +#define AR_PHY_HALFGI_DSC_EXP 0x0000000F +#define AR_PHY_HALFGI_DSC_EXP_S 0 + +#define AR_PHY_CHAN_INFO_MEMORY 0x99DC +#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001 + +#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0 + +#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS 0x99EC +#define AR_PHY_RIFS_INIT_DELAY 0x03ff0000 + +#define AR_PHY_M_SLEEP 0x99f0 +#define AR_PHY_REFCLKDLY 0x99f4 +#define AR_PHY_REFCLKPD 0x99f8 + +#define AR_PHY_CALMODE 0x99f0 + +#define AR_PHY_CALMODE_IQ 0x00000000 +#define AR_PHY_CALMODE_ADC_GAIN 0x00000001 +#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002 +#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003 + +#define AR_PHY_CAL_MEAS_0(_i) (0x9c10 + ((_i) << 12)) +#define AR_PHY_CAL_MEAS_1(_i) (0x9c14 + ((_i) << 12)) +#define AR_PHY_CAL_MEAS_2(_i) (0x9c18 + ((_i) << 12)) +#define AR_PHY_CAL_MEAS_3(_i) (0x9c1c + ((_i) << 12)) + +#define AR_PHY_CURRENT_RSSI 0x9c1c +#define AR9280_PHY_CURRENT_RSSI 0x9c3c + +#define AR_PHY_RFBUS_GRANT 0x9C20 +#define AR_PHY_RFBUS_GRANT_EN 0x00000001 + +#define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4 +#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 + +#define AR_PHY_CHAN_INFO_GAIN 0x9CFC + +#define AR_PHY_MODE 0xA200 +#define AR_PHY_MODE_ASYNCFIFO 0x80 +#define AR_PHY_MODE_AR2133 0x08 +#define AR_PHY_MODE_AR5111 0x00 +#define AR_PHY_MODE_AR5112 0x08 +#define AR_PHY_MODE_DYNAMIC 0x04 +#define AR_PHY_MODE_RF2GHZ 0x02 +#define AR_PHY_MODE_RF5GHZ 0x00 +#define AR_PHY_MODE_CCK 0x01 +#define AR_PHY_MODE_OFDM 0x00 +#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100 + +#define AR_PHY_CCK_TX_CTRL 0xA204 +#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 +#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C +#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2 + +#define AR_PHY_CCK_DETECT 0xA208 +#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F +#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0 +/* [12:6] settling time for antenna switch */ +#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 +#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6 +#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 +#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13 + +#define AR_PHY_GAIN_2GHZ 0xA20C +#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000 +#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18 +#define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00 +#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10 +#define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F +#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0 + +#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003E0000 +#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17 +#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001F000 +#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12 +#define AR_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000FC0 +#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S 6 +#define AR_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003F +#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S 0 + +#define AR_PHY_CCK_RXCTRL4 0xA21C +#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000 +#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19 + +#define AR_PHY_DAG_CTRLCCK 0xA228 +#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200 +#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00 +#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10 + +#define AR_PHY_FORCE_CLKEN_CCK 0xA22C +#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040 + +#define AR_PHY_POWER_TX_RATE3 0xA234 +#define AR_PHY_POWER_TX_RATE4 0xA238 + +#define AR_PHY_SCRM_SEQ_XR 0xA23C +#define AR_PHY_HEADER_DETECT_XR 0xA240 +#define AR_PHY_CHIRP_DETECTED_XR 0xA244 +#define AR_PHY_BLUETOOTH 0xA254 + +#define AR_PHY_TPCRG1 0xA258 +#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000 +#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14 + +#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000 +#define AR_PHY_TPCRG1_PD_GAIN_1_S 16 +#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000 +#define AR_PHY_TPCRG1_PD_GAIN_2_S 18 +#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 +#define AR_PHY_TPCRG1_PD_GAIN_3_S 20 + +#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000 +#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22 + +#define AR_PHY_TX_PWRCTRL4 0xa264 +#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001 +#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0 +#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE +#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1 + +#define AR_PHY_TX_PWRCTRL6_0 0xa270 +#define AR_PHY_TX_PWRCTRL6_1 0xb270 +#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000 +#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 + +#define AR_PHY_TX_PWRCTRL7 0xa274 +#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 +#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 + +#define AR_PHY_TX_PWRCTRL9 0xa27C +#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 +#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 +#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 +#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 + +#define AR_PHY_TX_GAIN_TBL1 0xa300 +#define AR_PHY_TX_GAIN 0x0007F000 +#define AR_PHY_TX_GAIN_S 12 + +#define AR_PHY_CH0_TX_PWRCTRL11 0xa398 +#define AR_PHY_CH1_TX_PWRCTRL11 0xb398 +#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00 +#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 + +#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 +#define AR_PHY_MASK2_M_31_45 0xa3a4 +#define AR_PHY_MASK2_M_16_30 0xa3a8 +#define AR_PHY_MASK2_M_00_15 0xa3ac +#define AR_PHY_MASK2_P_15_01 0xa3b8 +#define AR_PHY_MASK2_P_30_16 0xa3bc +#define AR_PHY_MASK2_P_45_31 0xa3c0 +#define AR_PHY_MASK2_P_61_45 0xa3c4 +#define AR_PHY_SPUR_REG 0x994c + +#define AR_PHY_SPUR_REG_MASK_RATE_CNTL (0xFF << 18) +#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18 + +#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000 +#define AR_PHY_SPUR_REG_MASK_RATE_SELECT (0xFF << 9) +#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S 9 +#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100 +#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7F +#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0 + +#define AR_PHY_PILOT_MASK_01_30 0xa3b0 +#define AR_PHY_PILOT_MASK_31_60 0xa3b4 + +#define AR_PHY_CHANNEL_MASK_01_30 0x99d4 +#define AR_PHY_CHANNEL_MASK_31_60 0x99d8 + +#define AR_PHY_ANALOG_SWAP 0xa268 +#define AR_PHY_SWAP_ALT_CHAIN 0x00000040 + +#define AR_PHY_TPCRG5 0xA26C +#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F +#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22 + +/* Carrier leak calibration control, do it after AGC calibration */ +#define AR_PHY_CL_CAL_CTL 0xA358 +#define AR_PHY_CL_CAL_ENABLE 0x00000002 +#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001 + +#define AR_PHY_POWER_TX_RATE5 0xA38C +#define AR_PHY_POWER_TX_RATE6 0xA390 + +#define AR_PHY_CAL_CHAINMASK 0xA39C + +#define AR_PHY_POWER_TX_SUB 0xA3C8 +#define AR_PHY_POWER_TX_RATE7 0xA3CC +#define AR_PHY_POWER_TX_RATE8 0xA3D0 +#define AR_PHY_POWER_TX_RATE9 0xA3D4 + +#define AR_PHY_XPA_CFG 0xA3D8 +#define AR_PHY_FORCE_XPA_CFG 0x000000001 +#define AR_PHY_FORCE_XPA_CFG_S 0 + +#define AR_PHY_CH1_CCA 0xa864 +#define AR_PHY_CH1_MINCCA_PWR 0x0FF80000 +#define AR_PHY_CH1_MINCCA_PWR_S 19 +#define AR9280_PHY_CH1_MINCCA_PWR 0x1FF00000 +#define AR9280_PHY_CH1_MINCCA_PWR_S 20 + +#define AR_PHY_CH2_CCA 0xb864 +#define AR_PHY_CH2_MINCCA_PWR 0x0FF80000 +#define AR_PHY_CH2_MINCCA_PWR_S 19 + +#define AR_PHY_CH1_EXT_CCA 0xa9bc +#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23 +#define AR9280_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000 +#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16 + +#define AR_PHY_CH2_EXT_CCA 0xb9bc +#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23 + +#endif diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 064f5b51dfcd..eba85adb7cd3 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -15,6 +15,7 @@ */ #include "hw.h" +#include "ar9002_phy.h" /* We can tune this as we go by monitoring really low values */ #define ATH9K_NF_TOO_LOW -60 diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 0354fe50f8e0..97279a5e01e8 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -15,6 +15,7 @@ */ #include "hw.h" +#include "ar9002_phy.h" static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah) { diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index d8ca94c3fa0c..e57c5b48c039 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -15,6 +15,7 @@ */ #include "hw.h" +#include "ar9002_phy.h" static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah) { diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 404a0341242c..99f16a3a5be8 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -15,6 +15,7 @@ */ #include "hw.h" +#include "ar9002_phy.h" static void ath9k_get_txgain_index(struct ath_hw *ah, struct ath9k_channel *chan, diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index ee33146cda15..81f3d03f0dbf 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -28,4 +28,117 @@ static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah, ath9k_hw_ops(ah)->config_pci_powersave(ah, restore, power_off); } +/* Private hardware call ops */ + +/* PHY ops */ + +static inline int ath9k_hw_rf_set_freq(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + return ath9k_hw_private_ops(ah)->rf_set_freq(ah, chan); +} + +static inline void ath9k_hw_spur_mitigate_freq(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + ath9k_hw_private_ops(ah)->spur_mitigate_freq(ah, chan); +} + +static inline int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah) +{ + if (!ath9k_hw_private_ops(ah)->rf_alloc_ext_banks) + return 0; + + return ath9k_hw_private_ops(ah)->rf_alloc_ext_banks(ah); +} + +static inline void ath9k_hw_rf_free_ext_banks(struct ath_hw *ah) +{ + if (!ath9k_hw_private_ops(ah)->rf_free_ext_banks) + return; + + ath9k_hw_private_ops(ah)->rf_free_ext_banks(ah); +} + +static inline bool ath9k_hw_set_rf_regs(struct ath_hw *ah, + struct ath9k_channel *chan, + u16 modesIndex) +{ + if (!ath9k_hw_private_ops(ah)->set_rf_regs) + return true; + + return ath9k_hw_private_ops(ah)->set_rf_regs(ah, chan, modesIndex); +} + +static inline void ath9k_hw_init_bb(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + return ath9k_hw_private_ops(ah)->init_bb(ah, chan); +} + +static inline void ath9k_hw_set_channel_regs(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + return ath9k_hw_private_ops(ah)->set_channel_regs(ah, chan); +} + +static inline int ath9k_hw_process_ini(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + return ath9k_hw_private_ops(ah)->process_ini(ah, chan); +} + +static inline void ath9k_olc_init(struct ath_hw *ah) +{ + if (!ath9k_hw_private_ops(ah)->olc_init) + return; + + return ath9k_hw_private_ops(ah)->olc_init(ah); +} + +static inline void ath9k_hw_set_rfmode(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + return ath9k_hw_private_ops(ah)->set_rfmode(ah, chan); +} + +static inline void ath9k_hw_mark_phy_inactive(struct ath_hw *ah) +{ + return ath9k_hw_private_ops(ah)->mark_phy_inactive(ah); +} + +static inline void ath9k_hw_set_delta_slope(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + return ath9k_hw_private_ops(ah)->set_delta_slope(ah, chan); +} + +static inline bool ath9k_hw_rfbus_req(struct ath_hw *ah) +{ + return ath9k_hw_private_ops(ah)->rfbus_req(ah); +} + +static inline void ath9k_hw_rfbus_done(struct ath_hw *ah) +{ + return ath9k_hw_private_ops(ah)->rfbus_done(ah); +} + +static inline void ath9k_enable_rfkill(struct ath_hw *ah) +{ + return ath9k_hw_private_ops(ah)->enable_rfkill(ah); +} + +static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah) +{ + if (!ath9k_hw_private_ops(ah)->restore_chainmask) + return; + + return ath9k_hw_private_ops(ah)->restore_chainmask(ah); +} + +static inline void ath9k_hw_set_diversity(struct ath_hw *ah, bool value) +{ + return ath9k_hw_private_ops(ah)->set_diversity(ah, value); +} + #endif /* ATH9K_HW_OPS_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 6f447cdbd05c..2ab061381fcf 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -29,7 +29,6 @@ static void ar9002_hw_attach_ops(struct ath_hw *ah); static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); -static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan); MODULE_AUTHOR("Atheros Communications"); MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); @@ -535,14 +534,12 @@ static int ath9k_hw_post_init(struct ath_hw *ah) ah->eep_ops->get_eeprom_ver(ah), ah->eep_ops->get_eeprom_rev(ah)); - if (!AR_SREV_9280_10_OR_LATER(ah)) { - ecode = ath9k_hw_rf_alloc_ext_banks(ah); - if (ecode) { - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "Failed allocating banks for " - "external radio\n"); - return ecode; - } + ecode = ath9k_hw_rf_alloc_ext_banks(ah); + if (ecode) { + ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, + "Failed allocating banks for " + "external radio\n"); + return ecode; } if (!AR_SREV_9100(ah)) { @@ -913,20 +910,12 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (AR_SREV_9271(ah)) ah->is_pciexpress = false; - /* XXX: move this to its own hw op */ ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); - ath9k_hw_init_cal_settings(ah); ah->ani_function = ATH9K_ANI_ALL; - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9280_10_OR_LATER(ah)) ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; - ah->ath9k_hw_rf_set_freq = &ath9k_hw_ar9280_set_channel; - ah->ath9k_hw_spur_mitigate_freq = &ath9k_hw_9280_spur_mitigate; - } else { - ah->ath9k_hw_rf_set_freq = &ath9k_hw_set_channel; - ah->ath9k_hw_spur_mitigate_freq = &ath9k_hw_spur_mitigate; - } ath9k_hw_init_mode_regs(ah); @@ -1014,22 +1003,6 @@ int ath9k_hw_init(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_init); -static void ath9k_hw_init_bb(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - u32 synthDelay; - - synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; - if (IS_CHAN_B(chan)) - synthDelay = (4 * synthDelay) / 22; - else - synthDelay /= 10; - - REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); - - udelay(synthDelay + BASE_ACTIVATE_DELAY); -} - static void ath9k_hw_init_qos(struct ath_hw *ah) { REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa); @@ -1121,43 +1094,6 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); } -static void ath9k_hw_init_chain_masks(struct ath_hw *ah) -{ - int rx_chainmask, tx_chainmask; - - rx_chainmask = ah->rxchainmask; - tx_chainmask = ah->txchainmask; - - switch (rx_chainmask) { - case 0x5: - REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, - AR_PHY_SWAP_ALT_CHAIN); - case 0x3: - if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) { - REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); - REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7); - break; - } - case 0x1: - case 0x2: - case 0x7: - REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); - REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); - break; - default: - break; - } - - REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); - if (tx_chainmask == 0x5) { - REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, - AR_PHY_SWAP_ALT_CHAIN); - } - if (AR_SREV_9100(ah)) - REG_WRITE(ah, AR_PHY_ANALOG_SWAP, - REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001); -} - static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, enum nl80211_iftype opmode) { @@ -1277,8 +1213,7 @@ void ath9k_hw_deinit(struct ath_hw *ah) ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); free_hw: - if (!AR_SREV_9280_10_OR_LATER(ah)) - ath9k_hw_rf_free_ext_banks(ah); + ath9k_hw_rf_free_ext_banks(ah); } EXPORT_SYMBOL(ath9k_hw_deinit); @@ -1286,73 +1221,7 @@ EXPORT_SYMBOL(ath9k_hw_deinit); /* INI */ /*******/ -static void ath9k_hw_override_ini(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - u32 val; - - /* - * Set the RX_ABORT and RX_DIS and clear if off only after - * RXE is set for MAC. This prevents frames with corrupted - * descriptor status. - */ - REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); - - if (AR_SREV_9280_10_OR_LATER(ah)) { - val = REG_READ(ah, AR_PCU_MISC_MODE2); - - if (!AR_SREV_9271(ah)) - val &= ~AR_PCU_MISC_MODE2_HWWAR1; - - if (AR_SREV_9287_10_OR_LATER(ah)) - val = val & (~AR_PCU_MISC_MODE2_HWWAR2); - - REG_WRITE(ah, AR_PCU_MISC_MODE2, val); - } - - if (!AR_SREV_5416_20_OR_LATER(ah) || - AR_SREV_9280_10_OR_LATER(ah)) - return; - /* - * Disable BB clock gating - * Necessary to avoid issues on AR5416 2.0 - */ - REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); - - /* - * Disable RIFS search on some chips to avoid baseband - * hang issues. - */ - if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) { - val = REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS); - val &= ~AR_PHY_RIFS_INIT_DELAY; - REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val); - } -} - -static void ath9k_olc_init(struct ath_hw *ah) -{ - u32 i; - - if (OLC_FOR_AR9287_10_LATER) { - REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9, - AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0, - AR9287_AN_TXPC0_TXPCMODE, - AR9287_AN_TXPC0_TXPCMODE_S, - AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE); - udelay(100); - } else { - for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) - ah->originalGain[i] = - MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4), - AR_PHY_TX_GAIN); - ah->PDADCdelta = 0; - } -} - -static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, - struct ath9k_channel *chan) +u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan) { u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band); @@ -1366,184 +1235,10 @@ static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, return ctl; } -static int ath9k_hw_process_ini(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - int i, regWrites = 0; - struct ieee80211_channel *channel = chan->chan; - u32 modesIndex, freqIndex; - - switch (chan->chanmode) { - case CHANNEL_A: - case CHANNEL_A_HT20: - modesIndex = 1; - freqIndex = 1; - break; - case CHANNEL_A_HT40PLUS: - case CHANNEL_A_HT40MINUS: - modesIndex = 2; - freqIndex = 1; - break; - case CHANNEL_G: - case CHANNEL_G_HT20: - case CHANNEL_B: - modesIndex = 4; - freqIndex = 2; - break; - case CHANNEL_G_HT40PLUS: - case CHANNEL_G_HT40MINUS: - modesIndex = 3; - freqIndex = 2; - break; - - default: - return -EINVAL; - } - - /* Set correct baseband to analog shift setting to access analog chips */ - REG_WRITE(ah, AR_PHY(0), 0x00000007); - - /* Write ADDAC shifts */ - REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); - ah->eep_ops->set_addac(ah, chan); - - if (AR_SREV_5416_22_OR_LATER(ah)) { - REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); - } else { - struct ar5416IniArray temp; - u32 addacSize = - sizeof(u32) * ah->iniAddac.ia_rows * - ah->iniAddac.ia_columns; - - /* For AR5416 2.0/2.1 */ - memcpy(ah->addac5416_21, - ah->iniAddac.ia_array, addacSize); - - /* override CLKDRV value at [row, column] = [31, 1] */ - (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0; - - temp.ia_array = ah->addac5416_21; - temp.ia_columns = ah->iniAddac.ia_columns; - temp.ia_rows = ah->iniAddac.ia_rows; - REG_WRITE_ARRAY(&temp, 1, regWrites); - } - - REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); - - for (i = 0; i < ah->iniModes.ia_rows; i++) { - u32 reg = INI_RA(&ah->iniModes, i, 0); - u32 val = INI_RA(&ah->iniModes, i, modesIndex); - - if (reg == AR_AN_TOP2 && ah->need_an_top2_fixup) - val &= ~AR_AN_TOP2_PWDCLKIND; - - REG_WRITE(ah, reg, val); - - if (reg >= 0x7800 && reg < 0x78a0 - && ah->config.analog_shiftreg) { - udelay(100); - } - - DO_DELAY(regWrites); - } - - if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah)) - REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); - - if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) || - AR_SREV_9287_10_OR_LATER(ah)) - REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); - - if (AR_SREV_9271_10(ah)) - REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only, - modesIndex, regWrites); - - /* Write common array parameters */ - for (i = 0; i < ah->iniCommon.ia_rows; i++) { - u32 reg = INI_RA(&ah->iniCommon, i, 0); - u32 val = INI_RA(&ah->iniCommon, i, 1); - - REG_WRITE(ah, reg, val); - - if (reg >= 0x7800 && reg < 0x78a0 - && ah->config.analog_shiftreg) { - udelay(100); - } - - DO_DELAY(regWrites); - } - - if (AR_SREV_9271(ah)) { - if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1) - REG_WRITE_ARRAY(&ah->iniModes_high_power_tx_gain_9271, - modesIndex, regWrites); - else - REG_WRITE_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, - modesIndex, regWrites); - } - - REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); - - if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { - REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, - regWrites); - } - - ath9k_hw_override_ini(ah, chan); - ath9k_hw_set_regs(ah, chan); - ath9k_hw_init_chain_masks(ah); - - if (OLC_FOR_AR9280_20_LATER) - ath9k_olc_init(ah); - - /* Set TX power */ - ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(regulatory, chan), - channel->max_antenna_gain * 2, - channel->max_power * 2, - min((u32) MAX_RATE_POWER, - (u32) regulatory->power_limit)); - - /* Write analog registers */ - if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "ar5416SetRfRegs failed\n"); - return -EIO; - } - - return 0; -} - /****************************************/ /* Reset and Channel Switching Routines */ /****************************************/ -static void ath9k_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan) -{ - u32 rfMode = 0; - - if (chan == NULL) - return; - - rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) - ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; - - if (!AR_SREV_9280_10_OR_LATER(ah)) - rfMode |= (IS_CHAN_5GHZ(chan)) ? - AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; - - if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) - rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); - - REG_WRITE(ah, AR_PHY_MODE, rfMode); -} - -static void ath9k_hw_mark_phy_inactive(struct ath_hw *ah) -{ - REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); -} - static inline void ath9k_hw_set_dma(struct ath_hw *ah) { u32 regval; @@ -1620,10 +1315,8 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) } } -static inline void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, - u32 coef_scaled, - u32 *coef_mantissa, - u32 *coef_exponent) +void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, + u32 *coef_mantissa, u32 *coef_exponent) { u32 coef_exp, coef_man; @@ -1639,40 +1332,6 @@ static inline void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, *coef_exponent = coef_exp - 16; } -static void ath9k_hw_set_delta_slope(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - u32 coef_scaled, ds_coef_exp, ds_coef_man; - u32 clockMhzScaled = 0x64000000; - struct chan_centers centers; - - if (IS_CHAN_HALF_RATE(chan)) - clockMhzScaled = clockMhzScaled >> 1; - else if (IS_CHAN_QUARTER_RATE(chan)) - clockMhzScaled = clockMhzScaled >> 2; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - coef_scaled = clockMhzScaled / centers.synth_center; - - ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, - &ds_coef_exp); - - REG_RMW_FIELD(ah, AR_PHY_TIMING3, - AR_PHY_TIMING3_DSC_MAN, ds_coef_man); - REG_RMW_FIELD(ah, AR_PHY_TIMING3, - AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); - - coef_scaled = (9 * coef_scaled) / 10; - - ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, - &ds_coef_exp); - - REG_RMW_FIELD(ah, AR_PHY_HALFGI, - AR_PHY_HALFGI_DSC_MAN, ds_coef_man); - REG_RMW_FIELD(ah, AR_PHY_HALFGI, - AR_PHY_HALFGI_DSC_EXP, ds_coef_exp); -} - static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) { u32 rst_flags; @@ -1779,34 +1438,6 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) } } -static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan) -{ - u32 phymode; - u32 enableDacFifo = 0; - - if (AR_SREV_9285_10_OR_LATER(ah)) - enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) & - AR_PHY_FC_ENABLE_DAC_FIFO); - - phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40 - | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo; - - if (IS_CHAN_HT40(chan)) { - phymode |= AR_PHY_FC_DYN2040_EN; - - if ((chan->chanmode == CHANNEL_A_HT40PLUS) || - (chan->chanmode == CHANNEL_G_HT40PLUS)) - phymode |= AR_PHY_FC_DYN2040_PRI_CH; - - } - REG_WRITE(ah, AR_PHY_TURBO, phymode); - - ath9k_hw_set11nmac2040(ah); - - REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); - REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); -} - static bool ath9k_hw_chip_reset(struct ath_hw *ah, struct ath9k_channel *chan) { @@ -1832,7 +1463,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_channel *channel = chan->chan; - u32 synthDelay, qnum; + u32 qnum; int r; for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { @@ -1844,17 +1475,15 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, } } - REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); - if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, - AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) { + if (!ath9k_hw_rfbus_req(ah)) { ath_print(common, ATH_DBG_FATAL, "Could not kill baseband RX\n"); return false; } - ath9k_hw_set_regs(ah, chan); + ath9k_hw_set_channel_regs(ah, chan); - r = ah->ath9k_hw_rf_set_freq(ah, chan); + r = ath9k_hw_rf_set_freq(ah, chan); if (r) { ath_print(common, ATH_DBG_FATAL, "Failed to set channel\n"); @@ -1868,20 +1497,12 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, min((u32) MAX_RATE_POWER, (u32) regulatory->power_limit)); - synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; - if (IS_CHAN_B(chan)) - synthDelay = (4 * synthDelay) / 22; - else - synthDelay /= 10; - - udelay(synthDelay + BASE_ACTIVATE_DELAY); - - REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); + ath9k_hw_rfbus_done(ah); if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) ath9k_hw_set_delta_slope(ah, chan); - ah->ath9k_hw_spur_mitigate_freq(ah, chan); + ath9k_hw_spur_mitigate_freq(ah, chan); if (!chan->oneTimeCalsDone) chan->oneTimeCalsDone = true; @@ -1889,18 +1510,6 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, return true; } -static void ath9k_enable_rfkill(struct ath_hw *ah) -{ - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, - AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); - - REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, - AR_GPIO_INPUT_MUX2_RFSILENT); - - ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); - REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); -} - int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, bool bChannelChange) { @@ -1910,7 +1519,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, u32 saveDefAntenna; u32 macStaId1; u64 tsf = 0; - int i, rx_chainmask, r; + int i, r; ah->txchainmask = common->tx_chainmask; ah->rxchainmask = common->rx_chainmask; @@ -1982,16 +1591,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (AR_SREV_9280_10_OR_LATER(ah)) REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); - if (AR_SREV_9287_12_OR_LATER(ah)) { - /* Enable ASYNC FIFO */ - REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, - AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); - REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); - REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, - AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); - REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, - AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); - } r = ath9k_hw_process_ini(ah, chan); if (r) return r; @@ -2016,7 +1615,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) ath9k_hw_set_delta_slope(ah, chan); - ah->ath9k_hw_spur_mitigate_freq(ah, chan); + ath9k_hw_spur_mitigate_freq(ah, chan); ah->eep_ops->set_board_values(ah, chan); REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); @@ -2038,7 +1637,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); - r = ah->ath9k_hw_rf_set_freq(ah, chan); + r = ath9k_hw_rf_set_freq(ah, chan); if (r) return r; @@ -2095,12 +1694,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (!ath9k_hw_init_cal(ah, chan)) return -EIO; - rx_chainmask = ah->rxchainmask; - if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) { - REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); - REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); - } - + ath9k_hw_restore_chainmask(ah); REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); /* @@ -3322,10 +2916,6 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, case ATH9K_CAP_TKIP_SPLIT: return (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ? false : true; - case ATH9K_CAP_DIVERSITY: - return (REG_READ(ah, AR_PHY_CCK_DETECT) & - AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ? - true : false; case ATH9K_CAP_MCAST_KEYSRCH: switch (capability) { case 0: @@ -3368,8 +2958,6 @@ EXPORT_SYMBOL(ath9k_hw_getcapability); bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, u32 capability, u32 setting, int *status) { - u32 v; - switch (type) { case ATH9K_CAP_TKIP_MIC: if (setting) @@ -3379,14 +2967,6 @@ bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, ah->sta_id1_defaults &= ~AR_STA_ID1_CRPT_MIC_ENABLE; return true; - case ATH9K_CAP_DIVERSITY: - v = REG_READ(ah, AR_PHY_CCK_DETECT); - if (setting) - v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; - else - v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; - REG_WRITE(ah, AR_PHY_CCK_DETECT, v); - return true; case ATH9K_CAP_MCAST_KEYSRCH: if (setting) ah->sta_id1_defaults |= AR_STA_ID1_MCAST_KSRCH; @@ -3981,4 +3561,9 @@ static void ar9002_hw_attach_ops(struct ath_hw *ah) priv_ops->macversion_supported = ar9002_hw_macversion_supported; ops->config_pci_powersave = ar9002_hw_configpcipowersave; + + if (AR_SREV_9280_10_OR_LATER(ah)) + ar9002_hw_attach_phy_ops(ah); + else + ar5008_hw_attach_phy_ops(ah); } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index dfe8502866bb..d740e9cc721c 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -171,7 +171,6 @@ enum ath9k_capability_type { ATH9K_CAP_CIPHER = 0, ATH9K_CAP_TKIP_MIC, ATH9K_CAP_TKIP_SPLIT, - ATH9K_CAP_DIVERSITY, ATH9K_CAP_TXPOW, ATH9K_CAP_MCAST_KEYSRCH, ATH9K_CAP_DS @@ -449,11 +448,41 @@ struct ath_gen_timer_table { * @init_cal_settings: Initializes calibration settings * @init_mode_regs: Initializes mode registers * @macversion_supported: If this specific mac revision is supported + * + * @rf_set_freq: change frequency + * @spur_mitigate_freq: spur mitigation + * @rf_alloc_ext_banks: + * @rf_free_ext_banks: + * @set_rf_regs: */ struct ath_hw_private_ops { void (*init_cal_settings)(struct ath_hw *ah); void (*init_mode_regs)(struct ath_hw *ah); bool (*macversion_supported)(u32 macversion); + + /* PHY ops */ + int (*rf_set_freq)(struct ath_hw *ah, + struct ath9k_channel *chan); + void (*spur_mitigate_freq)(struct ath_hw *ah, + struct ath9k_channel *chan); + int (*rf_alloc_ext_banks)(struct ath_hw *ah); + void (*rf_free_ext_banks)(struct ath_hw *ah); + bool (*set_rf_regs)(struct ath_hw *ah, + struct ath9k_channel *chan, + u16 modesIndex); + void (*set_channel_regs)(struct ath_hw *ah, struct ath9k_channel *chan); + void (*init_bb)(struct ath_hw *ah, + struct ath9k_channel *chan); + int (*process_ini)(struct ath_hw *ah, struct ath9k_channel *chan); + void (*olc_init)(struct ath_hw *ah); + void (*set_rfmode)(struct ath_hw *ah, struct ath9k_channel *chan); + void (*mark_phy_inactive)(struct ath_hw *ah); + void (*set_delta_slope)(struct ath_hw *ah, struct ath9k_channel *chan); + bool (*rfbus_req)(struct ath_hw *ah); + void (*rfbus_done)(struct ath_hw *ah); + void (*enable_rfkill)(struct ath_hw *ah); + void (*restore_chainmask)(struct ath_hw *ah); + void (*set_diversity)(struct ath_hw *ah, bool value); }; /** @@ -563,13 +592,6 @@ struct ath_hw { DONT_USE_32KHZ, } enable_32kHz_clock; - /* Callback for radio frequency change */ - int (*ath9k_hw_rf_set_freq)(struct ath_hw *ah, struct ath9k_channel *chan); - - /* Callback for baseband spur frequency */ - void (*ath9k_hw_spur_mitigate_freq)(struct ath_hw *ah, - struct ath9k_channel *chan); - /* Private to hardware code */ struct ath_hw_private_ops private_ops; /* Accessed by the lower level driver */ @@ -675,6 +697,7 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, u32 capability, u32 *result); bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, u32 capability, u32 setting, int *status); +u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); /* Key Cache Management */ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry); @@ -752,6 +775,13 @@ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len); /* HTC */ void ath9k_hw_htc_resetinit(struct ath_hw *ah); +/* PHY */ +void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, + u32 *coef_mantissa, u32 *coef_exponent); + +void ar9002_hw_attach_phy_ops(struct ath_hw *ah); +void ar5008_hw_attach_phy_ops(struct ath_hw *ah); + #define ATH_PCIE_CAP_LINK_CTRL 0x70 #define ATH_PCIE_CAP_LINK_L0S 1 #define ATH_PCIE_CAP_LINK_L1 2 diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 62682cc2e216..1956c611503e 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -512,7 +512,7 @@ static void ath9k_init_misc(struct ath_softc *sc) common->tx_chainmask = sc->sc_ah->caps.tx_chainmask; common->rx_chainmask = sc->sc_ah->caps.rx_chainmask; - ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); + ath9k_hw_set_diversity(sc->sc_ah, true); sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c deleted file mode 100644 index 02d40dfd3a91..000000000000 --- a/drivers/net/wireless/ath/ath9k/phy.c +++ /dev/null @@ -1,961 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/** - * DOC: Programming Atheros 802.11n analog front end radios - * - * AR5416 MAC based PCI devices and AR518 MAC based PCI-Express - * devices have either an external AR2133 analog front end radio for single - * band 2.4 GHz communication or an AR5133 analog front end radio for dual - * band 2.4 GHz / 5 GHz communication. - * - * All devices after the AR5416 and AR5418 family starting with the AR9280 - * have their analog front radios, MAC/BB and host PCIe/USB interface embedded - * into a single-chip and require less programming. - * - * The following single-chips exist with a respective embedded radio: - * - * AR9280 - 11n dual-band 2x2 MIMO for PCIe - * AR9281 - 11n single-band 1x2 MIMO for PCIe - * AR9285 - 11n single-band 1x1 for PCIe - * AR9287 - 11n single-band 2x2 MIMO for PCIe - * - * AR9220 - 11n dual-band 2x2 MIMO for PCI - * AR9223 - 11n single-band 2x2 MIMO for PCI - * - * AR9287 - 11n single-band 1x1 MIMO for USB - */ - -#include "hw.h" - -/** - * ath9k_hw_ar9280_set_channel - set channel on single-chip device - * @ah: atheros hardware structure - * @chan: - * - * This is the function to change channel on single-chip devices, that is - * all devices after ar9280. - * - * This function takes the channel value in MHz and sets - * hardware channel value. Assumes writes have been enabled to analog bus. - * - * Actual Expression, - * - * For 2GHz channel, - * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) - * (freq_ref = 40MHz) - * - * For 5GHz channel, - * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) - * (freq_ref = 40MHz/(24>>amodeRefSel)) - */ -int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) -{ - u16 bMode, fracMode, aModeRefSel = 0; - u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; - struct chan_centers centers; - u32 refDivA = 24; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = centers.synth_center; - - reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); - reg32 &= 0xc0000000; - - if (freq < 4800) { /* 2 GHz, fractional mode */ - u32 txctl; - int regWrites = 0; - - bMode = 1; - fracMode = 1; - aModeRefSel = 0; - channelSel = (freq * 0x10000) / 15; - - if (AR_SREV_9287_11_OR_LATER(ah)) { - if (freq == 2484) { - /* Enable channel spreading for channel 14 */ - REG_WRITE_ARRAY(&ah->iniCckfirJapan2484, - 1, regWrites); - } else { - REG_WRITE_ARRAY(&ah->iniCckfirNormal, - 1, regWrites); - } - } else { - txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); - if (freq == 2484) { - /* Enable channel spreading for channel 14 */ - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl | AR_PHY_CCK_TX_CTRL_JAPAN); - } else { - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); - } - } - } else { - bMode = 0; - fracMode = 0; - - switch(ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) { - case 0: - if ((freq % 20) == 0) { - aModeRefSel = 3; - } else if ((freq % 10) == 0) { - aModeRefSel = 2; - } - if (aModeRefSel) - break; - case 1: - default: - aModeRefSel = 0; - /* - * Enable 2G (fractional) mode for channels - * which are 5MHz spaced. - */ - fracMode = 1; - refDivA = 1; - channelSel = (freq * 0x8000) / 15; - - /* RefDivA setting */ - REG_RMW_FIELD(ah, AR_AN_SYNTH9, - AR_AN_SYNTH9_REFDIVA, refDivA); - - } - - if (!fracMode) { - ndiv = (freq * (refDivA >> aModeRefSel)) / 60; - channelSel = ndiv & 0x1ff; - channelFrac = (ndiv & 0xfffffe00) * 2; - channelSel = (channelSel << 17) | channelFrac; - } - } - - reg32 = reg32 | - (bMode << 29) | - (fracMode << 28) | (aModeRefSel << 26) | (channelSel); - - REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); - - ah->curchan = chan; - ah->curchan_rad_index = -1; - - return 0; -} - -/** - * ath9k_hw_9280_spur_mitigate - convert baseband spur frequency - * @ah: atheros hardware structure - * @chan: - * - * For single-chip solutions. Converts to baseband spur frequency given the - * input channel frequency and compute register settings below. - */ -void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) -{ - int bb_spur = AR_NO_SPUR; - int freq; - int bin, cur_bin; - int bb_spur_off, spur_subchannel_sd; - int spur_freq_sd; - int spur_delta_phase; - int denominator; - int upper, lower, cur_vit_mask; - int tmp, newVal; - int i; - int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, - AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 - }; - int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, - AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 - }; - int inc[4] = { 0, 100, 0, 0 }; - struct chan_centers centers; - - int8_t mask_m[123]; - int8_t mask_p[123]; - int8_t mask_amt; - int tmp_mask; - int cur_bb_spur; - bool is2GHz = IS_CHAN_2GHZ(chan); - - memset(&mask_m, 0, sizeof(int8_t) * 123); - memset(&mask_p, 0, sizeof(int8_t) * 123); - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = centers.synth_center; - - ah->config.spurmode = SPUR_ENABLE_EEPROM; - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); - - if (is2GHz) - cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; - else - cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; - - if (AR_NO_SPUR == cur_bb_spur) - break; - cur_bb_spur = cur_bb_spur - freq; - - if (IS_CHAN_HT40(chan)) { - if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && - (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { - bb_spur = cur_bb_spur; - break; - } - } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && - (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { - bb_spur = cur_bb_spur; - break; - } - } - - if (AR_NO_SPUR == bb_spur) { - REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, - AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); - return; - } else { - REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, - AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); - } - - bin = bb_spur * 320; - - tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); - - newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | - AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | - AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | - AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal); - - newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | - AR_PHY_SPUR_REG_ENABLE_MASK_PPM | - AR_PHY_SPUR_REG_MASK_RATE_SELECT | - AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | - SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); - REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); - - if (IS_CHAN_HT40(chan)) { - if (bb_spur < 0) { - spur_subchannel_sd = 1; - bb_spur_off = bb_spur + 10; - } else { - spur_subchannel_sd = 0; - bb_spur_off = bb_spur - 10; - } - } else { - spur_subchannel_sd = 0; - bb_spur_off = bb_spur; - } - - if (IS_CHAN_HT40(chan)) - spur_delta_phase = - ((bb_spur * 262144) / - 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; - else - spur_delta_phase = - ((bb_spur * 524288) / - 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; - - denominator = IS_CHAN_2GHZ(chan) ? 44 : 40; - spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; - - newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | - SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | - SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); - REG_WRITE(ah, AR_PHY_TIMING11, newVal); - - newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; - REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); - - cur_bin = -6000; - upper = bin + 100; - lower = bin - 100; - - for (i = 0; i < 4; i++) { - int pilot_mask = 0; - int chan_mask = 0; - int bp = 0; - for (bp = 0; bp < 30; bp++) { - if ((cur_bin > lower) && (cur_bin < upper)) { - pilot_mask = pilot_mask | 0x1 << bp; - chan_mask = chan_mask | 0x1 << bp; - } - cur_bin += 100; - } - cur_bin += inc[i]; - REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); - REG_WRITE(ah, chan_mask_reg[i], chan_mask); - } - - cur_vit_mask = 6100; - upper = bin + 120; - lower = bin - 120; - - for (i = 0; i < 123; i++) { - if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { - - /* workaround for gcc bug #37014 */ - volatile int tmp_v = abs(cur_vit_mask - bin); - - if (tmp_v < 75) - mask_amt = 1; - else - mask_amt = 0; - if (cur_vit_mask < 0) - mask_m[abs(cur_vit_mask / 100)] = mask_amt; - else - mask_p[cur_vit_mask / 100] = mask_amt; - } - cur_vit_mask -= 100; - } - - tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) - | (mask_m[48] << 26) | (mask_m[49] << 24) - | (mask_m[50] << 22) | (mask_m[51] << 20) - | (mask_m[52] << 18) | (mask_m[53] << 16) - | (mask_m[54] << 14) | (mask_m[55] << 12) - | (mask_m[56] << 10) | (mask_m[57] << 8) - | (mask_m[58] << 6) | (mask_m[59] << 4) - | (mask_m[60] << 2) | (mask_m[61] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); - REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); - - tmp_mask = (mask_m[31] << 28) - | (mask_m[32] << 26) | (mask_m[33] << 24) - | (mask_m[34] << 22) | (mask_m[35] << 20) - | (mask_m[36] << 18) | (mask_m[37] << 16) - | (mask_m[48] << 14) | (mask_m[39] << 12) - | (mask_m[40] << 10) | (mask_m[41] << 8) - | (mask_m[42] << 6) | (mask_m[43] << 4) - | (mask_m[44] << 2) | (mask_m[45] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); - - tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) - | (mask_m[18] << 26) | (mask_m[18] << 24) - | (mask_m[20] << 22) | (mask_m[20] << 20) - | (mask_m[22] << 18) | (mask_m[22] << 16) - | (mask_m[24] << 14) | (mask_m[24] << 12) - | (mask_m[25] << 10) | (mask_m[26] << 8) - | (mask_m[27] << 6) | (mask_m[28] << 4) - | (mask_m[29] << 2) | (mask_m[30] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); - - tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) - | (mask_m[2] << 26) | (mask_m[3] << 24) - | (mask_m[4] << 22) | (mask_m[5] << 20) - | (mask_m[6] << 18) | (mask_m[7] << 16) - | (mask_m[8] << 14) | (mask_m[9] << 12) - | (mask_m[10] << 10) | (mask_m[11] << 8) - | (mask_m[12] << 6) | (mask_m[13] << 4) - | (mask_m[14] << 2) | (mask_m[15] << 0); - REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); - - tmp_mask = (mask_p[15] << 28) - | (mask_p[14] << 26) | (mask_p[13] << 24) - | (mask_p[12] << 22) | (mask_p[11] << 20) - | (mask_p[10] << 18) | (mask_p[9] << 16) - | (mask_p[8] << 14) | (mask_p[7] << 12) - | (mask_p[6] << 10) | (mask_p[5] << 8) - | (mask_p[4] << 6) | (mask_p[3] << 4) - | (mask_p[2] << 2) | (mask_p[1] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); - - tmp_mask = (mask_p[30] << 28) - | (mask_p[29] << 26) | (mask_p[28] << 24) - | (mask_p[27] << 22) | (mask_p[26] << 20) - | (mask_p[25] << 18) | (mask_p[24] << 16) - | (mask_p[23] << 14) | (mask_p[22] << 12) - | (mask_p[21] << 10) | (mask_p[20] << 8) - | (mask_p[19] << 6) | (mask_p[18] << 4) - | (mask_p[17] << 2) | (mask_p[16] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); - - tmp_mask = (mask_p[45] << 28) - | (mask_p[44] << 26) | (mask_p[43] << 24) - | (mask_p[42] << 22) | (mask_p[41] << 20) - | (mask_p[40] << 18) | (mask_p[39] << 16) - | (mask_p[38] << 14) | (mask_p[37] << 12) - | (mask_p[36] << 10) | (mask_p[35] << 8) - | (mask_p[34] << 6) | (mask_p[33] << 4) - | (mask_p[32] << 2) | (mask_p[31] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); - - tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) - | (mask_p[59] << 26) | (mask_p[58] << 24) - | (mask_p[57] << 22) | (mask_p[56] << 20) - | (mask_p[55] << 18) | (mask_p[54] << 16) - | (mask_p[53] << 14) | (mask_p[52] << 12) - | (mask_p[51] << 10) | (mask_p[50] << 8) - | (mask_p[49] << 6) | (mask_p[48] << 4) - | (mask_p[47] << 2) | (mask_p[46] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); -} - -/* All code below is for non single-chip solutions */ - -/** - * ath9k_phy_modify_rx_buffer() - perform analog swizzling of parameters - * @rfbuf: - * @reg32: - * @numBits: - * @firstBit: - * @column: - * - * Performs analog "swizzling" of parameters into their location. - * Used on external AR2133/AR5133 radios. - */ -static void ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, - u32 numBits, u32 firstBit, - u32 column) -{ - u32 tmp32, mask, arrayEntry, lastBit; - int32_t bitPosition, bitsLeft; - - tmp32 = ath9k_hw_reverse_bits(reg32, numBits); - arrayEntry = (firstBit - 1) / 8; - bitPosition = (firstBit - 1) % 8; - bitsLeft = numBits; - while (bitsLeft > 0) { - lastBit = (bitPosition + bitsLeft > 8) ? - 8 : bitPosition + bitsLeft; - mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << - (column * 8); - rfBuf[arrayEntry] &= ~mask; - rfBuf[arrayEntry] |= ((tmp32 << bitPosition) << - (column * 8)) & mask; - bitsLeft -= 8 - bitPosition; - tmp32 = tmp32 >> (8 - bitPosition); - bitPosition = 0; - arrayEntry++; - } -} - -/* - * Fix on 2.4 GHz band for orientation sensitivity issue by increasing - * rf_pwd_icsyndiv. - * - * Theoretical Rules: - * if 2 GHz band - * if forceBiasAuto - * if synth_freq < 2412 - * bias = 0 - * else if 2412 <= synth_freq <= 2422 - * bias = 1 - * else // synth_freq > 2422 - * bias = 2 - * else if forceBias > 0 - * bias = forceBias & 7 - * else - * no change, use value from ini file - * else - * no change, invalid band - * - * 1st Mod: - * 2422 also uses value of 2 - * - * - * 2nd Mod: - * Less than 2412 uses value of 0, 2412 and above uses value of 2 - */ -static void ath9k_hw_force_bias(struct ath_hw *ah, u16 synth_freq) -{ - struct ath_common *common = ath9k_hw_common(ah); - u32 tmp_reg; - int reg_writes = 0; - u32 new_bias = 0; - - if (!AR_SREV_5416(ah) || synth_freq >= 3000) { - return; - } - - BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); - - if (synth_freq < 2412) - new_bias = 0; - else if (synth_freq < 2422) - new_bias = 1; - else - new_bias = 2; - - /* pre-reverse this field */ - tmp_reg = ath9k_hw_reverse_bits(new_bias, 3); - - ath_print(common, ATH_DBG_CONFIG, - "Force rf_pwd_icsyndiv to %1d on %4d\n", - new_bias, synth_freq); - - /* swizzle rf_pwd_icsyndiv */ - ath9k_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3); - - /* write Bank 6 with new params */ - REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes); -} - -/** - * ath9k_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios - * @ah: atheros hardware stucture - * @chan: - * - * For the external AR2133/AR5133 radios, takes the MHz channel value and set - * the channel value. Assumes writes enabled to analog bus and bank6 register - * cache in ah->analogBank6Data. - */ -int ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) -{ - struct ath_common *common = ath9k_hw_common(ah); - u32 channelSel = 0; - u32 bModeSynth = 0; - u32 aModeRefSel = 0; - u32 reg32 = 0; - u16 freq; - struct chan_centers centers; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = centers.synth_center; - - if (freq < 4800) { - u32 txctl; - - if (((freq - 2192) % 5) == 0) { - channelSel = ((freq - 672) * 2 - 3040) / 10; - bModeSynth = 0; - } else if (((freq - 2224) % 5) == 0) { - channelSel = ((freq - 704) * 2 - 3040) / 10; - bModeSynth = 1; - } else { - ath_print(common, ATH_DBG_FATAL, - "Invalid channel %u MHz\n", freq); - return -EINVAL; - } - - channelSel = (channelSel << 2) & 0xff; - channelSel = ath9k_hw_reverse_bits(channelSel, 8); - - txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); - if (freq == 2484) { - - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl | AR_PHY_CCK_TX_CTRL_JAPAN); - } else { - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); - } - - } else if ((freq % 20) == 0 && freq >= 5120) { - channelSel = - ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8); - aModeRefSel = ath9k_hw_reverse_bits(1, 2); - } else if ((freq % 10) == 0) { - channelSel = - ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8); - if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) - aModeRefSel = ath9k_hw_reverse_bits(2, 2); - else - aModeRefSel = ath9k_hw_reverse_bits(1, 2); - } else if ((freq % 5) == 0) { - channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); - aModeRefSel = ath9k_hw_reverse_bits(1, 2); - } else { - ath_print(common, ATH_DBG_FATAL, - "Invalid channel %u MHz\n", freq); - return -EINVAL; - } - - ath9k_hw_force_bias(ah, freq); - - reg32 = - (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | - (1 << 5) | 0x1; - - REG_WRITE(ah, AR_PHY(0x37), reg32); - - ah->curchan = chan; - ah->curchan_rad_index = -1; - - return 0; -} - -/** - * ath9k_hw_spur_mitigate - convert baseband spur frequency for external radios - * @ah: atheros hardware structure - * @chan: - * - * For non single-chip solutions. Converts to baseband spur frequency given the - * input channel frequency and compute register settings below. - */ -void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) -{ - int bb_spur = AR_NO_SPUR; - int bin, cur_bin; - int spur_freq_sd; - int spur_delta_phase; - int denominator; - int upper, lower, cur_vit_mask; - int tmp, new; - int i; - int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, - AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 - }; - int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, - AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 - }; - int inc[4] = { 0, 100, 0, 0 }; - - int8_t mask_m[123]; - int8_t mask_p[123]; - int8_t mask_amt; - int tmp_mask; - int cur_bb_spur; - bool is2GHz = IS_CHAN_2GHZ(chan); - - memset(&mask_m, 0, sizeof(int8_t) * 123); - memset(&mask_p, 0, sizeof(int8_t) * 123); - - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); - if (AR_NO_SPUR == cur_bb_spur) - break; - cur_bb_spur = cur_bb_spur - (chan->channel * 10); - if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { - bb_spur = cur_bb_spur; - break; - } - } - - if (AR_NO_SPUR == bb_spur) - return; - - bin = bb_spur * 32; - - tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); - new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | - AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | - AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | - AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); - - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new); - - new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | - AR_PHY_SPUR_REG_ENABLE_MASK_PPM | - AR_PHY_SPUR_REG_MASK_RATE_SELECT | - AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | - SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); - REG_WRITE(ah, AR_PHY_SPUR_REG, new); - - spur_delta_phase = ((bb_spur * 524288) / 100) & - AR_PHY_TIMING11_SPUR_DELTA_PHASE; - - denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; - spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; - - new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | - SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | - SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); - REG_WRITE(ah, AR_PHY_TIMING11, new); - - cur_bin = -6000; - upper = bin + 100; - lower = bin - 100; - - for (i = 0; i < 4; i++) { - int pilot_mask = 0; - int chan_mask = 0; - int bp = 0; - for (bp = 0; bp < 30; bp++) { - if ((cur_bin > lower) && (cur_bin < upper)) { - pilot_mask = pilot_mask | 0x1 << bp; - chan_mask = chan_mask | 0x1 << bp; - } - cur_bin += 100; - } - cur_bin += inc[i]; - REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); - REG_WRITE(ah, chan_mask_reg[i], chan_mask); - } - - cur_vit_mask = 6100; - upper = bin + 120; - lower = bin - 120; - - for (i = 0; i < 123; i++) { - if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { - - /* workaround for gcc bug #37014 */ - volatile int tmp_v = abs(cur_vit_mask - bin); - - if (tmp_v < 75) - mask_amt = 1; - else - mask_amt = 0; - if (cur_vit_mask < 0) - mask_m[abs(cur_vit_mask / 100)] = mask_amt; - else - mask_p[cur_vit_mask / 100] = mask_amt; - } - cur_vit_mask -= 100; - } - - tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) - | (mask_m[48] << 26) | (mask_m[49] << 24) - | (mask_m[50] << 22) | (mask_m[51] << 20) - | (mask_m[52] << 18) | (mask_m[53] << 16) - | (mask_m[54] << 14) | (mask_m[55] << 12) - | (mask_m[56] << 10) | (mask_m[57] << 8) - | (mask_m[58] << 6) | (mask_m[59] << 4) - | (mask_m[60] << 2) | (mask_m[61] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); - REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); - - tmp_mask = (mask_m[31] << 28) - | (mask_m[32] << 26) | (mask_m[33] << 24) - | (mask_m[34] << 22) | (mask_m[35] << 20) - | (mask_m[36] << 18) | (mask_m[37] << 16) - | (mask_m[48] << 14) | (mask_m[39] << 12) - | (mask_m[40] << 10) | (mask_m[41] << 8) - | (mask_m[42] << 6) | (mask_m[43] << 4) - | (mask_m[44] << 2) | (mask_m[45] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); - - tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) - | (mask_m[18] << 26) | (mask_m[18] << 24) - | (mask_m[20] << 22) | (mask_m[20] << 20) - | (mask_m[22] << 18) | (mask_m[22] << 16) - | (mask_m[24] << 14) | (mask_m[24] << 12) - | (mask_m[25] << 10) | (mask_m[26] << 8) - | (mask_m[27] << 6) | (mask_m[28] << 4) - | (mask_m[29] << 2) | (mask_m[30] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); - - tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) - | (mask_m[2] << 26) | (mask_m[3] << 24) - | (mask_m[4] << 22) | (mask_m[5] << 20) - | (mask_m[6] << 18) | (mask_m[7] << 16) - | (mask_m[8] << 14) | (mask_m[9] << 12) - | (mask_m[10] << 10) | (mask_m[11] << 8) - | (mask_m[12] << 6) | (mask_m[13] << 4) - | (mask_m[14] << 2) | (mask_m[15] << 0); - REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); - - tmp_mask = (mask_p[15] << 28) - | (mask_p[14] << 26) | (mask_p[13] << 24) - | (mask_p[12] << 22) | (mask_p[11] << 20) - | (mask_p[10] << 18) | (mask_p[9] << 16) - | (mask_p[8] << 14) | (mask_p[7] << 12) - | (mask_p[6] << 10) | (mask_p[5] << 8) - | (mask_p[4] << 6) | (mask_p[3] << 4) - | (mask_p[2] << 2) | (mask_p[1] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); - - tmp_mask = (mask_p[30] << 28) - | (mask_p[29] << 26) | (mask_p[28] << 24) - | (mask_p[27] << 22) | (mask_p[26] << 20) - | (mask_p[25] << 18) | (mask_p[24] << 16) - | (mask_p[23] << 14) | (mask_p[22] << 12) - | (mask_p[21] << 10) | (mask_p[20] << 8) - | (mask_p[19] << 6) | (mask_p[18] << 4) - | (mask_p[17] << 2) | (mask_p[16] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); - - tmp_mask = (mask_p[45] << 28) - | (mask_p[44] << 26) | (mask_p[43] << 24) - | (mask_p[42] << 22) | (mask_p[41] << 20) - | (mask_p[40] << 18) | (mask_p[39] << 16) - | (mask_p[38] << 14) | (mask_p[37] << 12) - | (mask_p[36] << 10) | (mask_p[35] << 8) - | (mask_p[34] << 6) | (mask_p[33] << 4) - | (mask_p[32] << 2) | (mask_p[31] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); - - tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) - | (mask_p[59] << 26) | (mask_p[58] << 24) - | (mask_p[57] << 22) | (mask_p[56] << 20) - | (mask_p[55] << 18) | (mask_p[54] << 16) - | (mask_p[53] << 14) | (mask_p[52] << 12) - | (mask_p[51] << 10) | (mask_p[50] << 8) - | (mask_p[49] << 6) | (mask_p[48] << 4) - | (mask_p[47] << 2) | (mask_p[46] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); -} - -/** - * ath9k_hw_rf_alloc_ext_banks - allocates banks for external radio programming - * @ah: atheros hardware structure - * - * Only required for older devices with external AR2133/AR5133 radios. - */ -int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah) -{ -#define ATH_ALLOC_BANK(bank, size) do { \ - bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \ - if (!bank) { \ - ath_print(common, ATH_DBG_FATAL, \ - "Cannot allocate RF banks\n"); \ - return -ENOMEM; \ - } \ - } while (0); - - struct ath_common *common = ath9k_hw_common(ah); - - BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); - - ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows); - ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows); - ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows); - ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows); - ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows); - ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows); - ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows); - ATH_ALLOC_BANK(ah->addac5416_21, - ah->iniAddac.ia_rows * ah->iniAddac.ia_columns); - ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows); - - return 0; -#undef ATH_ALLOC_BANK -} - - -/** - * ath9k_hw_rf_free_ext_banks - Free memory for analog bank scratch buffers - * @ah: atheros hardware struture - * For the external AR2133/AR5133 radios banks. - */ -void -ath9k_hw_rf_free_ext_banks(struct ath_hw *ah) -{ -#define ATH_FREE_BANK(bank) do { \ - kfree(bank); \ - bank = NULL; \ - } while (0); - - BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); - - ATH_FREE_BANK(ah->analogBank0Data); - ATH_FREE_BANK(ah->analogBank1Data); - ATH_FREE_BANK(ah->analogBank2Data); - ATH_FREE_BANK(ah->analogBank3Data); - ATH_FREE_BANK(ah->analogBank6Data); - ATH_FREE_BANK(ah->analogBank6TPCData); - ATH_FREE_BANK(ah->analogBank7Data); - ATH_FREE_BANK(ah->addac5416_21); - ATH_FREE_BANK(ah->bank6Temp); - -#undef ATH_FREE_BANK -} - -/* * - * ath9k_hw_set_rf_regs - programs rf registers based on EEPROM - * @ah: atheros hardware structure - * @chan: - * @modesIndex: - * - * Used for the external AR2133/AR5133 radios. - * - * Reads the EEPROM header info from the device structure and programs - * all rf registers. This routine requires access to the analog - * rf device. This is not required for single-chip devices. - */ -bool ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, - u16 modesIndex) -{ - u32 eepMinorRev; - u32 ob5GHz = 0, db5GHz = 0; - u32 ob2GHz = 0, db2GHz = 0; - int regWrites = 0; - - /* - * Software does not need to program bank data - * for single chip devices, that is AR9280 or anything - * after that. - */ - if (AR_SREV_9280_10_OR_LATER(ah)) - return true; - - /* Setup rf parameters */ - eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); - - /* Setup Bank 0 Write */ - RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); - - /* Setup Bank 1 Write */ - RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); - - /* Setup Bank 2 Write */ - RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); - - /* Setup Bank 6 Write */ - RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, - modesIndex); - { - int i; - for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) { - ah->analogBank6Data[i] = - INI_RA(&ah->iniBank6TPC, i, modesIndex); - } - } - - /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ - if (eepMinorRev >= 2) { - if (IS_CHAN_2GHZ(chan)) { - ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2); - db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2); - ath9k_phy_modify_rx_buffer(ah->analogBank6Data, - ob2GHz, 3, 197, 0); - ath9k_phy_modify_rx_buffer(ah->analogBank6Data, - db2GHz, 3, 194, 0); - } else { - ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5); - db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5); - ath9k_phy_modify_rx_buffer(ah->analogBank6Data, - ob5GHz, 3, 203, 0); - ath9k_phy_modify_rx_buffer(ah->analogBank6Data, - db5GHz, 3, 200, 0); - } - } - - /* Setup Bank 7 Setup */ - RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); - - /* Write Analog registers */ - REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data, - regWrites); - - return true; -} diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 4b6e494bd984..b90815205a14 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -17,501 +17,11 @@ #ifndef PHY_H #define PHY_H -/* Single chip radio settings */ -int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan); -void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); - -/* Routines below are for non single-chip solutions */ -int ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan); -void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); - -int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah); -void ath9k_hw_rf_free_ext_banks(struct ath_hw *ah); - -bool ath9k_hw_set_rf_regs(struct ath_hw *ah, - struct ath9k_channel *chan, - u16 modesIndex); - #define AR_PHY_BASE 0x9800 #define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) -#define AR_PHY_TEST 0x9800 -#define PHY_AGC_CLR 0x10000000 -#define RFSILENT_BB 0x00002000 - -#define AR_PHY_TURBO 0x9804 -#define AR_PHY_FC_TURBO_MODE 0x00000001 -#define AR_PHY_FC_TURBO_SHORT 0x00000002 -#define AR_PHY_FC_DYN2040_EN 0x00000004 -#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008 -#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010 -/* For 25 MHz channel spacing -- not used but supported by hw */ -#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020 -#define AR_PHY_FC_HT_EN 0x00000040 -#define AR_PHY_FC_SHORT_GI_40 0x00000080 -#define AR_PHY_FC_WALSH 0x00000100 -#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200 -#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800 - -#define AR_PHY_TEST2 0x9808 - -#define AR_PHY_TIMING2 0x9810 -#define AR_PHY_TIMING3 0x9814 -#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 -#define AR_PHY_TIMING3_DSC_MAN_S 17 -#define AR_PHY_TIMING3_DSC_EXP 0x0001E000 -#define AR_PHY_TIMING3_DSC_EXP_S 13 - -#define AR_PHY_CHIP_ID 0x9818 -#define AR_PHY_CHIP_ID_REV_0 0x80 -#define AR_PHY_CHIP_ID_REV_1 0x81 -#define AR_PHY_CHIP_ID_9160_REV_0 0xb0 - -#define AR_PHY_ACTIVE 0x981C -#define AR_PHY_ACTIVE_EN 0x00000001 -#define AR_PHY_ACTIVE_DIS 0x00000000 - -#define AR_PHY_RF_CTL2 0x9824 -#define AR_PHY_TX_END_DATA_START 0x000000FF -#define AR_PHY_TX_END_DATA_START_S 0 -#define AR_PHY_TX_END_PA_ON 0x0000FF00 -#define AR_PHY_TX_END_PA_ON_S 8 - -#define AR_PHY_RF_CTL3 0x9828 -#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000 -#define AR_PHY_TX_END_TO_A2_RX_ON_S 16 - -#define AR_PHY_ADC_CTL 0x982C -#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003 -#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0 -#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000 -#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000 -#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000 -#define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000 -#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16 - -#define AR_PHY_ADC_SERIAL_CTL 0x9830 -#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000 -#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001 - -#define AR_PHY_RF_CTL4 0x9834 -#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000 -#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24 -#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000 -#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16 -#define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00 -#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8 -#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF -#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0 - -#define AR_PHY_TSTDAC_CONST 0x983c - -#define AR_PHY_SETTLING 0x9844 -#define AR_PHY_SETTLING_SWITCH 0x00003F80 -#define AR_PHY_SETTLING_SWITCH_S 7 - -#define AR_PHY_RXGAIN 0x9848 -#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000 -#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12 -#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000 -#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18 -#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80 -#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7 -#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000 -#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14 - -#define AR_PHY_DESIRED_SZ 0x9850 -#define AR_PHY_DESIRED_SZ_ADC 0x000000FF -#define AR_PHY_DESIRED_SZ_ADC_S 0 -#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00 -#define AR_PHY_DESIRED_SZ_PGA_S 8 -#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000 -#define AR_PHY_DESIRED_SZ_TOT_DES_S 20 - -#define AR_PHY_FIND_SIG 0x9858 -#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000 -#define AR_PHY_FIND_SIG_FIRSTEP_S 12 -#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000 -#define AR_PHY_FIND_SIG_FIRPWR_S 18 - -#define AR_PHY_AGC_CTL1 0x985C -#define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80 -#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7 -#define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000 -#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15 - -#define AR_PHY_AGC_CONTROL 0x9860 -#define AR_PHY_AGC_CONTROL_CAL 0x00000001 -#define AR_PHY_AGC_CONTROL_NF 0x00000002 -#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 -#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 -#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 - -#define AR_PHY_CCA 0x9864 -#define AR_PHY_MINCCA_PWR 0x0FF80000 -#define AR_PHY_MINCCA_PWR_S 19 -#define AR_PHY_CCA_THRESH62 0x0007F000 -#define AR_PHY_CCA_THRESH62_S 12 -#define AR9280_PHY_MINCCA_PWR 0x1FF00000 -#define AR9280_PHY_MINCCA_PWR_S 20 -#define AR9280_PHY_CCA_THRESH62 0x000FF000 -#define AR9280_PHY_CCA_THRESH62_S 12 - -#define AR_PHY_SFCORR_LOW 0x986C -#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001 -#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00 -#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8 -#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000 -#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14 -#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000 -#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21 - -#define AR_PHY_SFCORR 0x9868 -#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F -#define AR_PHY_SFCORR_M2COUNT_THR_S 0 -#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000 -#define AR_PHY_SFCORR_M1_THRESH_S 17 -#define AR_PHY_SFCORR_M2_THRESH 0x7F000000 -#define AR_PHY_SFCORR_M2_THRESH_S 24 - -#define AR_PHY_SLEEP_CTR_CONTROL 0x9870 -#define AR_PHY_SLEEP_CTR_LIMIT 0x9874 -#define AR_PHY_SYNTH_CONTROL 0x9874 -#define AR_PHY_SLEEP_SCAL 0x9878 - -#define AR_PHY_PLL_CTL 0x987c -#define AR_PHY_PLL_CTL_40 0xaa -#define AR_PHY_PLL_CTL_40_5413 0x04 -#define AR_PHY_PLL_CTL_44 0xab -#define AR_PHY_PLL_CTL_44_2133 0xeb -#define AR_PHY_PLL_CTL_40_2133 0xea - -#define AR_PHY_SPECTRAL_SCAN 0x9910 /* AR9280 spectral scan configuration register */ -#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1 -#define AR_PHY_SPECTRAL_SCAN_ENA 0x00000001 /* Enable spectral scan, reg 68, bit 0 */ -#define AR_PHY_SPECTRAL_SCAN_ENA_S 0 /* Enable spectral scan, reg 68, bit 0 */ -#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 /* Activate spectral scan reg 68, bit 1*/ -#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 /* Activate spectral scan reg 68, bit 1*/ -#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 /* Interval for FFT reports, reg 68, bits 4-7*/ -#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4 -#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 /* Interval for FFT reports, reg 68, bits 8-15*/ -#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8 -#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 /* Number of reports, reg 68, bits 16-23*/ -#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16 -#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 /* Short repeat, reg 68, bit 24*/ -#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 /* Short repeat, reg 68, bit 24*/ - -#define AR_PHY_RX_DELAY 0x9914 -#define AR_PHY_SEARCH_START_DELAY 0x9918 -#define AR_PHY_RX_DELAY_DELAY 0x00003FFF - -#define AR_PHY_TIMING_CTRL4(_i) (0x9920 + ((_i) << 12)) -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0 -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0 -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 -#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800 -#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000 -#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 -#define AR_PHY_TIMING_CTRL4_DO_CAL 0x10000 - -#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000 -#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000 -#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000 -#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000 - -#define AR_PHY_TIMING5 0x9924 -#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE -#define AR_PHY_TIMING5_CYCPWR_THR1_S 1 - -#define AR_PHY_POWER_TX_RATE1 0x9934 -#define AR_PHY_POWER_TX_RATE2 0x9938 -#define AR_PHY_POWER_TX_RATE_MAX 0x993c -#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040 - -#define AR_PHY_FRAME_CTL 0x9944 -#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038 -#define AR_PHY_FRAME_CTL_TX_CLIP_S 3 - -#define AR_PHY_TXPWRADJ 0x994C -#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0 -#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6 -#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000 -#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18 - -#define AR_PHY_RADAR_EXT 0x9940 -#define AR_PHY_RADAR_EXT_ENA 0x00004000 - -#define AR_PHY_RADAR_0 0x9954 -#define AR_PHY_RADAR_0_ENA 0x00000001 -#define AR_PHY_RADAR_0_FFT_ENA 0x80000000 -#define AR_PHY_RADAR_0_INBAND 0x0000003e -#define AR_PHY_RADAR_0_INBAND_S 1 -#define AR_PHY_RADAR_0_PRSSI 0x00000FC0 -#define AR_PHY_RADAR_0_PRSSI_S 6 -#define AR_PHY_RADAR_0_HEIGHT 0x0003F000 -#define AR_PHY_RADAR_0_HEIGHT_S 12 -#define AR_PHY_RADAR_0_RRSSI 0x00FC0000 -#define AR_PHY_RADAR_0_RRSSI_S 18 -#define AR_PHY_RADAR_0_FIRPWR 0x7F000000 -#define AR_PHY_RADAR_0_FIRPWR_S 24 - -#define AR_PHY_RADAR_1 0x9958 -#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000 -#define AR_PHY_RADAR_1_USE_FIR128 0x00400000 -#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000 -#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16 -#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000 -#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000 -#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000 -#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00 -#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8 -#define AR_PHY_RADAR_1_MAXLEN 0x000000FF -#define AR_PHY_RADAR_1_MAXLEN_S 0 - -#define AR_PHY_SWITCH_CHAIN_0 0x9960 -#define AR_PHY_SWITCH_COM 0x9964 - -#define AR_PHY_SIGMA_DELTA 0x996C -#define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003 -#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0 -#define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8 -#define AR_PHY_SIGMA_DELTA_FILT2_S 3 -#define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00 -#define AR_PHY_SIGMA_DELTA_FILT1_S 8 -#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000 -#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13 - -#define AR_PHY_RESTART 0x9970 -#define AR_PHY_RESTART_DIV_GC 0x001C0000 -#define AR_PHY_RESTART_DIV_GC_S 18 - -#define AR_PHY_RFBUS_REQ 0x997C -#define AR_PHY_RFBUS_REQ_EN 0x00000001 - -#define AR_PHY_TIMING7 0x9980 -#define AR_PHY_TIMING8 0x9984 -#define AR_PHY_TIMING8_PILOT_MASK_2 0x000FFFFF -#define AR_PHY_TIMING8_PILOT_MASK_2_S 0 - -#define AR_PHY_BIN_MASK2_1 0x9988 -#define AR_PHY_BIN_MASK2_2 0x998c -#define AR_PHY_BIN_MASK2_3 0x9990 -#define AR_PHY_BIN_MASK2_4 0x9994 - -#define AR_PHY_BIN_MASK_1 0x9900 -#define AR_PHY_BIN_MASK_2 0x9904 -#define AR_PHY_BIN_MASK_3 0x9908 - -#define AR_PHY_MASK_CTL 0x990c - -#define AR_PHY_BIN_MASK2_4_MASK_4 0x00003FFF -#define AR_PHY_BIN_MASK2_4_MASK_4_S 0 - -#define AR_PHY_TIMING9 0x9998 -#define AR_PHY_TIMING10 0x999c -#define AR_PHY_TIMING10_PILOT_MASK_2 0x000FFFFF -#define AR_PHY_TIMING10_PILOT_MASK_2_S 0 - -#define AR_PHY_TIMING11 0x99a0 -#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF -#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0 -#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 -#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 -#define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000 -#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000 - -#define AR_PHY_RX_CHAINMASK 0x99a4 -#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12)) -#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 -#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 - -#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac -#define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000 -#define AR_PHY_9285_ANT_DIV_CTL 0x01000000 -#define AR_PHY_9285_ANT_DIV_CTL_S 24 -#define AR_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000 -#define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S 25 -#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000 -#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27 -#define AR_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000 -#define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S 29 -#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000 -#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30 -#define AR_PHY_9285_ANT_DIV_LNA1 2 -#define AR_PHY_9285_ANT_DIV_LNA2 1 -#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3 -#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0 -#define AR_PHY_9285_ANT_DIV_GAINTB_0 0 -#define AR_PHY_9285_ANT_DIV_GAINTB_1 1 - -#define AR_PHY_EXT_CCA0 0x99b8 -#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF -#define AR_PHY_EXT_CCA0_THRESH62_S 0 - -#define AR_PHY_EXT_CCA 0x99bc -#define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00 -#define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9 -#define AR_PHY_EXT_CCA_THRESH62 0x007F0000 -#define AR_PHY_EXT_CCA_THRESH62_S 16 -#define AR_PHY_EXT_MINCCA_PWR 0xFF800000 -#define AR_PHY_EXT_MINCCA_PWR_S 23 -#define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000 -#define AR9280_PHY_EXT_MINCCA_PWR_S 16 - -#define AR_PHY_SFCORR_EXT 0x99c0 -#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F -#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0 -#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80 -#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7 -#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000 -#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 -#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000 -#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 -#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 - -#define AR_PHY_HALFGI 0x99D0 -#define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0 -#define AR_PHY_HALFGI_DSC_MAN_S 4 -#define AR_PHY_HALFGI_DSC_EXP 0x0000000F -#define AR_PHY_HALFGI_DSC_EXP_S 0 - -#define AR_PHY_CHAN_INFO_MEMORY 0x99DC -#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001 - -#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0 - -#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS 0x99EC -#define AR_PHY_RIFS_INIT_DELAY 0x03ff0000 - -#define AR_PHY_M_SLEEP 0x99f0 -#define AR_PHY_REFCLKDLY 0x99f4 -#define AR_PHY_REFCLKPD 0x99f8 - -#define AR_PHY_CALMODE 0x99f0 - -#define AR_PHY_CALMODE_IQ 0x00000000 -#define AR_PHY_CALMODE_ADC_GAIN 0x00000001 -#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002 -#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003 - -#define AR_PHY_CAL_MEAS_0(_i) (0x9c10 + ((_i) << 12)) -#define AR_PHY_CAL_MEAS_1(_i) (0x9c14 + ((_i) << 12)) -#define AR_PHY_CAL_MEAS_2(_i) (0x9c18 + ((_i) << 12)) -#define AR_PHY_CAL_MEAS_3(_i) (0x9c1c + ((_i) << 12)) - -#define AR_PHY_CURRENT_RSSI 0x9c1c -#define AR9280_PHY_CURRENT_RSSI 0x9c3c - -#define AR_PHY_RFBUS_GRANT 0x9C20 -#define AR_PHY_RFBUS_GRANT_EN 0x00000001 - -#define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4 -#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 - -#define AR_PHY_CHAN_INFO_GAIN 0x9CFC - -#define AR_PHY_MODE 0xA200 -#define AR_PHY_MODE_ASYNCFIFO 0x80 -#define AR_PHY_MODE_AR2133 0x08 -#define AR_PHY_MODE_AR5111 0x00 -#define AR_PHY_MODE_AR5112 0x08 -#define AR_PHY_MODE_DYNAMIC 0x04 -#define AR_PHY_MODE_RF2GHZ 0x02 -#define AR_PHY_MODE_RF5GHZ 0x00 -#define AR_PHY_MODE_CCK 0x01 -#define AR_PHY_MODE_OFDM 0x00 -#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100 - -#define AR_PHY_CCK_TX_CTRL 0xA204 -#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 -#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C -#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2 - -#define AR_PHY_CCK_DETECT 0xA208 -#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F -#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0 -/* [12:6] settling time for antenna switch */ -#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 -#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6 -#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 -#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13 - -#define AR_PHY_GAIN_2GHZ 0xA20C -#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000 -#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18 -#define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00 -#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10 -#define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F -#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0 - -#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003E0000 -#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17 -#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001F000 -#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12 -#define AR_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000FC0 -#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S 6 -#define AR_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003F -#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S 0 - -#define AR_PHY_CCK_RXCTRL4 0xA21C -#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000 -#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19 - -#define AR_PHY_DAG_CTRLCCK 0xA228 -#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200 -#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00 -#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10 - -#define AR_PHY_FORCE_CLKEN_CCK 0xA22C -#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040 - -#define AR_PHY_POWER_TX_RATE3 0xA234 -#define AR_PHY_POWER_TX_RATE4 0xA238 - -#define AR_PHY_SCRM_SEQ_XR 0xA23C -#define AR_PHY_HEADER_DETECT_XR 0xA240 -#define AR_PHY_CHIRP_DETECTED_XR 0xA244 -#define AR_PHY_BLUETOOTH 0xA254 - -#define AR_PHY_TPCRG1 0xA258 -#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000 -#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14 - -#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000 -#define AR_PHY_TPCRG1_PD_GAIN_1_S 16 -#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000 -#define AR_PHY_TPCRG1_PD_GAIN_2_S 18 -#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 -#define AR_PHY_TPCRG1_PD_GAIN_3_S 20 - -#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000 -#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22 - -#define AR_PHY_TX_PWRCTRL4 0xa264 -#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001 -#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0 -#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE -#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1 - -#define AR_PHY_TX_PWRCTRL6_0 0xa270 -#define AR_PHY_TX_PWRCTRL6_1 0xb270 -#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000 -#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 - -#define AR_PHY_TX_PWRCTRL7 0xa274 #define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX 0x0007E000 #define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX_S 13 -#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 -#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 - -#define AR_PHY_TX_PWRCTRL9 0xa27C -#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 -#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 -#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 -#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 - -#define AR_PHY_TX_GAIN_TBL1 0xa300 #define AR_PHY_TX_GAIN_CLC 0x0000001E #define AR_PHY_TX_GAIN_CLC_S 1 #define AR_PHY_TX_GAIN 0x0007F000 @@ -523,91 +33,6 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, #define AR_PHY_CLC_Q0 0x0000ffd0 #define AR_PHY_CLC_Q0_S 5 -#define AR_PHY_CH0_TX_PWRCTRL11 0xa398 -#define AR_PHY_CH1_TX_PWRCTRL11 0xb398 -#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00 -#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 - -#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 -#define AR_PHY_MASK2_M_31_45 0xa3a4 -#define AR_PHY_MASK2_M_16_30 0xa3a8 -#define AR_PHY_MASK2_M_00_15 0xa3ac -#define AR_PHY_MASK2_P_15_01 0xa3b8 -#define AR_PHY_MASK2_P_30_16 0xa3bc -#define AR_PHY_MASK2_P_45_31 0xa3c0 -#define AR_PHY_MASK2_P_61_45 0xa3c4 -#define AR_PHY_SPUR_REG 0x994c - -#define AR_PHY_SPUR_REG_MASK_RATE_CNTL (0xFF << 18) -#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18 - -#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000 -#define AR_PHY_SPUR_REG_MASK_RATE_SELECT (0xFF << 9) -#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S 9 -#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100 -#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7F -#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0 - -#define AR_PHY_PILOT_MASK_01_30 0xa3b0 -#define AR_PHY_PILOT_MASK_31_60 0xa3b4 - -#define AR_PHY_CHANNEL_MASK_01_30 0x99d4 -#define AR_PHY_CHANNEL_MASK_31_60 0x99d8 - -#define AR_PHY_ANALOG_SWAP 0xa268 -#define AR_PHY_SWAP_ALT_CHAIN 0x00000040 - -#define AR_PHY_TPCRG5 0xA26C -#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F -#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22 - -/* Carrier leak calibration control, do it after AGC calibration */ -#define AR_PHY_CL_CAL_CTL 0xA358 -#define AR_PHY_CL_CAL_ENABLE 0x00000002 -#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001 - -#define AR_PHY_POWER_TX_RATE5 0xA38C -#define AR_PHY_POWER_TX_RATE6 0xA390 - -#define AR_PHY_CAL_CHAINMASK 0xA39C - -#define AR_PHY_POWER_TX_SUB 0xA3C8 -#define AR_PHY_POWER_TX_RATE7 0xA3CC -#define AR_PHY_POWER_TX_RATE8 0xA3D0 -#define AR_PHY_POWER_TX_RATE9 0xA3D4 - -#define AR_PHY_XPA_CFG 0xA3D8 -#define AR_PHY_FORCE_XPA_CFG 0x000000001 -#define AR_PHY_FORCE_XPA_CFG_S 0 - -#define AR_PHY_CH1_CCA 0xa864 -#define AR_PHY_CH1_MINCCA_PWR 0x0FF80000 -#define AR_PHY_CH1_MINCCA_PWR_S 19 -#define AR9280_PHY_CH1_MINCCA_PWR 0x1FF00000 -#define AR9280_PHY_CH1_MINCCA_PWR_S 20 - -#define AR_PHY_CH2_CCA 0xb864 -#define AR_PHY_CH2_MINCCA_PWR 0x0FF80000 -#define AR_PHY_CH2_MINCCA_PWR_S 19 - -#define AR_PHY_CH1_EXT_CCA 0xa9bc -#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000 -#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23 -#define AR9280_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000 -#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16 - -#define AR_PHY_CH2_EXT_CCA 0xb9bc -#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000 -#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23 - #define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do { \ int r; \ for (r = 0; r < ((iniarray)->ia_rows); r++) { \ @@ -622,6 +47,7 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, #define ANTSWAP_AB 0x0001 #define REDUCE_CHAIN_0 0x00000050 #define REDUCE_CHAIN_1 0x00000051 +#define AR_PHY_CHIP_ID 0x9818 #define RF_BANK_SETUP(_bank, _iniarray, _col) do { \ int i; \ -- cgit v1.2.3 From e041228fed0c9fe8b5c3b8e0ca66b08178b26a87 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:15 -0400 Subject: ath9k_hw: skip PLL initialization on AR9003 on Power-On-Reset This is not required for the AR9003 family. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2ab061381fcf..f1405042a48d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2064,7 +2064,8 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) ATH9K_RESET_POWER_ON) != true) { return false; } - ath9k_hw_init_pll(ah, NULL); + if (!AR_SREV_9300_20_OR_LATER(ah)) + ath9k_hw_init_pll(ah, NULL); } if (AR_SREV_9100(ah)) REG_SET_BIT(ah, AR_RTC_RESET, -- cgit v1.2.3 From bbd79af5639bd51af1119e5df866568063a1b011 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:16 -0400 Subject: ath9k_hw: add some comments for ath9k_set_power_network_sleep() Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index f1405042a48d..ea831f575a9d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2036,6 +2036,11 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) } } +/* + * Notify Power Management is enabled in self-generating + * frames. If request, set power mode of chip to + * auto/normal. Duration in units of 128us (1/8 TU). + */ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip) { REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); @@ -2043,9 +2048,14 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip) struct ath9k_hw_capabilities *pCap = &ah->caps; if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { + /* Set WakeOnInterrupt bit; clear ForceWake bit */ REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); } else { + /* + * Clear the RTC force wake bit to allow the + * mac to go to sleep. + */ REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); } -- cgit v1.2.3 From 647739645bea4a5628f9e4eaf8022dcc5875c535 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:17 -0400 Subject: ath9k_hw: add a private callback for PLL control computation The PLL control computation used to program the AR_RTC_PLL_CONTROL register varies between our harware so just add a private callback for it. AR9003 will use its own callback. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar5008_phy.c | 55 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9002_phy.c | 31 ++++++++++++++ drivers/net/wireless/ath/ath9k/hw.c | 64 ++++------------------------- drivers/net/wireless/ath/ath9k/hw.h | 4 ++ 4 files changed, 97 insertions(+), 57 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 982b0d3877f8..9685f4c6fc99 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -967,6 +967,54 @@ static void ar5008_set_diversity(struct ath_hw *ah, bool value) REG_WRITE(ah, AR_PHY_CCK_DETECT, v); } +static u32 ar9100_hw_compute_pll_control(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + if (chan && IS_CHAN_5GHZ(chan)) + return 0x1450; + return 0x1458; +} + +static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + u32 pll; + + pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); + + if (chan && IS_CHAN_HALF_RATE(chan)) + pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); + else if (chan && IS_CHAN_QUARTER_RATE(chan)) + pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); + + if (chan && IS_CHAN_5GHZ(chan)) + pll |= SM(0x50, AR_RTC_9160_PLL_DIV); + else + pll |= SM(0x58, AR_RTC_9160_PLL_DIV); + + return pll; +} + +static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + u32 pll; + + pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2; + + if (chan && IS_CHAN_HALF_RATE(chan)) + pll |= SM(0x1, AR_RTC_PLL_CLKSEL); + else if (chan && IS_CHAN_QUARTER_RATE(chan)) + pll |= SM(0x2, AR_RTC_PLL_CLKSEL); + + if (chan && IS_CHAN_5GHZ(chan)) + pll |= SM(0xa, AR_RTC_PLL_DIV); + else + pll |= SM(0xb, AR_RTC_PLL_DIV); + + return pll; +} + void ar5008_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); @@ -988,4 +1036,11 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->enable_rfkill = ar5008_hw_enable_rfkill; priv_ops->restore_chainmask = ar5008_restore_chainmask; priv_ops->set_diversity = ar5008_set_diversity; + + if (AR_SREV_9100(ah)) + priv_ops->compute_pll_control = ar9100_hw_compute_pll_control; + else if (AR_SREV_9160_10_OR_LATER(ah)) + priv_ops->compute_pll_control = ar9160_hw_compute_pll_control; + else + priv_ops->compute_pll_control = ar5008_hw_compute_pll_control; } diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 29b50ca0a0cc..87541a8440c0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -437,6 +437,36 @@ static void ar9002_olc_init(struct ath_hw *ah) } } +static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + u32 pll; + + pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); + + if (chan && IS_CHAN_HALF_RATE(chan)) + pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); + else if (chan && IS_CHAN_QUARTER_RATE(chan)) + pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); + + if (chan && IS_CHAN_5GHZ(chan)) { + pll |= SM(0x28, AR_RTC_9160_PLL_DIV); + + + if (AR_SREV_9280_20(ah)) { + if (((chan->channel % 20) == 0) + || ((chan->channel % 10) == 0)) + pll = 0x2850; + else + pll = 0x142c; + } + } else { + pll |= SM(0x2c, AR_RTC_9160_PLL_DIV); + } + + return pll; +} + void ar9002_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); @@ -447,4 +477,5 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->rf_set_freq = ar9002_hw_set_channel; priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate; priv_ops->olc_init = ar9002_olc_init; + priv_ops->compute_pll_control = ar9002_hw_compute_pll_control; } diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ea831f575a9d..349cffdbdea6 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -66,6 +66,12 @@ static bool ath9k_hw_macversion_supported(struct ath_hw *ah) return priv_ops->macversion_supported(ah->hw_version.macVersion); } +static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + return ath9k_hw_private_ops(ah)->compute_pll_control(ah, chan); +} + /********************/ /* Helper Functions */ /********************/ @@ -1023,64 +1029,8 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) static void ath9k_hw_init_pll(struct ath_hw *ah, struct ath9k_channel *chan) { - u32 pll; - - if (AR_SREV_9100(ah)) { - if (chan && IS_CHAN_5GHZ(chan)) - pll = 0x1450; - else - pll = 0x1458; - } else { - if (AR_SREV_9280_10_OR_LATER(ah)) { - pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); - - if (chan && IS_CHAN_HALF_RATE(chan)) - pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); - else if (chan && IS_CHAN_QUARTER_RATE(chan)) - pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); - - if (chan && IS_CHAN_5GHZ(chan)) { - pll |= SM(0x28, AR_RTC_9160_PLL_DIV); - - - if (AR_SREV_9280_20(ah)) { - if (((chan->channel % 20) == 0) - || ((chan->channel % 10) == 0)) - pll = 0x2850; - else - pll = 0x142c; - } - } else { - pll |= SM(0x2c, AR_RTC_9160_PLL_DIV); - } - - } else if (AR_SREV_9160_10_OR_LATER(ah)) { - - pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); - - if (chan && IS_CHAN_HALF_RATE(chan)) - pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); - else if (chan && IS_CHAN_QUARTER_RATE(chan)) - pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); - - if (chan && IS_CHAN_5GHZ(chan)) - pll |= SM(0x50, AR_RTC_9160_PLL_DIV); - else - pll |= SM(0x58, AR_RTC_9160_PLL_DIV); - } else { - pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2; - - if (chan && IS_CHAN_HALF_RATE(chan)) - pll |= SM(0x1, AR_RTC_PLL_CLKSEL); - else if (chan && IS_CHAN_QUARTER_RATE(chan)) - pll |= SM(0x2, AR_RTC_PLL_CLKSEL); + u32 pll = ath9k_hw_compute_pll_control(ah, chan); - if (chan && IS_CHAN_5GHZ(chan)) - pll |= SM(0xa, AR_RTC_PLL_DIV); - else - pll |= SM(0xb, AR_RTC_PLL_DIV); - } - } REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); /* Switch the core clock for ar9271 to 117Mhz */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index d740e9cc721c..79b938b93055 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -454,6 +454,8 @@ struct ath_gen_timer_table { * @rf_alloc_ext_banks: * @rf_free_ext_banks: * @set_rf_regs: + * @compute_pll_control: compute the PLL control value to use for + * AR_RTC_PLL_CONTROL for a given channel */ struct ath_hw_private_ops { void (*init_cal_settings)(struct ath_hw *ah); @@ -483,6 +485,8 @@ struct ath_hw_private_ops { void (*enable_rfkill)(struct ath_hw *ah); void (*restore_chainmask)(struct ath_hw *ah); void (*set_diversity)(struct ath_hw *ah, bool value); + u32 (*compute_pll_control)(struct ath_hw *ah, + struct ath9k_channel *chan); }; /** -- cgit v1.2.3 From db3cc53a2faea2da5730304af06a77d343f314a5 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Thu, 15 Apr 2010 17:38:18 -0400 Subject: ath9k_hw: Add the PCI IDs for AR9300 and fill up the pci_id_tables Also, clean up and reorganize the AR9287 macro to have better ordering. We won't add the PCI ID to the supported device list until we have some functional code for it. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 5 +++-- drivers/net/wireless/ath/ath9k/hw.h | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 349cffdbdea6..7952818e6307 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -984,9 +984,10 @@ int ath9k_hw_init(struct ath_hw *ah) case AR9280_DEVID_PCI: case AR9280_DEVID_PCIE: case AR9285_DEVID_PCIE: - case AR5416_DEVID_AR9287_PCI: - case AR5416_DEVID_AR9287_PCIE: + case AR9287_DEVID_PCI: + case AR9287_DEVID_PCIE: case AR2427_DEVID_PCIE: + case AR9300_DEVID_PCIE: break; default: if (common->bus_ops->ath_bus_type == ATH_USB) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 79b938b93055..a1ce79d1795d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -41,6 +41,9 @@ #define AR9280_DEVID_PCIE 0x002a #define AR9285_DEVID_PCIE 0x002b #define AR2427_DEVID_PCIE 0x002c +#define AR9287_DEVID_PCI 0x002d +#define AR9287_DEVID_PCIE 0x002e +#define AR9300_DEVID_PCIE 0x0030 #define AR5416_AR9100_DEVID 0x000b @@ -48,9 +51,6 @@ #define AR_SUBVENDOR_ID_NEW_A 0x7065 #define AR5416_MAGIC 0x19641014 -#define AR5416_DEVID_AR9287_PCI 0x002D -#define AR5416_DEVID_AR9287_PCIE 0x002E - #define AR9280_COEX2WIRE_SUBSYSID 0x309b #define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa #define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab -- cgit v1.2.3 From 8525f2801df14b6c4ae6a96127e47d646be5304c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:19 -0400 Subject: ath9k_hw: Add AR9003 PHY support This add stubs for PHY support for the AR9003 hardware family. Signed-off-by: Felix Fietkau Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Makefile | 1 + drivers/net/wireless/ath/ath9k/ar9003_phy.c | 147 ++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/hw.c | 20 +++- drivers/net/wireless/ath/ath9k/hw.h | 3 +- 4 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/ar9003_phy.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index db63ba298049..ecf3f8c71d6f 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -14,6 +14,7 @@ ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o obj-$(CONFIG_ATH9K) += ath9k.o ath9k_hw-y:= hw.o \ + ar9003_phy.o \ ar9002_phy.o \ ar5008_phy.o \ eeprom.o \ diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c new file mode 100644 index 000000000000..c4511b8ff75a --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" + +/** + * ar9003_hw_set_channel - set channel on single-chip device + * @ah: atheros hardware structure + * @chan: + * + * This is the function to change channel on single-chip devices, that is + * all devices after ar9280. + * + * This function takes the channel value in MHz and sets + * hardware channel value. Assumes writes have been enabled to analog bus. + * + * Actual Expression, + * + * For 2GHz channel, + * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) + * (freq_ref = 40MHz) + * + * For 5GHz channel, + * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) + * (freq_ref = 40MHz/(24>>amodeRefSel)) + * + * For 5GHz channels which are 5MHz spaced, + * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) + * (freq_ref = 40MHz) + */ +static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) +{ + /* TODO */ + return 0; +} + +/** + * ar9003_hw_spur_mitigate - convert baseband spur frequency + * @ah: atheros hardware structure + * @chan: + * + * For single-chip solutions. Converts to baseband spur frequency given the + * input channel frequency and compute register settings below. + * + * Spur mitigation for MRC CCK + */ +static void ar9003_hw_spur_mitigate(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + /* TODO */ +} + +static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + /* TODO */ + return 0; +} + +static void ar9003_hw_set_channel_regs(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + /* TODO */ +} + +static void ar9003_hw_init_bb(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + /* TODO */ +} + +static int ar9003_hw_process_ini(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + /* TODO */ + return -1; +} + +static void ar9003_hw_set_rfmode(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + /* TODO */ +} + +static void ar9003_hw_mark_phy_inactive(struct ath_hw *ah) +{ + /* TODO */ +} + +static void ar9003_hw_set_delta_slope(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + /* TODO */ +} + +static bool ar9003_hw_rfbus_req(struct ath_hw *ah) +{ + /* TODO */ + return false; +} + +static void ar9003_hw_rfbus_done(struct ath_hw *ah) +{ + /* TODO */ +} + +static void ar9003_hw_enable_rfkill(struct ath_hw *ah) +{ + /* TODO */ +} + +static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value) +{ + /* TODO */ +} + +void ar9003_hw_attach_phy_ops(struct ath_hw *ah) +{ + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + + priv_ops->rf_set_freq = ar9003_hw_set_channel; + priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate; + priv_ops->compute_pll_control = ar9003_hw_compute_pll_control; + priv_ops->set_channel_regs = ar9003_hw_set_channel_regs; + priv_ops->init_bb = ar9003_hw_init_bb; + priv_ops->process_ini = ar9003_hw_process_ini; + priv_ops->set_rfmode = ar9003_hw_set_rfmode; + priv_ops->mark_phy_inactive = ar9003_hw_mark_phy_inactive; + priv_ops->set_delta_slope = ar9003_hw_set_delta_slope; + priv_ops->rfbus_req = ar9003_hw_rfbus_req; + priv_ops->rfbus_done = ar9003_hw_rfbus_done; + priv_ops->enable_rfkill = ar9003_hw_enable_rfkill; + priv_ops->set_diversity = ar9003_hw_set_diversity; +} diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 7952818e6307..f057d1ad9290 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -27,6 +27,7 @@ #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 static void ar9002_hw_attach_ops(struct ath_hw *ah); +static void ar9003_hw_attach_ops(struct ath_hw *ah); static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); @@ -858,6 +859,14 @@ static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah) "needs fixup for AR_AN_TOP2 register\n"); } +static void ath9k_hw_attach_ops(struct ath_hw *ah) +{ + if (AR_SREV_9300_20_OR_LATER(ah)) + ar9003_hw_attach_ops(ah); + else + ar9002_hw_attach_ops(ah); +} + /* Called for all hardware families */ static int __ath9k_hw_init(struct ath_hw *ah) { @@ -873,7 +882,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) return -EIO; } - ar9002_hw_attach_ops(ah); + ath9k_hw_attach_ops(ah); if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { ath_print(common, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); @@ -3524,8 +3533,13 @@ static void ar9002_hw_attach_ops(struct ath_hw *ah) ops->config_pci_powersave = ar9002_hw_configpcipowersave; + ar5008_hw_attach_phy_ops(ah); if (AR_SREV_9280_10_OR_LATER(ah)) ar9002_hw_attach_phy_ops(ah); - else - ar5008_hw_attach_phy_ops(ah); +} + +/* Sets up the AR9003 hardware familiy callbacks */ +static void ar9003_hw_attach_ops(struct ath_hw *ah) +{ + ar9003_hw_attach_phy_ops(ah); } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index a1ce79d1795d..3bc362134dce 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -783,8 +783,9 @@ void ath9k_hw_htc_resetinit(struct ath_hw *ah); void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, u32 *coef_mantissa, u32 *coef_exponent); -void ar9002_hw_attach_phy_ops(struct ath_hw *ah); void ar5008_hw_attach_phy_ops(struct ath_hw *ah); +void ar9002_hw_attach_phy_ops(struct ath_hw *ah); +void ar9003_hw_attach_phy_ops(struct ath_hw *ah); #define ATH_PCIE_CAP_LINK_CTRL 0x70 #define ATH_PCIE_CAP_LINK_L0S 1 -- cgit v1.2.3 From bab1f62e214f19d2edb1b5508ad5ba1b0a8a22ec Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:20 -0400 Subject: ath9k_hw: move init config and default after chip is up This allows us to add SREV checks on these helpers. Signed-off-by: Luis R. Rodriguez Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index f057d1ad9290..65c3b9e5d9c3 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -409,8 +409,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) ah->hw_version.subvendorid = 0; ah->ah_flags = 0; - if (ah->hw_version.devid == AR5416_AR9100_DEVID) - ah->hw_version.macVersion = AR_SREV_VERSION_9100; if (!AR_SREV_9100(ah)) ah->ah_flags = AH_USE_EEPROM; @@ -873,8 +871,8 @@ static int __ath9k_hw_init(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); int r = 0; - ath9k_hw_init_defaults(ah); - ath9k_hw_init_config(ah); + if (ah->hw_version.devid == AR5416_AR9100_DEVID) + ah->hw_version.macVersion = AR_SREV_VERSION_9100; if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { ath_print(common, ATH_DBG_FATAL, @@ -882,6 +880,9 @@ static int __ath9k_hw_init(struct ath_hw *ah) return -EIO; } + ath9k_hw_init_defaults(ah); + ath9k_hw_init_config(ah); + ath9k_hw_attach_ops(ah); if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { -- cgit v1.2.3 From 61accab9b5cfc2a7f42c88f30656d9f1771400d3 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:21 -0400 Subject: ath9k_hw: add the AR9003 ar9003_hw_macversion_supported() Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 65c3b9e5d9c3..56cae9500293 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -573,6 +573,17 @@ static bool ar9002_hw_macversion_supported(u32 macversion) return false; } +static bool ar9003_hw_macversion_supported(u32 macversion) +{ + switch (macversion) { + case AR_SREV_VERSION_9300: + return true; + default: + break; + } + return false; +} + static void ar9002_hw_init_cal_settings(struct ath_hw *ah) { if (AR_SREV_9160_10_OR_LATER(ah)) { @@ -3542,5 +3553,9 @@ static void ar9002_hw_attach_ops(struct ath_hw *ah) /* Sets up the AR9003 hardware familiy callbacks */ static void ar9003_hw_attach_ops(struct ath_hw *ah) { + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + + priv_ops->macversion_supported = ar9003_hw_macversion_supported; + ar9003_hw_attach_phy_ops(ah); } -- cgit v1.2.3 From 31a0bd3c7564ec79cf86a3eb9f9aaa3c47099d9b Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:22 -0400 Subject: ath9k_hw: disable ANI for AR9003 ANI is still being debugged on AR9003 by our systems team so it should not yet be enabled yet. When ANI will be enabled all ANI functionality is expected to be enabled so fill the ANI functionality to all for AR9003 for now as well. Cc: Enis Akay Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 56cae9500293..39dac9797e48 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -363,7 +363,13 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.ofdm_trig_high = 500; ah->config.cck_trig_high = 200; ah->config.cck_trig_low = 100; - ah->config.enable_ani = 1; + + /* + * For now ANI is disabled for AR9003, it is still + * being tested. + */ + if (!AR_SREV_9300_20_OR_LATER(ah)) + ah->config.enable_ani = 1; for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { ah->config.spurchans[i][0] = AR_NO_SPUR; @@ -941,7 +947,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) ath9k_hw_init_cal_settings(ah); ah->ani_function = ATH9K_ANI_ALL; - if (AR_SREV_9280_10_OR_LATER(ah)) + if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah)) ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; ath9k_hw_init_mode_regs(ah); -- cgit v1.2.3 From 3448f912c64bac4431b657b47b4e6e57565b656f Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:23 -0400 Subject: ath9k: disable the MIB interrupt if ANI is disabled Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index f7ef11407e27..494456cd1daa 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1436,7 +1436,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, if ((vif->type == NL80211_IFTYPE_STATION) || (vif->type == NL80211_IFTYPE_ADHOC) || (vif->type == NL80211_IFTYPE_MESH_POINT)) { - ah->imask |= ATH9K_INT_MIB; + if (ah->config.enable_ani) + ah->imask |= ATH9K_INT_MIB; ah->imask |= ATH9K_INT_TSFOOR; } -- cgit v1.2.3 From 1adf02ffad449ea955e21393e05b0e45ef2c16a4 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:38:24 -0400 Subject: ath9k_hw: Add hw cap flag for EDMA for the AR9003 family AR9003 supports extended DMA (EDMA), this comes with some bells and whistles on top of the legacy DMA that we are used to. Mark AR9003 and later chips EDMA capable. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 3 +++ drivers/net/wireless/ath/ath9k/hw.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 39dac9797e48..b33aa2d35d67 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2873,6 +2873,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE; } + if (AR_SREV_9300_20_OR_LATER(ah)) + pCap->hw_caps |= ATH9K_HW_CAP_EDMA; + return 0; } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 3bc362134dce..d89af6ef8b26 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -165,6 +165,7 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_ENHANCEDPM = BIT(14), ATH9K_HW_CAP_AUTOSLEEP = BIT(15), ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16), + ATH9K_HW_CAP_EDMA = BIT(17), }; enum ath9k_capability_type { -- cgit v1.2.3 From ceb2644576bcb9fe7b79614512c1efe2bf3c307c Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:38:25 -0400 Subject: ath9k_hw: Fill few hw cap for edma HP & LP queue depth and rx status length. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.h | 35 +++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/hw.c | 6 ++++- drivers/net/wireless/ath/ath9k/hw.h | 7 ++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/ath/ath9k/ar9003_mac.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h new file mode 100644 index 000000000000..dbf74eba4c58 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef AR9003_MAC_H +#define AR9003_MAC_H + +struct ar9003_rxs { + u32 ds_info; + u32 status1; + u32 status2; + u32 status3; + u32 status4; + u32 status5; + u32 status6; + u32 status7; + u32 status8; + u32 status9; + u32 status10; + u32 status11; +} __packed; + +#endif diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index b33aa2d35d67..8bd718c01238 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2873,8 +2873,12 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE; } - if (AR_SREV_9300_20_OR_LATER(ah)) + if (AR_SREV_9300_20_OR_LATER(ah)) { pCap->hw_caps |= ATH9K_HW_CAP_EDMA; + pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH; + pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH; + pCap->rx_status_len = sizeof(struct ar9003_rxs); + } return 0; } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index d89af6ef8b26..6bd87bf17ad4 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -28,6 +28,7 @@ #include "reg.h" #include "phy.h" #include "btcoex.h" +#include "ar9003_mac.h" #include "../regd.h" #include "../debug.h" @@ -135,6 +136,9 @@ #define TU_TO_USEC(_tu) ((_tu) << 10) +#define ATH9K_HW_RX_HP_QDEPTH 16 +#define ATH9K_HW_RX_LP_QDEPTH 128 + enum wireless_mode { ATH9K_MODE_11A = 0, ATH9K_MODE_11G, @@ -192,6 +196,9 @@ struct ath9k_hw_capabilities { u8 num_gpio_pins; u8 num_antcfg_2ghz; u8 num_antcfg_5ghz; + u8 rx_hp_qdepth; + u8 rx_lp_qdepth; + u8 rx_status_len; }; struct ath9k_ops_config { -- cgit v1.2.3 From cee1f625bfcabeed39138547be21d8995357f8e1 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:38:26 -0400 Subject: ath9k_hw: Add abstraction for rx enable Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw-ops.h | 5 +++++ drivers/net/wireless/ath/ath9k/hw.c | 2 ++ drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/mac.c | 17 +++++++++++------ drivers/net/wireless/ath/ath9k/mac.h | 3 ++- 5 files changed, 21 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 81f3d03f0dbf..19259fbad507 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -28,6 +28,11 @@ static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah, ath9k_hw_ops(ah)->config_pci_powersave(ah, restore, power_off); } +static inline void ath9k_hw_rxena(struct ath_hw *ah) +{ + ath9k_hw_ops(ah)->rx_enable(ah); +} + /* Private hardware call ops */ /* PHY ops */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8bd718c01238..c06c44c396de 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1566,6 +1566,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) ath9k_hw_settsf64(ah, tsf); + ar9002_hw_attach_mac_ops(ah); + if (AR_SREV_9280_10_OR_LATER(ah)) REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 6bd87bf17ad4..b07ee8d6d332 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -509,6 +509,7 @@ struct ath_hw_ops { void (*config_pci_powersave)(struct ath_hw *ah, int restore, int power_off); + void (*rx_enable)(struct ath_hw *ah); }; struct ath_hw { diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 4a2060e5a777..ae9d54c9c79a 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -16,6 +16,17 @@ #include "hw.h" +static void ar9002_hw_rx_enable(struct ath_hw *ah) +{ + REG_WRITE(ah, AR_CR, AR_CR_RXE); +} + +void ar9002_hw_attach_mac_ops(struct ath_hw *ah) +{ + struct ath_hw_ops *ops = ath9k_hw_ops(ah); + + ops->rx_enable = ar9002_hw_rx_enable; +} static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, struct ath9k_tx_queue_info *qi) { @@ -999,12 +1010,6 @@ void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp) } EXPORT_SYMBOL(ath9k_hw_putrxbuf); -void ath9k_hw_rxena(struct ath_hw *ah) -{ - REG_WRITE(ah, AR_CR, AR_CR_RXE); -} -EXPORT_SYMBOL(ath9k_hw_rxena); - void ath9k_hw_startpcureceive(struct ath_hw *ah) { ath9k_enable_mib_counters(ah); diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 68dbd7a8ddca..9e8500a8c800 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -729,10 +729,11 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, u32 size, u32 flags); bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); -void ath9k_hw_rxena(struct ath_hw *ah); void ath9k_hw_startpcureceive(struct ath_hw *ah); void ath9k_hw_stoppcurecv(struct ath_hw *ah); bool ath9k_hw_stopdmarecv(struct ath_hw *ah); int ath9k_hw_beaconq_setup(struct ath_hw *ah); +void ar9002_hw_attach_mac_ops(struct ath_hw *ah); + #endif /* MAC_H */ -- cgit v1.2.3 From ae3bb6d4628dae7ead588263177a0674221fea78 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:38:27 -0400 Subject: ath9k_hw: Fill rx_enable() for the AR9003 hardware family Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Makefile | 1 + drivers/net/wireless/ath/ath9k/ar9003_mac.c | 28 ++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_mac.h | 2 ++ drivers/net/wireless/ath/ath9k/hw.c | 6 ++++-- 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/ar9003_mac.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index ecf3f8c71d6f..96af3d96de5c 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -25,6 +25,7 @@ ath9k_hw-y:= hw.o \ ani.o \ btcoex.o \ mac.o \ + ar9003_mac.o obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c new file mode 100644 index 000000000000..ee84e64b8b0c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "hw.h" + +static void ar9003_hw_rx_enable(struct ath_hw *hw) +{ + REG_WRITE(hw, AR_CR, 0); +} + +void ar9003_hw_attach_mac_ops(struct ath_hw *hw) +{ + struct ath_hw_ops *ops = ath9k_hw_ops(hw); + + ops->rx_enable = ar9003_hw_rx_enable; +} diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index dbf74eba4c58..2a9d80e9e0c7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h @@ -32,4 +32,6 @@ struct ar9003_rxs { u32 status11; } __packed; +void ar9003_hw_attach_mac_ops(struct ath_hw *hw); + #endif diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index c06c44c396de..b4a8af1a544c 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1566,8 +1566,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) ath9k_hw_settsf64(ah, tsf); - ar9002_hw_attach_mac_ops(ah); - if (AR_SREV_9280_10_OR_LATER(ah)) REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); @@ -3563,6 +3561,8 @@ static void ar9002_hw_attach_ops(struct ath_hw *ah) ar5008_hw_attach_phy_ops(ah); if (AR_SREV_9280_10_OR_LATER(ah)) ar9002_hw_attach_phy_ops(ah); + + ar9002_hw_attach_mac_ops(ah); } /* Sets up the AR9003 hardware familiy callbacks */ @@ -3573,4 +3573,6 @@ static void ar9003_hw_attach_ops(struct ath_hw *ah) priv_ops->macversion_supported = ar9003_hw_macversion_supported; ar9003_hw_attach_phy_ops(ah); + + ar9003_hw_attach_mac_ops(ah); } -- cgit v1.2.3 From ad7b806065f5791696a1c9a4c2665f6421cbbf05 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:38:28 -0400 Subject: ath9k_hw: Add few routines for rx edma support * Set rx buf size in register 0x60 * Set rxdp on the respective hw rx queue (HP and LP queues) * Process rx descriptor Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 95 +++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_mac.h | 12 ++++ drivers/net/wireless/ath/ath9k/hw.h | 6 ++ drivers/net/wireless/ath/ath9k/mac.h | 2 + drivers/net/wireless/ath/ath9k/reg.h | 6 ++ 5 files changed, 121 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index ee84e64b8b0c..20890060ee2c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -26,3 +26,98 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) ops->rx_enable = ar9003_hw_rx_enable; } + +void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) +{ + REG_WRITE(ah, AR_DATABUF_SIZE, buf_size & AR_DATABUF_SIZE_MASK); +} +EXPORT_SYMBOL(ath9k_hw_set_rx_bufsize); + +void ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp, + enum ath9k_rx_qtype qtype) +{ + if (qtype == ATH9K_RX_QUEUE_HP) + REG_WRITE(ah, AR_HP_RXDP, rxdp); + else + REG_WRITE(ah, AR_LP_RXDP, rxdp); +} +EXPORT_SYMBOL(ath9k_hw_addrxbuf_edma); + +int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, + void *buf_addr) +{ + struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr; + unsigned int phyerr; + + /* TODO: byte swap on big endian for ar9300_10 */ + + if ((rxsp->status11 & AR_RxDone) == 0) + return -EINPROGRESS; + + if (MS(rxsp->ds_info, AR_DescId) != 0x168c) + return -EINVAL; + + if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0) + return -EINPROGRESS; + + rxs->rs_status = 0; + rxs->rs_flags = 0; + + rxs->rs_datalen = rxsp->status2 & AR_DataLen; + rxs->rs_tstamp = rxsp->status3; + + /* XXX: Keycache */ + rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined); + rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00); + rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01); + rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02); + rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10); + rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11); + rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12); + + if (rxsp->status11 & AR_RxKeyIdxValid) + rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx); + else + rxs->rs_keyix = ATH9K_RXKEYIX_INVALID; + + rxs->rs_rate = MS(rxsp->status1, AR_RxRate); + rxs->rs_more = (rxsp->status2 & AR_RxMore) ? 1 : 0; + + rxs->rs_isaggr = (rxsp->status11 & AR_RxAggr) ? 1 : 0; + rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0; + rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7); + rxs->rs_flags = (rxsp->status4 & AR_GI) ? ATH9K_RX_GI : 0; + rxs->rs_flags |= (rxsp->status4 & AR_2040) ? ATH9K_RX_2040 : 0; + + rxs->evm0 = rxsp->status6; + rxs->evm1 = rxsp->status7; + rxs->evm2 = rxsp->status8; + rxs->evm3 = rxsp->status9; + rxs->evm4 = (rxsp->status10 & 0xffff); + + if (rxsp->status11 & AR_PreDelimCRCErr) + rxs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE; + + if (rxsp->status11 & AR_PostDelimCRCErr) + rxs->rs_flags |= ATH9K_RX_DELIM_CRC_POST; + + if (rxsp->status11 & AR_DecryptBusyErr) + rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY; + + if ((rxsp->status11 & AR_RxFrameOK) == 0) { + if (rxsp->status11 & AR_CRCErr) { + rxs->rs_status |= ATH9K_RXERR_CRC; + } else if (rxsp->status11 & AR_PHYErr) { + rxs->rs_status |= ATH9K_RXERR_PHY; + phyerr = MS(rxsp->status11, AR_PHYErrCode); + rxs->rs_phyerr = phyerr; + } else if (rxsp->status11 & AR_DecryptCRCErr) { + rxs->rs_status |= ATH9K_RXERR_DECRYPT; + } else if (rxsp->status11 & AR_MichaelErr) { + rxs->rs_status |= ATH9K_RXERR_MIC; + } + } + + return 0; +} +EXPORT_SYMBOL(ath9k_hw_process_rxdesc_edma); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index 2a9d80e9e0c7..b22f78c320c5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h @@ -17,6 +17,11 @@ #ifndef AR9003_MAC_H #define AR9003_MAC_H +#define AR_DescId 0xffff0000 +#define AR_DescId_S 16 +#define AR_CtrlStat 0x00004000 +#define AR_TxRxDesc 0x00008000 + struct ar9003_rxs { u32 ds_info; u32 status1; @@ -33,5 +38,12 @@ struct ar9003_rxs { } __packed; void ar9003_hw_attach_mac_ops(struct ath_hw *hw); +void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size); +void ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp, + enum ath9k_rx_qtype qtype); + +int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, + struct ath_rx_status *rxs, + void *buf_addr); #endif diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index b07ee8d6d332..d713ff2dfc55 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -370,6 +370,12 @@ enum ser_reg_mode { SER_REG_MODE_AUTO = 2, }; +enum ath9k_rx_qtype { + ATH9K_RX_QUEUE_HP, + ATH9K_RX_QUEUE_LP, + ATH9K_RX_QUEUE_MAX, +}; + struct ath9k_beacon_state { u32 bs_nexttbtt; u32 bs_nextdtim; diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 9e8500a8c800..126a4030be1d 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -148,6 +148,8 @@ struct ath_rx_status { u32 evm0; u32 evm1; u32 evm2; + u32 evm3; + u32 evm4; }; struct ath_htc_rx_status { diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index d52489149167..bc48bc92076f 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -144,6 +144,9 @@ #define AR_MACMISC_MISC_OBS_BUS_MSB_S 15 #define AR_MACMISC_MISC_OBS_BUS_1 1 +#define AR_DATABUF_SIZE 0x0060 +#define AR_DATABUF_SIZE_MASK 0x00000FFF + #define AR_GTXTO 0x0064 #define AR_GTXTO_TIMEOUT_COUNTER 0x0000FFFF #define AR_GTXTO_TIMEOUT_LIMIT 0xFFFF0000 @@ -160,6 +163,9 @@ #define AR_CST_TIMEOUT_LIMIT 0xFFFF0000 #define AR_CST_TIMEOUT_LIMIT_S 16 +#define AR_HP_RXDP 0x0074 +#define AR_LP_RXDP 0x0078 + #define AR_ISR 0x0080 #define AR_ISR_RXOK 0x00000001 #define AR_ISR_RXDESC 0x00000002 -- cgit v1.2.3 From 1f3f06184006dff1ec439c56dcee9a99ed93e985 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Thu, 15 Apr 2010 17:38:29 -0400 Subject: ath9k_hw: update the chip tests for AR9003 The AR9003 family requires a change on the loop and can also skip testing the PHY timing registers. This chip test can now be used by all Atheros hardware families, including legacy. We can eventually move this out to the generic ath module. Signed-off-by: Senthil Balasubramanian Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index b4a8af1a544c..034b6fdf01f3 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -297,18 +297,25 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah) REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); } +/* This should work for all families including legacy */ static bool ath9k_hw_chip_test(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); - u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) }; + u32 regAddr[2] = { AR_STA_ID0 }; u32 regHold[2]; u32 patternData[4] = { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 }; - int i, j; + int i, j, loop_max; - for (i = 0; i < 2; i++) { + if (!AR_SREV_9300_20_OR_LATER(ah)) { + loop_max = 2; + regAddr[1] = AR_PHY_BASE + (8 << 2); + } else + loop_max = 1; + + for (i = 0; i < loop_max; i++) { u32 addr = regAddr[i]; u32 wrData, rdData; -- cgit v1.2.3 From 84e2169b0fead5d87de0a29f17a06fba904bc46b Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Thu, 15 Apr 2010 17:38:30 -0400 Subject: ath9k_hw: prevent reset control register zeroing on AR9003 reset Also, no need for the udelay(2) on AR9003 hardware. Signed-off-by: Senthil Balasubramanian Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 034b6fdf01f3..601dbf79cc0d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1385,9 +1385,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) REG_WRITE(ah, AR_RC, AR_RC_AHB); REG_WRITE(ah, AR_RTC_RESET, 0); - udelay(2); - if (!AR_SREV_9100(ah)) + if (!AR_SREV_9300_20_OR_LATER(ah)) + udelay(2); + + if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) REG_WRITE(ah, AR_RC, 0); REG_WRITE(ah, AR_RTC_RESET, 1); -- cgit v1.2.3 From da6f1d7f5f46d71f85d69a6521a16b83ad00e7e3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Apr 2010 17:38:31 -0400 Subject: ath9k_hw: Add AR9003 PHY register definitions Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 1 + drivers/net/wireless/ath/ath9k/ar9003_phy.h | 804 ++++++++++++++++++++++++++++ 2 files changed, 805 insertions(+) create mode 100644 drivers/net/wireless/ath/ath9k/ar9003_phy.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index c4511b8ff75a..084b0f92afde 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -15,6 +15,7 @@ */ #include "hw.h" +#include "ar9003_phy.h" /** * ar9003_hw_set_channel - set channel on single-chip device diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h new file mode 100644 index 000000000000..2e51e5795a31 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -0,0 +1,804 @@ +/* + * Copyright (c) 2002-2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef AR9003_PHY_H +#define AR9003_PHY_H + +/* + * Channel Register Map + */ +#define AR_CHAN_BASE 0x9800 + +#define AR_PHY_TIMING1 (AR_CHAN_BASE + 0x0) +#define AR_PHY_TIMING2 (AR_CHAN_BASE + 0x4) +#define AR_PHY_TIMING3 (AR_CHAN_BASE + 0x8) +#define AR_PHY_TIMING4 (AR_CHAN_BASE + 0xc) +#define AR_PHY_TIMING5 (AR_CHAN_BASE + 0x10) +#define AR_PHY_TIMING6 (AR_CHAN_BASE + 0x14) +#define AR_PHY_TIMING11 (AR_CHAN_BASE + 0x18) +#define AR_PHY_SPUR_REG (AR_CHAN_BASE + 0x1c) +#define AR_PHY_RX_IQCAL_CORR_B0 (AR_CHAN_BASE + 0xdc) +#define AR_PHY_TX_IQCAL_CONTROL_3 (AR_CHAN_BASE + 0xb0) + +#define AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN 0x20000000 +#define AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN_S 29 + +#define AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN 0x80000000 +#define AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN_S 31 + +#define AR_PHY_FIND_SIG_LOW (AR_CHAN_BASE + 0x20) + +#define AR_PHY_SFCORR (AR_CHAN_BASE + 0x24) +#define AR_PHY_SFCORR_LOW (AR_CHAN_BASE + 0x28) +#define AR_PHY_SFCORR_EXT (AR_CHAN_BASE + 0x2c) + +#define AR_PHY_EXT_CCA (AR_CHAN_BASE + 0x30) +#define AR_PHY_RADAR_0 (AR_CHAN_BASE + 0x34) +#define AR_PHY_RADAR_1 (AR_CHAN_BASE + 0x38) +#define AR_PHY_RADAR_EXT (AR_CHAN_BASE + 0x3c) +#define AR_PHY_MULTICHAIN_CTRL (AR_CHAN_BASE + 0x80) +#define AR_PHY_PERCHAIN_CSD (AR_CHAN_BASE + 0x84) + +#define AR_PHY_TX_PHASE_RAMP_0 (AR_CHAN_BASE + 0xd0) +#define AR_PHY_ADC_GAIN_DC_CORR_0 (AR_CHAN_BASE + 0xd4) +#define AR_PHY_IQ_ADC_MEAS_0_B0 (AR_CHAN_BASE + 0xc0) +#define AR_PHY_IQ_ADC_MEAS_1_B0 (AR_CHAN_BASE + 0xc4) +#define AR_PHY_IQ_ADC_MEAS_2_B0 (AR_CHAN_BASE + 0xc8) +#define AR_PHY_IQ_ADC_MEAS_3_B0 (AR_CHAN_BASE + 0xcc) + +/* The following registers changed position from AR9300 1.0 to AR9300 2.0 */ +#define AR_PHY_TX_PHASE_RAMP_0_9300_10 (AR_CHAN_BASE + 0xd0 - 0x10) +#define AR_PHY_ADC_GAIN_DC_CORR_0_9300_10 (AR_CHAN_BASE + 0xd4 - 0x10) +#define AR_PHY_IQ_ADC_MEAS_0_B0_9300_10 (AR_CHAN_BASE + 0xc0 + 0x8) +#define AR_PHY_IQ_ADC_MEAS_1_B0_9300_10 (AR_CHAN_BASE + 0xc4 + 0x8) +#define AR_PHY_IQ_ADC_MEAS_2_B0_9300_10 (AR_CHAN_BASE + 0xc8 + 0x8) +#define AR_PHY_IQ_ADC_MEAS_3_B0_9300_10 (AR_CHAN_BASE + 0xcc + 0x8) + +#define AR_PHY_TX_CRC (AR_CHAN_BASE + 0xa0) +#define AR_PHY_TST_DAC_CONST (AR_CHAN_BASE + 0xa4) +#define AR_PHY_SPUR_REPORT_0 (AR_CHAN_BASE + 0xa8) +#define AR_PHY_CHAN_INFO_TAB_0 (AR_CHAN_BASE + 0x300) + +/* + * Channel Field Definitions + */ +#define AR_PHY_TIMING2_USE_FORCE_PPM 0x00001000 +#define AR_PHY_TIMING2_FORCE_PPM_VAL 0x00000fff +#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 +#define AR_PHY_TIMING3_DSC_MAN_S 17 +#define AR_PHY_TIMING3_DSC_EXP 0x0001E000 +#define AR_PHY_TIMING3_DSC_EXP_S 13 +#define AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX 0xF000 +#define AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX_S 12 +#define AR_PHY_TIMING4_DO_CAL 0x10000 +#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 +#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 +#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001 +#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00 +#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8 +#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000 +#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14 +#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000 +#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21 +#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F +#define AR_PHY_SFCORR_M2COUNT_THR_S 0 +#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000 +#define AR_PHY_SFCORR_M1_THRESH_S 17 +#define AR_PHY_SFCORR_M2_THRESH 0x7F000000 +#define AR_PHY_SFCORR_M2_THRESH_S 24 +#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F +#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0 +#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80 +#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 +#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 +#define AR_PHY_EXT_CCA_THRESH62 0x007F0000 +#define AR_PHY_EXT_CCA_THRESH62_S 16 +#define AR_PHY_EXT_MINCCA_PWR 0x01FF0000 +#define AR_PHY_EXT_MINCCA_PWR_S 16 +#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE +#define AR_PHY_TIMING5_CYCPWR_THR1_S 1 +#define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE 0x00000001 +#define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE_S 0 +#define AR_PHY_TIMING5_CYCPWR_THR1A 0x007F0000 +#define AR_PHY_TIMING5_CYCPWR_THR1A_S 16 +#define AR_PHY_TIMING5_RSSI_THR1A (0x7F << 16) +#define AR_PHY_TIMING5_RSSI_THR1A_S 16 +#define AR_PHY_TIMING5_RSSI_THR1A_ENA (0x1 << 15) +#define AR_PHY_RADAR_0_ENA 0x00000001 +#define AR_PHY_RADAR_0_FFT_ENA 0x80000000 +#define AR_PHY_RADAR_0_INBAND 0x0000003e +#define AR_PHY_RADAR_0_INBAND_S 1 +#define AR_PHY_RADAR_0_PRSSI 0x00000FC0 +#define AR_PHY_RADAR_0_PRSSI_S 6 +#define AR_PHY_RADAR_0_HEIGHT 0x0003F000 +#define AR_PHY_RADAR_0_HEIGHT_S 12 +#define AR_PHY_RADAR_0_RRSSI 0x00FC0000 +#define AR_PHY_RADAR_0_RRSSI_S 18 +#define AR_PHY_RADAR_0_FIRPWR 0x7F000000 +#define AR_PHY_RADAR_0_FIRPWR_S 24 +#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000 +#define AR_PHY_RADAR_1_USE_FIR128 0x00400000 +#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000 +#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16 +#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000 +#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000 +#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000 +#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00 +#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8 +#define AR_PHY_RADAR_1_MAXLEN 0x000000FF +#define AR_PHY_RADAR_1_MAXLEN_S 0 +#define AR_PHY_RADAR_EXT_ENA 0x00004000 +#define AR_PHY_RADAR_DC_PWR_THRESH 0x007f8000 +#define AR_PHY_RADAR_DC_PWR_THRESH_S 15 +#define AR_PHY_RADAR_LB_DC_CAP 0x7f800000 +#define AR_PHY_RADAR_LB_DC_CAP_S 23 +#define AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW (0x3f << 6) +#define AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW_S 6 +#define AR_PHY_FIND_SIG_LOW_FIRPWR (0x7f << 12) +#define AR_PHY_FIND_SIG_LOW_FIRPWR_S 12 +#define AR_PHY_FIND_SIG_LOW_FIRPWR_SIGN_BIT 19 +#define AR_PHY_FIND_SIG_LOW_RELSTEP 0x1f +#define AR_PHY_FIND_SIG_LOW_RELSTEP_S 0 +#define AR_PHY_FIND_SIG_LOW_RELSTEP_SIGN_BIT 5 +#define AR_PHY_CHAN_INFO_TAB_S2_READ 0x00000008 +#define AR_PHY_CHAN_INFO_TAB_S2_READ_S 3 +#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF 0x0000007F +#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF_S 0 +#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF 0x00003F80 +#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF_S 7 +#define AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE 0x00004000 +#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF 0x003f8000 +#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF_S 15 +#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF 0x1fc00000 +#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF_S 22 + +/* + * MRC Register Map + */ +#define AR_MRC_BASE 0x9c00 + +#define AR_PHY_TIMING_3A (AR_MRC_BASE + 0x0) +#define AR_PHY_LDPC_CNTL1 (AR_MRC_BASE + 0x4) +#define AR_PHY_LDPC_CNTL2 (AR_MRC_BASE + 0x8) +#define AR_PHY_PILOT_SPUR_MASK (AR_MRC_BASE + 0xc) +#define AR_PHY_CHAN_SPUR_MASK (AR_MRC_BASE + 0x10) +#define AR_PHY_SGI_DELTA (AR_MRC_BASE + 0x14) +#define AR_PHY_ML_CNTL_1 (AR_MRC_BASE + 0x18) +#define AR_PHY_ML_CNTL_2 (AR_MRC_BASE + 0x1c) +#define AR_PHY_TST_ADC (AR_MRC_BASE + 0x20) + +/* + * MRC Feild Definitions + */ +#define AR_PHY_SGI_DSC_MAN 0x0007FFF0 +#define AR_PHY_SGI_DSC_MAN_S 4 +#define AR_PHY_SGI_DSC_EXP 0x0000000F +#define AR_PHY_SGI_DSC_EXP_S 0 +/* + * BBB Register Map + */ +#define AR_BBB_BASE 0x9d00 + +/* + * AGC Register Map + */ +#define AR_AGC_BASE 0x9e00 + +#define AR_PHY_SETTLING (AR_AGC_BASE + 0x0) +#define AR_PHY_FORCEMAX_GAINS_0 (AR_AGC_BASE + 0x4) +#define AR_PHY_GAINS_MINOFF0 (AR_AGC_BASE + 0x8) +#define AR_PHY_DESIRED_SZ (AR_AGC_BASE + 0xc) +#define AR_PHY_FIND_SIG (AR_AGC_BASE + 0x10) +#define AR_PHY_AGC (AR_AGC_BASE + 0x14) +#define AR_PHY_EXT_ATTEN_CTL_0 (AR_AGC_BASE + 0x18) +#define AR_PHY_CCA_0 (AR_AGC_BASE + 0x1c) +#define AR_PHY_EXT_CCA0 (AR_AGC_BASE + 0x20) +#define AR_PHY_RESTART (AR_AGC_BASE + 0x24) +#define AR_PHY_MC_GAIN_CTRL (AR_AGC_BASE + 0x28) +#define AR_PHY_EXTCHN_PWRTHR1 (AR_AGC_BASE + 0x2c) +#define AR_PHY_EXT_CHN_WIN (AR_AGC_BASE + 0x30) +#define AR_PHY_20_40_DET_THR (AR_AGC_BASE + 0x34) +#define AR_PHY_RIFS_SRCH (AR_AGC_BASE + 0x38) +#define AR_PHY_PEAK_DET_CTRL_1 (AR_AGC_BASE + 0x3c) +#define AR_PHY_PEAK_DET_CTRL_2 (AR_AGC_BASE + 0x40) +#define AR_PHY_RX_GAIN_BOUNDS_1 (AR_AGC_BASE + 0x44) +#define AR_PHY_RX_GAIN_BOUNDS_2 (AR_AGC_BASE + 0x48) +#define AR_PHY_RSSI_0 (AR_AGC_BASE + 0x180) +#define AR_PHY_SPUR_CCK_REP0 (AR_AGC_BASE + 0x184) +#define AR_PHY_CCK_DETECT (AR_AGC_BASE + 0x1c0) +#define AR_PHY_DAG_CTRLCCK (AR_AGC_BASE + 0x1c4) +#define AR_PHY_IQCORR_CTRL_CCK (AR_AGC_BASE + 0x1c8) + +#define AR_PHY_CCK_SPUR_MIT (AR_AGC_BASE + 0x1cc) +#define AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR 0x000001fe +#define AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR_S 1 +#define AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE 0x60000000 +#define AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE_S 29 +#define AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT 0x00000001 +#define AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT_S 0 +#define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ 0x1ffffe00 +#define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ_S 9 + +#define AR_PHY_RX_OCGAIN (AR_AGC_BASE + 0x200) + +#define AR_PHY_CCA_NOM_VAL_9300_2GHZ -110 +#define AR_PHY_CCA_NOM_VAL_9300_5GHZ -115 +#define AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ -125 +#define AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ -125 +#define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ -95 +#define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ -100 + +/* + * AGC Field Definitions + */ +#define AR_PHY_EXT_ATTEN_CTL_RXTX_MARGIN 0x00FC0000 +#define AR_PHY_EXT_ATTEN_CTL_RXTX_MARGIN_S 18 +#define AR_PHY_EXT_ATTEN_CTL_BSW_MARGIN 0x00003C00 +#define AR_PHY_EXT_ATTEN_CTL_BSW_MARGIN_S 10 +#define AR_PHY_EXT_ATTEN_CTL_BSW_ATTEN 0x0000001F +#define AR_PHY_EXT_ATTEN_CTL_BSW_ATTEN_S 0 +#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_MARGIN 0x003E0000 +#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_MARGIN_S 17 +#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN 0x0001F000 +#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN_S 12 +#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_DB 0x00000FC0 +#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_DB_S 6 +#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB 0x0000003F +#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB_S 0 +#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000 +#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12 +#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000 +#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18 +#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80 +#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7 +#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000 +#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14 +#define AR_PHY_SETTLING_SWITCH 0x00003F80 +#define AR_PHY_SETTLING_SWITCH_S 7 +#define AR_PHY_DESIRED_SZ_ADC 0x000000FF +#define AR_PHY_DESIRED_SZ_ADC_S 0 +#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00 +#define AR_PHY_DESIRED_SZ_PGA_S 8 +#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000 +#define AR_PHY_DESIRED_SZ_TOT_DES_S 20 +#define AR_PHY_MINCCA_PWR 0x1FF00000 +#define AR_PHY_MINCCA_PWR_S 20 +#define AR_PHY_CCA_THRESH62 0x0007F000 +#define AR_PHY_CCA_THRESH62_S 12 +#define AR9280_PHY_MINCCA_PWR 0x1FF00000 +#define AR9280_PHY_MINCCA_PWR_S 20 +#define AR9280_PHY_CCA_THRESH62 0x000FF000 +#define AR9280_PHY_CCA_THRESH62_S 12 +#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF +#define AR_PHY_EXT_CCA0_THRESH62_S 0 +#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F +#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0 +#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 +#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6 +#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 + +#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200 +#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR_S 9 +#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00 +#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10 + +#define AR_PHY_RIFS_INIT_DELAY 0x3ff0000 +#define AR_PHY_AGC_COARSE_LOW 0x00007F80 +#define AR_PHY_AGC_COARSE_LOW_S 7 +#define AR_PHY_AGC_COARSE_HIGH 0x003F8000 +#define AR_PHY_AGC_COARSE_HIGH_S 15 +#define AR_PHY_AGC_COARSE_PWR_CONST 0x0000007F +#define AR_PHY_AGC_COARSE_PWR_CONST_S 0 +#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000 +#define AR_PHY_FIND_SIG_FIRSTEP_S 12 +#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000 +#define AR_PHY_FIND_SIG_FIRPWR_S 18 +#define AR_PHY_FIND_SIG_FIRPWR_SIGN_BIT 25 +#define AR_PHY_FIND_SIG_RELPWR (0x1f << 6) +#define AR_PHY_FIND_SIG_RELPWR_S 6 +#define AR_PHY_FIND_SIG_RELPWR_SIGN_BIT 11 +#define AR_PHY_FIND_SIG_RELSTEP 0x1f +#define AR_PHY_FIND_SIG_RELSTEP_S 0 +#define AR_PHY_FIND_SIG_RELSTEP_SIGN_BIT 5 +#define AR_PHY_RESTART_DIV_GC 0x001C0000 +#define AR_PHY_RESTART_DIV_GC_S 18 +#define AR_PHY_RESTART_ENA 0x01 +#define AR_PHY_DC_RESTART_DIS 0x40000000 + +#define AR_PHY_TPC_OLPC_GAIN_DELTA_PAL_ON 0xFF000000 +#define AR_PHY_TPC_OLPC_GAIN_DELTA_PAL_ON_S 24 +#define AR_PHY_TPC_OLPC_GAIN_DELTA 0x00FF0000 +#define AR_PHY_TPC_OLPC_GAIN_DELTA_S 16 + +#define AR_PHY_TPC_6_ERROR_EST_MODE 0x03000000 +#define AR_PHY_TPC_6_ERROR_EST_MODE_S 24 + +/* + * SM Register Map + */ +#define AR_SM_BASE 0xa200 + +#define AR_PHY_D2_CHIP_ID (AR_SM_BASE + 0x0) +#define AR_PHY_GEN_CTRL (AR_SM_BASE + 0x4) +#define AR_PHY_MODE (AR_SM_BASE + 0x8) +#define AR_PHY_ACTIVE (AR_SM_BASE + 0xc) +#define AR_PHY_SPUR_MASK_A (AR_SM_BASE + 0x20) +#define AR_PHY_SPUR_MASK_B (AR_SM_BASE + 0x24) +#define AR_PHY_SPECTRAL_SCAN (AR_SM_BASE + 0x28) +#define AR_PHY_RADAR_BW_FILTER (AR_SM_BASE + 0x2c) +#define AR_PHY_SEARCH_START_DELAY (AR_SM_BASE + 0x30) +#define AR_PHY_MAX_RX_LEN (AR_SM_BASE + 0x34) +#define AR_PHY_FRAME_CTL (AR_SM_BASE + 0x38) +#define AR_PHY_RFBUS_REQ (AR_SM_BASE + 0x3c) +#define AR_PHY_RFBUS_GRANT (AR_SM_BASE + 0x40) +#define AR_PHY_RIFS (AR_SM_BASE + 0x44) +#define AR_PHY_RX_CLR_DELAY (AR_SM_BASE + 0x50) +#define AR_PHY_RX_DELAY (AR_SM_BASE + 0x54) + +#define AR_PHY_XPA_TIMING_CTL (AR_SM_BASE + 0x64) +#define AR_PHY_MISC_PA_CTL (AR_SM_BASE + 0x80) +#define AR_PHY_SWITCH_CHAIN_0 (AR_SM_BASE + 0x84) +#define AR_PHY_SWITCH_COM (AR_SM_BASE + 0x88) +#define AR_PHY_SWITCH_COM_2 (AR_SM_BASE + 0x8c) +#define AR_PHY_RX_CHAINMASK (AR_SM_BASE + 0xa0) +#define AR_PHY_CAL_CHAINMASK (AR_SM_BASE + 0xc0) +#define AR_PHY_AGC_CONTROL (AR_SM_BASE + 0xc4) +#define AR_PHY_CALMODE (AR_SM_BASE + 0xc8) +#define AR_PHY_FCAL_1 (AR_SM_BASE + 0xcc) +#define AR_PHY_FCAL_2_0 (AR_SM_BASE + 0xd0) +#define AR_PHY_DFT_TONE_CTL_0 (AR_SM_BASE + 0xd4) +#define AR_PHY_CL_CAL_CTL (AR_SM_BASE + 0xd8) +#define AR_PHY_CL_TAB_0 (AR_SM_BASE + 0x100) +#define AR_PHY_SYNTH_CONTROL (AR_SM_BASE + 0x140) +#define AR_PHY_ADDAC_CLK_SEL (AR_SM_BASE + 0x144) +#define AR_PHY_PLL_CTL (AR_SM_BASE + 0x148) +#define AR_PHY_ANALOG_SWAP (AR_SM_BASE + 0x14c) +#define AR_PHY_ADDAC_PARA_CTL (AR_SM_BASE + 0x150) +#define AR_PHY_XPA_CFG (AR_SM_BASE + 0x158) + +#define AR_PHY_TEST (AR_SM_BASE + 0x160) + +#define AR_PHY_TEST_BBB_OBS_SEL 0x780000 +#define AR_PHY_TEST_BBB_OBS_SEL_S 19 + +#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23 +#define AR_PHY_TEST_RX_OBS_SEL_BIT5 (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S) + +#define AR_PHY_TEST_CHAIN_SEL 0xC0000000 +#define AR_PHY_TEST_CHAIN_SEL_S 30 + +#define AR_PHY_TEST_CTL_STATUS (AR_SM_BASE + 0x164) +#define AR_PHY_TEST_CTL_TSTDAC_EN 0x1 +#define AR_PHY_TEST_CTL_TSTDAC_EN_S 0 +#define AR_PHY_TEST_CTL_TX_OBS_SEL 0x1C +#define AR_PHY_TEST_CTL_TX_OBS_SEL_S 2 +#define AR_PHY_TEST_CTL_TX_OBS_MUX_SEL 0x60 +#define AR_PHY_TEST_CTL_TX_OBS_MUX_SEL_S 5 +#define AR_PHY_TEST_CTL_TSTADC_EN 0x100 +#define AR_PHY_TEST_CTL_TSTADC_EN_S 8 +#define AR_PHY_TEST_CTL_RX_OBS_SEL 0x3C00 +#define AR_PHY_TEST_CTL_RX_OBS_SEL_S 10 + + +#define AR_PHY_TSTDAC (AR_SM_BASE + 0x168) + +#define AR_PHY_CHAN_STATUS (AR_SM_BASE + 0x16c) +#define AR_PHY_CHAN_INFO_MEMORY (AR_SM_BASE + 0x170) +#define AR_PHY_CHNINFO_NOISEPWR (AR_SM_BASE + 0x174) +#define AR_PHY_CHNINFO_GAINDIFF (AR_SM_BASE + 0x178) +#define AR_PHY_CHNINFO_FINETIM (AR_SM_BASE + 0x17c) +#define AR_PHY_CHAN_INFO_GAIN_0 (AR_SM_BASE + 0x180) +#define AR_PHY_SCRAMBLER_SEED (AR_SM_BASE + 0x190) +#define AR_PHY_CCK_TX_CTRL (AR_SM_BASE + 0x194) + +#define AR_PHY_HEAVYCLIP_CTL (AR_SM_BASE + 0x1a4) +#define AR_PHY_HEAVYCLIP_20 (AR_SM_BASE + 0x1a8) +#define AR_PHY_HEAVYCLIP_40 (AR_SM_BASE + 0x1ac) +#define AR_PHY_ILLEGAL_TXRATE (AR_SM_BASE + 0x1b0) + +#define AR_PHY_PWRTX_MAX (AR_SM_BASE + 0x1f0) +#define AR_PHY_POWER_TX_SUB (AR_SM_BASE + 0x1f4) + +#define AR_PHY_TPC_4_B0 (AR_SM_BASE + 0x204) +#define AR_PHY_TPC_5_B0 (AR_SM_BASE + 0x208) +#define AR_PHY_TPC_6_B0 (AR_SM_BASE + 0x20c) +#define AR_PHY_TPC_11_B0 (AR_SM_BASE + 0x220) +#define AR_PHY_TPC_18 (AR_SM_BASE + 0x23c) +#define AR_PHY_TPC_19 (AR_SM_BASE + 0x240) + +#define AR_PHY_TX_FORCED_GAIN (AR_SM_BASE + 0x258) + +#define AR_PHY_PDADC_TAB_0 (AR_SM_BASE + 0x280) + +#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448) +#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440) +#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c) +#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B0 (AR_SM_BASE + 0x450) + +#define AR_PHY_PANIC_WD_STATUS (AR_SM_BASE + 0x5c0) +#define AR_PHY_PANIC_WD_CTL_1 (AR_SM_BASE + 0x5c4) +#define AR_PHY_PANIC_WD_CTL_2 (AR_SM_BASE + 0x5c8) +#define AR_PHY_BT_CTL (AR_SM_BASE + 0x5cc) +#define AR_PHY_ONLY_WARMRESET (AR_SM_BASE + 0x5d0) +#define AR_PHY_ONLY_CTL (AR_SM_BASE + 0x5d4) +#define AR_PHY_ECO_CTRL (AR_SM_BASE + 0x5dc) +#define AR_PHY_BB_THERM_ADC_1 (AR_SM_BASE + 0x248) + +#define AR_PHY_65NM_CH0_SYNTH4 0x1608c +#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT 0x00000002 +#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S 1 +#define AR_PHY_65NM_CH0_SYNTH7 0x16098 +#define AR_PHY_65NM_CH0_BIAS1 0x160c0 +#define AR_PHY_65NM_CH0_BIAS2 0x160c4 +#define AR_PHY_65NM_CH0_BIAS4 0x160cc +#define AR_PHY_65NM_CH0_RXTX4 0x1610c +#define AR_PHY_65NM_CH0_THERM 0x16290 + +#define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000 +#define AR_PHY_65NM_CH0_THERM_LOCAL_S 31 +#define AR_PHY_65NM_CH0_THERM_START 0x20000000 +#define AR_PHY_65NM_CH0_THERM_START_S 29 +#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT 0x0000ff00 +#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT_S 8 + +#define AR_PHY_65NM_CH0_RXTX1 0x16100 +#define AR_PHY_65NM_CH0_RXTX2 0x16104 +#define AR_PHY_65NM_CH1_RXTX1 0x16500 +#define AR_PHY_65NM_CH1_RXTX2 0x16504 +#define AR_PHY_65NM_CH2_RXTX1 0x16900 +#define AR_PHY_65NM_CH2_RXTX2 0x16904 + +#define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT 0x00380000 +#define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT_S 19 +#define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT 0x00c00000 +#define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT_S 22 +#define AR_PHY_LNAGAIN_LONG_SHIFT 0xe0000000 +#define AR_PHY_LNAGAIN_LONG_SHIFT_S 29 +#define AR_PHY_MXRGAIN_LONG_SHIFT 0x03000000 +#define AR_PHY_MXRGAIN_LONG_SHIFT_S 24 +#define AR_PHY_VGAGAIN_LONG_SHIFT 0x1c000000 +#define AR_PHY_VGAGAIN_LONG_SHIFT_S 26 +#define AR_PHY_SCFIR_GAIN_LONG_SHIFT 0x00000001 +#define AR_PHY_SCFIR_GAIN_LONG_SHIFT_S 0 +#define AR_PHY_MANRXGAIN_LONG_SHIFT 0x00000002 +#define AR_PHY_MANRXGAIN_LONG_SHIFT_S 1 + +/* + * SM Field Definitions + */ +#define AR_PHY_CL_CAL_ENABLE 0x00000002 +#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001 +#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000 +#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22 + +#define AR_PHY_ADDAC_PARACTL_OFF_PWDADC 0x00008000 + +#define AR_PHY_FCAL20_CAP_STATUS_0 0x01f00000 +#define AR_PHY_FCAL20_CAP_STATUS_0_S 20 + +#define AR_PHY_RFBUS_REQ_EN 0x00000001 /* request for RF bus */ +#define AR_PHY_RFBUS_GRANT_EN 0x00000001 /* RF bus granted */ +#define AR_PHY_GC_TURBO_MODE 0x00000001 /* set turbo mode bits */ +#define AR_PHY_GC_TURBO_SHORT 0x00000002 /* set short symbols to turbo mode setting */ +#define AR_PHY_GC_DYN2040_EN 0x00000004 /* enable dyn 20/40 mode */ +#define AR_PHY_GC_DYN2040_PRI_ONLY 0x00000008 /* dyn 20/40 - primary only */ +#define AR_PHY_GC_DYN2040_PRI_CH 0x00000010 /* dyn 20/40 - primary ch offset (0=+10MHz, 1=-10MHz)*/ +#define AR_PHY_GC_DYN2040_EXT_CH 0x00000020 /* dyn 20/40 - ext ch spacing (0=20MHz/ 1=25MHz) */ +#define AR_PHY_GC_HT_EN 0x00000040 /* ht enable */ +#define AR_PHY_GC_SHORT_GI_40 0x00000080 /* allow short GI for HT 40 */ +#define AR_PHY_GC_WALSH 0x00000100 /* walsh spatial spreading for 2 chains,2 streams TX */ +#define AR_PHY_GC_SINGLE_HT_LTF1 0x00000200 /* single length (4us) 1st HT long training symbol */ +#define AR_PHY_GC_GF_DETECT_EN 0x00000400 /* enable Green Field detection. Only affects rx, not tx */ +#define AR_PHY_GC_ENABLE_DAC_FIFO 0x00000800 /* fifo between bb and dac */ +#define AR_PHY_RX_DELAY_DELAY 0x00003FFF /* delay from wakeup to rx ena */ + +#define AR_PHY_AGC_CONTROL_CAL 0x00000001 /* do internal calibration */ +#define AR_PHY_AGC_CONTROL_NF 0x00000002 /* do noise-floor calibration */ +#define AR_PHY_AGC_CONTROL_OFFSET_CAL 0x00000800 /* allow offset calibration */ +#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 /* enable noise floor calibration to happen */ +#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 /* allow tx filter calibration */ +#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 /* don't update noise floor automatically */ +#define AR_PHY_AGC_CONTROL_EXT_NF_PWR_MEAS 0x00040000 /* extend noise floor power measurement */ +#define AR_PHY_AGC_CONTROL_CLC_SUCCESS 0x00080000 /* carrier leak calibration done */ + +#define AR_PHY_AGC_CONTROL_YCOK_MAX 0x000003c0 +#define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6 + +#define AR_PHY_CALMODE_IQ 0x00000000 +#define AR_PHY_CALMODE_ADC_GAIN 0x00000001 +#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002 +#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003 +#define AR_PHY_SWAP_ALT_CHAIN 0x00000040 +#define AR_PHY_MODE_OFDM 0x00000000 +#define AR_PHY_MODE_CCK 0x00000001 +#define AR_PHY_MODE_DYNAMIC 0x00000004 +#define AR_PHY_MODE_HALF 0x00000020 +#define AR_PHY_MODE_QUARTER 0x00000040 +#define AR_PHY_MAC_CLK_MODE 0x00000080 +#define AR_PHY_MODE_DYN_CCK_DISABLE 0x00000100 +#define AR_PHY_MODE_SVD_HALF 0x00000200 +#define AR_PHY_ACTIVE_EN 0x00000001 +#define AR_PHY_ACTIVE_DIS 0x00000000 +#define AR_PHY_FORCE_XPA_CFG 0x000000001 +#define AR_PHY_FORCE_XPA_CFG_S 0 +#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF 0xFF000000 +#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF_S 24 +#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF 0x00FF0000 +#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF_S 16 +#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON 0x0000FF00 +#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON_S 8 +#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON 0x000000FF +#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON_S 0 +#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000 +#define AR_PHY_TX_END_TO_A2_RX_ON_S 16 +#define AR_PHY_TX_END_DATA_START 0x000000FF +#define AR_PHY_TX_END_DATA_START_S 0 +#define AR_PHY_TX_END_PA_ON 0x0000FF00 +#define AR_PHY_TX_END_PA_ON_S 8 +#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F +#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22 +#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000 +#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14 +#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000 +#define AR_PHY_TPCRG1_PD_GAIN_1_S 16 +#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000 +#define AR_PHY_TPCRG1_PD_GAIN_2_S 18 +#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 +#define AR_PHY_TPCRG1_PD_GAIN_3_S 20 +#define AR_PHY_TPCGR1_FORCED_DAC_GAIN 0x0000003e +#define AR_PHY_TPCGR1_FORCED_DAC_GAIN_S 1 +#define AR_PHY_TPCGR1_FORCE_DAC_GAIN 0x00000001 +#define AR_PHY_TXGAIN_FORCE 0x00000001 +#define AR_PHY_TXGAIN_FORCED_PADVGNRA 0x00003c00 +#define AR_PHY_TXGAIN_FORCED_PADVGNRA_S 10 +#define AR_PHY_TXGAIN_FORCED_PADVGNRB 0x0003c000 +#define AR_PHY_TXGAIN_FORCED_PADVGNRB_S 14 +#define AR_PHY_TXGAIN_FORCED_PADVGNRD 0x00c00000 +#define AR_PHY_TXGAIN_FORCED_PADVGNRD_S 22 +#define AR_PHY_TXGAIN_FORCED_TXMXRGAIN 0x000003c0 +#define AR_PHY_TXGAIN_FORCED_TXMXRGAIN_S 6 +#define AR_PHY_TXGAIN_FORCED_TXBB1DBGAIN 0x0000000e +#define AR_PHY_TXGAIN_FORCED_TXBB1DBGAIN_S 1 + +#define AR_PHY_POWER_TX_RATE1 0x9934 +#define AR_PHY_POWER_TX_RATE2 0x9938 +#define AR_PHY_POWER_TX_RATE_MAX 0x993c +#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040 +#define PHY_AGC_CLR 0x10000000 +#define RFSILENT_BB 0x00002000 +#define AR_PHY_CHAN_INFO_GAIN_DIFF_PPM_MASK 0xFFF +#define AR_PHY_CHAN_INFO_GAIN_DIFF_PPM_SIGNED_BIT 0x800 +#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 +#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001 +#define AR_PHY_RX_DELAY_DELAY 0x00003FFF +#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 +#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x00000001 +#define AR_PHY_SPECTRAL_SCAN_ENABLE_S 0 +#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 +#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 +#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 +#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4 +#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 +#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8 +#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 +#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16 +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 +#define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004 +#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 +#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18 +#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001 +#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0 + +#define AR_PHY_TX_IQCAL_STATUS_FAILED 0x00000001 +#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE 0x00003fff +#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S 0 + +#define AR_PHY_TPC_18_THERM_CAL_VALUE 0xff +#define AR_PHY_TPC_18_THERM_CAL_VALUE_S 0 +#define AR_PHY_TPC_19_ALPHA_THERM 0xff +#define AR_PHY_TPC_19_ALPHA_THERM_S 0 + +#define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000 +#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28 + +#define AR_PHY_BB_THERM_ADC_1_INIT_THERM 0x000000ff +#define AR_PHY_BB_THERM_ADC_1_INIT_THERM_S 0 + +/* + * Channel 1 Register Map + */ +#define AR_CHAN1_BASE 0xa800 + +#define AR_PHY_EXT_CCA_1 (AR_CHAN1_BASE + 0x30) +#define AR_PHY_TX_PHASE_RAMP_1 (AR_CHAN1_BASE + 0xd0) +#define AR_PHY_ADC_GAIN_DC_CORR_1 (AR_CHAN1_BASE + 0xd4) + +#define AR_PHY_SPUR_REPORT_1 (AR_CHAN1_BASE + 0xa8) +#define AR_PHY_CHAN_INFO_TAB_1 (AR_CHAN1_BASE + 0x300) +#define AR_PHY_RX_IQCAL_CORR_B1 (AR_CHAN1_BASE + 0xdc) + +/* + * Channel 1 Field Definitions + */ +#define AR_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000 +#define AR_PHY_CH1_EXT_MINCCA_PWR_S 16 + +/* + * AGC 1 Register Map + */ +#define AR_AGC1_BASE 0xae00 + +#define AR_PHY_FORCEMAX_GAINS_1 (AR_AGC1_BASE + 0x4) +#define AR_PHY_EXT_ATTEN_CTL_1 (AR_AGC1_BASE + 0x18) +#define AR_PHY_CCA_1 (AR_AGC1_BASE + 0x1c) +#define AR_PHY_CCA_CTRL_1 (AR_AGC1_BASE + 0x20) +#define AR_PHY_RSSI_1 (AR_AGC1_BASE + 0x180) +#define AR_PHY_SPUR_CCK_REP_1 (AR_AGC1_BASE + 0x184) +#define AR_PHY_RX_OCGAIN_2 (AR_AGC1_BASE + 0x200) + +/* + * AGC 1 Field Definitions + */ +#define AR_PHY_CH1_MINCCA_PWR 0x1FF00000 +#define AR_PHY_CH1_MINCCA_PWR_S 20 + +/* + * SM 1 Register Map + */ +#define AR_SM1_BASE 0xb200 + +#define AR_PHY_SWITCH_CHAIN_1 (AR_SM1_BASE + 0x84) +#define AR_PHY_FCAL_2_1 (AR_SM1_BASE + 0xd0) +#define AR_PHY_DFT_TONE_CTL_1 (AR_SM1_BASE + 0xd4) +#define AR_PHY_CL_TAB_1 (AR_SM1_BASE + 0x100) +#define AR_PHY_CHAN_INFO_GAIN_1 (AR_SM1_BASE + 0x180) +#define AR_PHY_TPC_4_B1 (AR_SM1_BASE + 0x204) +#define AR_PHY_TPC_5_B1 (AR_SM1_BASE + 0x208) +#define AR_PHY_TPC_6_B1 (AR_SM1_BASE + 0x20c) +#define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220) +#define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + 0x240) +#define AR_PHY_TX_IQCAL_STATUS_B1 (AR_SM1_BASE + 0x48c) +#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B1 (AR_SM1_BASE + 0x450) + +/* + * Channel 2 Register Map + */ +#define AR_CHAN2_BASE 0xb800 + +#define AR_PHY_EXT_CCA_2 (AR_CHAN2_BASE + 0x30) +#define AR_PHY_TX_PHASE_RAMP_2 (AR_CHAN2_BASE + 0xd0) +#define AR_PHY_ADC_GAIN_DC_CORR_2 (AR_CHAN2_BASE + 0xd4) + +#define AR_PHY_SPUR_REPORT_2 (AR_CHAN2_BASE + 0xa8) +#define AR_PHY_CHAN_INFO_TAB_2 (AR_CHAN2_BASE + 0x300) +#define AR_PHY_RX_IQCAL_CORR_B2 (AR_CHAN2_BASE + 0xdc) + +/* + * Channel 2 Field Definitions + */ +#define AR_PHY_CH2_EXT_MINCCA_PWR 0x01FF0000 +#define AR_PHY_CH2_EXT_MINCCA_PWR_S 16 +/* + * AGC 2 Register Map + */ +#define AR_AGC2_BASE 0xbe00 + +#define AR_PHY_FORCEMAX_GAINS_2 (AR_AGC2_BASE + 0x4) +#define AR_PHY_EXT_ATTEN_CTL_2 (AR_AGC2_BASE + 0x18) +#define AR_PHY_CCA_2 (AR_AGC2_BASE + 0x1c) +#define AR_PHY_CCA_CTRL_2 (AR_AGC2_BASE + 0x20) +#define AR_PHY_RSSI_2 (AR_AGC2_BASE + 0x180) + +/* + * AGC 2 Field Definitions + */ +#define AR_PHY_CH2_MINCCA_PWR 0x1FF00000 +#define AR_PHY_CH2_MINCCA_PWR_S 20 + +/* + * SM 2 Register Map + */ +#define AR_SM2_BASE 0xc200 + +#define AR_PHY_SWITCH_CHAIN_2 (AR_SM2_BASE + 0x84) +#define AR_PHY_FCAL_2_2 (AR_SM2_BASE + 0xd0) +#define AR_PHY_DFT_TONE_CTL_2 (AR_SM2_BASE + 0xd4) +#define AR_PHY_CL_TAB_2 (AR_SM2_BASE + 0x100) +#define AR_PHY_CHAN_INFO_GAIN_2 (AR_SM2_BASE + 0x180) +#define AR_PHY_TPC_4_B2 (AR_SM2_BASE + 0x204) +#define AR_PHY_TPC_5_B2 (AR_SM2_BASE + 0x208) +#define AR_PHY_TPC_6_B2 (AR_SM2_BASE + 0x20c) +#define AR_PHY_TPC_11_B2 (AR_SM2_BASE + 0x220) +#define AR_PHY_PDADC_TAB_2 (AR_SM2_BASE + 0x240) +#define AR_PHY_TX_IQCAL_STATUS_B2 (AR_SM2_BASE + 0x48c) +#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B2 (AR_SM2_BASE + 0x450) + +#define AR_PHY_TX_IQCAL_STATUS_B2_FAILED 0x00000001 + +/* + * AGC 3 Register Map + */ +#define AR_AGC3_BASE 0xce00 + +#define AR_PHY_RSSI_3 (AR_AGC3_BASE + 0x180) + +/* + * Misc helper defines + */ +#define AR_PHY_CHAIN_OFFSET (AR_CHAN1_BASE - AR_CHAN_BASE) + +#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (AR_PHY_ADC_GAIN_DC_CORR_0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_NEW_ADC_DC_GAIN_CORR_9300_10(_i) (AR_PHY_ADC_GAIN_DC_CORR_0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_SWITCH_CHAIN(_i) (AR_PHY_SWITCH_CHAIN_0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_EXT_ATTEN_CTL(_i) (AR_PHY_EXT_ATTEN_CTL_0 + (AR_PHY_CHAIN_OFFSET * (_i))) + +#define AR_PHY_RXGAIN(_i) (AR_PHY_FORCEMAX_GAINS_0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_TPCRG5(_i) (AR_PHY_TPC_5_B0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_PDADC_TAB(_i) (AR_PHY_PDADC_TAB_0 + (AR_PHY_CHAIN_OFFSET * (_i))) + +#define AR_PHY_CAL_MEAS_0(_i) (AR_PHY_IQ_ADC_MEAS_0_B0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_CAL_MEAS_1(_i) (AR_PHY_IQ_ADC_MEAS_1_B0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_CAL_MEAS_2(_i) (AR_PHY_IQ_ADC_MEAS_2_B0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_CAL_MEAS_3(_i) (AR_PHY_IQ_ADC_MEAS_3_B0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_CAL_MEAS_0_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_0_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_CAL_MEAS_1_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_1_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_CAL_MEAS_2_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_2_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_CAL_MEAS_3_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_3_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) + +#define AR_PHY_BB_PANIC_NON_IDLE_ENABLE 0x00000001 +#define AR_PHY_BB_PANIC_IDLE_ENABLE 0x00000002 +#define AR_PHY_BB_PANIC_IDLE_MASK 0xFFFF0000 +#define AR_PHY_BB_PANIC_NON_IDLE_MASK 0x0000FFFC + +#define AR_PHY_BB_PANIC_RST_ENABLE 0x00000002 +#define AR_PHY_BB_PANIC_IRQ_ENABLE 0x00000004 +#define AR_PHY_BB_PANIC_CNTL2_MASK 0xFFFFFFF9 + +#define AR_PHY_BB_WD_STATUS 0x00000007 +#define AR_PHY_BB_WD_STATUS_S 0 +#define AR_PHY_BB_WD_DET_HANG 0x00000008 +#define AR_PHY_BB_WD_DET_HANG_S 3 +#define AR_PHY_BB_WD_RADAR_SM 0x000000F0 +#define AR_PHY_BB_WD_RADAR_SM_S 4 +#define AR_PHY_BB_WD_RX_OFDM_SM 0x00000F00 +#define AR_PHY_BB_WD_RX_OFDM_SM_S 8 +#define AR_PHY_BB_WD_RX_CCK_SM 0x0000F000 +#define AR_PHY_BB_WD_RX_CCK_SM_S 12 +#define AR_PHY_BB_WD_TX_OFDM_SM 0x000F0000 +#define AR_PHY_BB_WD_TX_OFDM_SM_S 16 +#define AR_PHY_BB_WD_TX_CCK_SM 0x00F00000 +#define AR_PHY_BB_WD_TX_CCK_SM_S 20 +#define AR_PHY_BB_WD_AGC_SM 0x0F000000 +#define AR_PHY_BB_WD_AGC_SM_S 24 +#define AR_PHY_BB_WD_SRCH_SM 0xF0000000 +#define AR_PHY_BB_WD_SRCH_SM_S 28 + +#define AR_PHY_BB_WD_STATUS_CLR 0x00000008 + +#endif /* AR9003_PHY_H */ -- cgit v1.2.3 From 7152451aa12558ab032f319a119ceb928396b905 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:32 -0400 Subject: ath9k_hw: add common channel select helpers for ar900[23] Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_phy.c | 4 ++-- drivers/net/wireless/ath/ath9k/phy.h | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 87541a8440c0..1f8ac0ae471a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -83,7 +83,7 @@ static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) bMode = 1; fracMode = 1; aModeRefSel = 0; - channelSel = (freq * 0x10000) / 15; + channelSel = CHANSEL_2G(freq); if (AR_SREV_9287_11_OR_LATER(ah)) { if (freq == 2484) { @@ -126,7 +126,7 @@ static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) */ fracMode = 1; refDivA = 1; - channelSel = (freq * 0x8000) / 15; + channelSel = CHANSEL_5G(freq); /* RefDivA setting */ REG_RMW_FIELD(ah, AR_AN_SYNTH9, diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index b90815205a14..7d397fd7bd18 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -17,6 +17,10 @@ #ifndef PHY_H #define PHY_H +#define CHANSEL_DIV 15 +#define CHANSEL_2G(_freq) (((_freq) * 0x10000) / CHANSEL_DIV) +#define CHANSEL_5G(_freq) (((_freq) * 0x8000) / CHANSEL_DIV) + #define AR_PHY_BASE 0x9800 #define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) -- cgit v1.2.3 From f7abf0c1958ab363874cad0d799a1bb43880145a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Apr 2010 17:38:33 -0400 Subject: ath9k_hw: Set the channel on AR9003 Signed-off-by: Felix Fietkau Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 47 ++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 084b0f92afde..f1632abdce50 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -44,7 +44,52 @@ */ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) { - /* TODO */ + u16 bMode, fracMode = 0, aModeRefSel = 0; + u32 freq, channelSel = 0, reg32 = 0; + struct chan_centers centers; + int loadSynthChannel; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + freq = centers.synth_center; + + if (freq < 4800) { /* 2 GHz, fractional mode */ + channelSel = CHANSEL_2G(freq); + /* Set to 2G mode */ + bMode = 1; + } else { + channelSel = CHANSEL_5G(freq); + /* Doubler is ON, so, divide channelSel by 2. */ + channelSel >>= 1; + /* Set to 5G mode */ + bMode = 0; + } + + /* Enable fractional mode for all channels */ + fracMode = 1; + aModeRefSel = 0; + loadSynthChannel = 0; + + reg32 = (bMode << 29); + REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); + + /* Enable Long shift Select for Synthesizer */ + REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_SYNTH4, + AR_PHY_SYNTH4_LONG_SHIFT_SELECT, 1); + + /* Program Synth. setting */ + reg32 = (channelSel << 2) | (fracMode << 30) | + (aModeRefSel << 28) | (loadSynthChannel << 31); + REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); + + /* Toggle Load Synth channel bit */ + loadSynthChannel = 1; + reg32 = (channelSel << 2) | (fracMode << 30) | + (aModeRefSel << 28) | (loadSynthChannel << 31); + REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); + + ah->curchan = chan; + ah->curchan_rad_index = -1; + return 0; } -- cgit v1.2.3 From 317d33280c63f32bd84c49aacaaae047e981b441 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Apr 2010 17:38:34 -0400 Subject: ath9k_hw: Implement PLL control on AR9003 Signed-off-by: Felix Fietkau Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 23 +++++++++++++++++++++-- drivers/net/wireless/ath/ath9k/reg.h | 6 ++++++ 2 files changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index f1632abdce50..9767265cde02 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -112,8 +112,27 @@ static void ar9003_hw_spur_mitigate(struct ath_hw *ah, static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah, struct ath9k_channel *chan) { - /* TODO */ - return 0; + u32 pll; + + pll = SM(0x5, AR_RTC_9300_PLL_REFDIV); + + if (chan && IS_CHAN_HALF_RATE(chan)) + pll |= SM(0x1, AR_RTC_9300_PLL_CLKSEL); + else if (chan && IS_CHAN_QUARTER_RATE(chan)) + pll |= SM(0x2, AR_RTC_9300_PLL_CLKSEL); + + if (chan && IS_CHAN_5GHZ(chan)) { + pll |= SM(0x28, AR_RTC_9300_PLL_DIV); + + /* + * When doing fast clock, set PLL to 0x142c + */ + if (IS_CHAN_A_5MHZ_SPACED(chan)) + pll = 0x142c; + } else + pll |= SM(0x2c, AR_RTC_9300_PLL_DIV); + + return pll; } static void ar9003_hw_set_channel_regs(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index bc48bc92076f..9d632861aaff 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1040,6 +1040,12 @@ enum { #define AR_PCIE_MSI (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094) #define AR_PCIE_MSI_ENABLE 0x00000001 +#define AR_RTC_9300_PLL_DIV 0x000003ff +#define AR_RTC_9300_PLL_DIV_S 0 +#define AR_RTC_9300_PLL_REFDIV 0x00003C00 +#define AR_RTC_9300_PLL_REFDIV_S 10 +#define AR_RTC_9300_PLL_CLKSEL 0x0000C000 +#define AR_RTC_9300_PLL_CLKSEL_S 14 #define AR_RTC_9160_PLL_DIV 0x000003ff #define AR_RTC_9160_PLL_DIV_S 0 -- cgit v1.2.3 From ca3755540707539ea3ccf45e0c777d946f768f62 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Apr 2010 17:38:35 -0400 Subject: ath9k_hw: Implement spur mitigation on AR9003 Signed-off-by: Felix Fietkau Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 50 ++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 9767265cde02..3e3472e493a4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -106,7 +106,55 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) static void ar9003_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) { - /* TODO */ + u32 spur_freq[4] = { 2420, 2440, 2464, 2480 }; + int cur_bb_spur, negative = 0, cck_spur_freq; + int i; + + /* + * Need to verify range +/- 10 MHz in control channel, otherwise spur + * is out-of-band and can be ignored. + */ + + for (i = 0; i < 4; i++) { + negative = 0; + cur_bb_spur = spur_freq[i] - chan->channel; + + if (cur_bb_spur < 0) { + negative = 1; + cur_bb_spur = -cur_bb_spur; + } + if (cur_bb_spur < 10) { + cck_spur_freq = (int)((cur_bb_spur << 19) / 11); + + if (negative == 1) + cck_spur_freq = -cck_spur_freq; + + cck_spur_freq = cck_spur_freq & 0xfffff; + + REG_RMW_FIELD(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_YCOK_MAX, 0x7); + REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, + AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR, 0x7f); + REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, + AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE, + 0x2); + REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, + AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT, + 0x1); + REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, + AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, + cck_spur_freq); + + return; + } + } + + REG_RMW_FIELD(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_YCOK_MAX, 0x5); + REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, + AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT, 0x0); + REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, + AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, 0x0); } static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah, -- cgit v1.2.3 From af01c04e21816da01454e1d580891f394465b77e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:36 -0400 Subject: ath9k_hw: split initvals.h by hardware family The initvals.h file is over 7000 lines now, so instead of adding AR9003 initvals to it instead lets split the current initvals.h by hardware family: AR5008, AR9001, AR9002 The AR9003 family will have its own initval file later. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar5008_initvals.h | 742 +++ drivers/net/wireless/ath/ath9k/ar9001_initvals.h | 1254 ++++ drivers/net/wireless/ath/ath9k/ar9002_initvals.h | 5230 ++++++++++++++++ drivers/net/wireless/ath/ath9k/hw.c | 4 +- drivers/net/wireless/ath/ath9k/initvals.h | 7200 ---------------------- 5 files changed, 7229 insertions(+), 7201 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/ar5008_initvals.h create mode 100644 drivers/net/wireless/ath/ath9k/ar9001_initvals.h create mode 100644 drivers/net/wireless/ath/ath9k/ar9002_initvals.h delete mode 100644 drivers/net/wireless/ath/ath9k/initvals.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h new file mode 100644 index 000000000000..cd953f6c4628 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h @@ -0,0 +1,742 @@ +/* + * Copyright (c) 2008-2009 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef INITVALS_AR5008_H +#define INITVALS_AR5008_H + +static const u32 ar5416Modes[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, + { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, + { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, + { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, + { 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e }, + { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 }, + { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 }, + { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b }, + { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, + { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, + { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, + { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, + { 0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, + { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, + { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, + { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, + { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, + { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, + { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, + { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, + { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, + { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, + { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, + { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, + { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, + { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, + { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const u32 ar5416Common[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00007010, 0x00000000 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008264, 0xa8000010 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00070000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xad848e19 }, + { 0x00009810, 0x7d14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a002e }, + { 0x0000984c, 0x1284233c }, + { 0x00009854, 0x00000859 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x05100000 }, + { 0x0000a920, 0x05100000 }, + { 0x0000b920, 0x05100000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280b212 }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5d50e188 }, + { 0x00009958, 0x00081fff }, + { 0x0000c95c, 0x004b6a8e }, + { 0x0000c968, 0x000003ce }, + { 0x00009970, 0x190fb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x001fff00 }, + { 0x000099ac, 0x00000000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000200 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x000000aa }, + { 0x000099fc, 0x00001042 }, + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b28, 0x0000000c }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b38, 0x00000012 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009b9c, 0x00000033 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, + { 0x0000a210, 0x40806333 }, + { 0x0000a214, 0x00106c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x018830c6 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x00000bb5 }, + { 0x0000a22c, 0x00000011 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0e79e5c6 }, + { 0x0000b26c, 0x0e79e5c6 }, + { 0x0000c26c, 0x0e79e5c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x051701ce }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa1f }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x08000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, +}; + +static const u32 ar5416Bank0[][2] = { + { 0x000098b0, 0x1e5795e5 }, + { 0x000098e0, 0x02008020 }, +}; + +static const u32 ar5416BB_RfGain[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000040, 0x00000040 }, + { 0x00009a08, 0x00000080, 0x00000080 }, + { 0x00009a0c, 0x000001a1, 0x00000141 }, + { 0x00009a10, 0x000001e1, 0x00000181 }, + { 0x00009a14, 0x00000021, 0x000001c1 }, + { 0x00009a18, 0x00000061, 0x00000001 }, + { 0x00009a1c, 0x00000168, 0x00000041 }, + { 0x00009a20, 0x000001a8, 0x000001a8 }, + { 0x00009a24, 0x000001e8, 0x000001e8 }, + { 0x00009a28, 0x00000028, 0x00000028 }, + { 0x00009a2c, 0x00000068, 0x00000068 }, + { 0x00009a30, 0x00000189, 0x000000a8 }, + { 0x00009a34, 0x000001c9, 0x00000169 }, + { 0x00009a38, 0x00000009, 0x000001a9 }, + { 0x00009a3c, 0x00000049, 0x000001e9 }, + { 0x00009a40, 0x00000089, 0x00000029 }, + { 0x00009a44, 0x00000170, 0x00000069 }, + { 0x00009a48, 0x000001b0, 0x00000190 }, + { 0x00009a4c, 0x000001f0, 0x000001d0 }, + { 0x00009a50, 0x00000030, 0x00000010 }, + { 0x00009a54, 0x00000070, 0x00000050 }, + { 0x00009a58, 0x00000191, 0x00000090 }, + { 0x00009a5c, 0x000001d1, 0x00000151 }, + { 0x00009a60, 0x00000011, 0x00000191 }, + { 0x00009a64, 0x00000051, 0x000001d1 }, + { 0x00009a68, 0x00000091, 0x00000011 }, + { 0x00009a6c, 0x000001b8, 0x00000051 }, + { 0x00009a70, 0x000001f8, 0x00000198 }, + { 0x00009a74, 0x00000038, 0x000001d8 }, + { 0x00009a78, 0x00000078, 0x00000018 }, + { 0x00009a7c, 0x00000199, 0x00000058 }, + { 0x00009a80, 0x000001d9, 0x00000098 }, + { 0x00009a84, 0x00000019, 0x00000159 }, + { 0x00009a88, 0x00000059, 0x00000199 }, + { 0x00009a8c, 0x00000099, 0x000001d9 }, + { 0x00009a90, 0x000000d9, 0x00000019 }, + { 0x00009a94, 0x000000f9, 0x00000059 }, + { 0x00009a98, 0x000000f9, 0x00000099 }, + { 0x00009a9c, 0x000000f9, 0x000000d9 }, + { 0x00009aa0, 0x000000f9, 0x000000f9 }, + { 0x00009aa4, 0x000000f9, 0x000000f9 }, + { 0x00009aa8, 0x000000f9, 0x000000f9 }, + { 0x00009aac, 0x000000f9, 0x000000f9 }, + { 0x00009ab0, 0x000000f9, 0x000000f9 }, + { 0x00009ab4, 0x000000f9, 0x000000f9 }, + { 0x00009ab8, 0x000000f9, 0x000000f9 }, + { 0x00009abc, 0x000000f9, 0x000000f9 }, + { 0x00009ac0, 0x000000f9, 0x000000f9 }, + { 0x00009ac4, 0x000000f9, 0x000000f9 }, + { 0x00009ac8, 0x000000f9, 0x000000f9 }, + { 0x00009acc, 0x000000f9, 0x000000f9 }, + { 0x00009ad0, 0x000000f9, 0x000000f9 }, + { 0x00009ad4, 0x000000f9, 0x000000f9 }, + { 0x00009ad8, 0x000000f9, 0x000000f9 }, + { 0x00009adc, 0x000000f9, 0x000000f9 }, + { 0x00009ae0, 0x000000f9, 0x000000f9 }, + { 0x00009ae4, 0x000000f9, 0x000000f9 }, + { 0x00009ae8, 0x000000f9, 0x000000f9 }, + { 0x00009aec, 0x000000f9, 0x000000f9 }, + { 0x00009af0, 0x000000f9, 0x000000f9 }, + { 0x00009af4, 0x000000f9, 0x000000f9 }, + { 0x00009af8, 0x000000f9, 0x000000f9 }, + { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const u32 ar5416Bank1[][2] = { + { 0x000098b0, 0x02108421 }, + { 0x000098ec, 0x00000008 }, +}; + +static const u32 ar5416Bank2[][2] = { + { 0x000098b0, 0x0e73ff17 }, + { 0x000098e0, 0x00000420 }, +}; + +static const u32 ar5416Bank3[][3] = { + { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +static const u32 ar5416Bank6[][3] = { + + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x004210a2, 0x004210a2 }, + { 0x0000989c, 0x0014008f, 0x0014008f }, + { 0x0000989c, 0x00c40003, 0x00c40003 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000f1, 0x000000f1 }, + { 0x0000989c, 0x00002081, 0x00002081 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank6TPC[][3] = { + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x00423022, 0x00423022 }, + { 0x0000989c, 0x201400df, 0x201400df }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000e1, 0x000000e1 }, + { 0x0000989c, 0x00007081, 0x00007081 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank7[][2] = { + { 0x0000989c, 0x00000500 }, + { 0x0000989c, 0x00000800 }, + { 0x000098cc, 0x0000000e }, +}; + +static const u32 ar5416Addac[][2] = { + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000003 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x0000000c }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000030 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000060 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000058 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x000098cc, 0x00000000 }, +}; + +static const u32 ar5416Modes_9100[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, + { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec86d2e, 0x7ec84d2e, 0x7ec82d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, + { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, + { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a11, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009940, 0x00754604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204 }, + { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, + { 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e }, + { 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff }, +#ifdef TB243 + { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, + { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, + { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 }, +#else + { 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, + { 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, + { 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, + { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, +#endif + { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00 }, + { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, + { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, + { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, + { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, + { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, + { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, + { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, + { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, + { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, + { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, + { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, + { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, + { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, + { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +#endif /* INITVALS_AR5008_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h new file mode 100644 index 000000000000..20abffeeb4b7 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h @@ -0,0 +1,1254 @@ + +static const u32 ar5416Common_9100[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00020010, 0x00000003 }, + { 0x00020038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00004000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0x00000000 }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00000000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xad848e19 }, + { 0x00009810, 0x7d14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a01ae }, + { 0x0000984c, 0x1284233c }, + { 0x00009854, 0x00000859 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x05100000 }, + { 0x0000a920, 0x05100000 }, + { 0x0000b920, 0x05100000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280b212 }, + { 0x0000994c, 0x00020028 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x0000c968, 0x000003ce }, + { 0x00009970, 0x190fb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x006f0000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000200 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099fc, 0x00001042 }, + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b28, 0x0000000c }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b38, 0x00000012 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009b9c, 0x00000033 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, + { 0x0000a210, 0x40806333 }, + { 0x0000a214, 0x00106c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x018830c6 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x001a0bb5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889ae }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000001 }, + { 0x0000a26c, 0x0ebae9c6 }, + { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000c26c, 0x0ebae9c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa33 }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, +}; + +static const u32 ar5416Bank0_9100[][2] = { + { 0x000098b0, 0x1e5795e5 }, + { 0x000098e0, 0x02008020 }, +}; + +static const u32 ar5416BB_RfGain_9100[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000040, 0x00000040 }, + { 0x00009a08, 0x00000080, 0x00000080 }, + { 0x00009a0c, 0x000001a1, 0x00000141 }, + { 0x00009a10, 0x000001e1, 0x00000181 }, + { 0x00009a14, 0x00000021, 0x000001c1 }, + { 0x00009a18, 0x00000061, 0x00000001 }, + { 0x00009a1c, 0x00000168, 0x00000041 }, + { 0x00009a20, 0x000001a8, 0x000001a8 }, + { 0x00009a24, 0x000001e8, 0x000001e8 }, + { 0x00009a28, 0x00000028, 0x00000028 }, + { 0x00009a2c, 0x00000068, 0x00000068 }, + { 0x00009a30, 0x00000189, 0x000000a8 }, + { 0x00009a34, 0x000001c9, 0x00000169 }, + { 0x00009a38, 0x00000009, 0x000001a9 }, + { 0x00009a3c, 0x00000049, 0x000001e9 }, + { 0x00009a40, 0x00000089, 0x00000029 }, + { 0x00009a44, 0x00000170, 0x00000069 }, + { 0x00009a48, 0x000001b0, 0x00000190 }, + { 0x00009a4c, 0x000001f0, 0x000001d0 }, + { 0x00009a50, 0x00000030, 0x00000010 }, + { 0x00009a54, 0x00000070, 0x00000050 }, + { 0x00009a58, 0x00000191, 0x00000090 }, + { 0x00009a5c, 0x000001d1, 0x00000151 }, + { 0x00009a60, 0x00000011, 0x00000191 }, + { 0x00009a64, 0x00000051, 0x000001d1 }, + { 0x00009a68, 0x00000091, 0x00000011 }, + { 0x00009a6c, 0x000001b8, 0x00000051 }, + { 0x00009a70, 0x000001f8, 0x00000198 }, + { 0x00009a74, 0x00000038, 0x000001d8 }, + { 0x00009a78, 0x00000078, 0x00000018 }, + { 0x00009a7c, 0x00000199, 0x00000058 }, + { 0x00009a80, 0x000001d9, 0x00000098 }, + { 0x00009a84, 0x00000019, 0x00000159 }, + { 0x00009a88, 0x00000059, 0x00000199 }, + { 0x00009a8c, 0x00000099, 0x000001d9 }, + { 0x00009a90, 0x000000d9, 0x00000019 }, + { 0x00009a94, 0x000000f9, 0x00000059 }, + { 0x00009a98, 0x000000f9, 0x00000099 }, + { 0x00009a9c, 0x000000f9, 0x000000d9 }, + { 0x00009aa0, 0x000000f9, 0x000000f9 }, + { 0x00009aa4, 0x000000f9, 0x000000f9 }, + { 0x00009aa8, 0x000000f9, 0x000000f9 }, + { 0x00009aac, 0x000000f9, 0x000000f9 }, + { 0x00009ab0, 0x000000f9, 0x000000f9 }, + { 0x00009ab4, 0x000000f9, 0x000000f9 }, + { 0x00009ab8, 0x000000f9, 0x000000f9 }, + { 0x00009abc, 0x000000f9, 0x000000f9 }, + { 0x00009ac0, 0x000000f9, 0x000000f9 }, + { 0x00009ac4, 0x000000f9, 0x000000f9 }, + { 0x00009ac8, 0x000000f9, 0x000000f9 }, + { 0x00009acc, 0x000000f9, 0x000000f9 }, + { 0x00009ad0, 0x000000f9, 0x000000f9 }, + { 0x00009ad4, 0x000000f9, 0x000000f9 }, + { 0x00009ad8, 0x000000f9, 0x000000f9 }, + { 0x00009adc, 0x000000f9, 0x000000f9 }, + { 0x00009ae0, 0x000000f9, 0x000000f9 }, + { 0x00009ae4, 0x000000f9, 0x000000f9 }, + { 0x00009ae8, 0x000000f9, 0x000000f9 }, + { 0x00009aec, 0x000000f9, 0x000000f9 }, + { 0x00009af0, 0x000000f9, 0x000000f9 }, + { 0x00009af4, 0x000000f9, 0x000000f9 }, + { 0x00009af8, 0x000000f9, 0x000000f9 }, + { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const u32 ar5416Bank1_9100[][2] = { + { 0x000098b0, 0x02108421}, + { 0x000098ec, 0x00000008}, +}; + +static const u32 ar5416Bank2_9100[][2] = { + { 0x000098b0, 0x0e73ff17}, + { 0x000098e0, 0x00000420}, +}; + +static const u32 ar5416Bank3_9100[][3] = { + { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +static const u32 ar5416Bank6_9100[][3] = { + + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x004210a2, 0x004210a2 }, + { 0x0000989c, 0x0014000f, 0x0014000f }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x000180d6, 0x000180d6 }, + { 0x0000989c, 0x0000c0aa, 0x0000c0aa }, + { 0x0000989c, 0x000000b1, 0x000000b1 }, + { 0x0000989c, 0x00002000, 0x00002000 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + + +static const u32 ar5416Bank6TPC_9100[][3] = { + + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x00423022, 0x00423022 }, + { 0x0000989c, 0x2014008f, 0x2014008f }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000e1, 0x000000e1 }, + { 0x0000989c, 0x00007080, 0x00007080 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank7_9100[][2] = { + { 0x0000989c, 0x00000500 }, + { 0x0000989c, 0x00000800 }, + { 0x000098cc, 0x0000000e }, +}; + +static const u32 ar5416Addac_9100[][2] = { + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000010 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000015 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x000098cc, 0x00000000 }, +}; + +static const u32 ar5416Modes_9160[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, + { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, + { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, + { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, + { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, + { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, + { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, + { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, + { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, + { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, + { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, + { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, + { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, + { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, + { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, + { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, + { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, + { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, + { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, + { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, + { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, + { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, + { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, + { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, + { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const u32 ar5416Common_9160[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00007010, 0x00000020 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00ff0000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xad848e19 }, + { 0x00009810, 0x7d14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a01ae }, + { 0x0000984c, 0x1284233c }, + { 0x00009854, 0x00000859 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x05100000 }, + { 0x0000a920, 0x05100000 }, + { 0x0000b920, 0x05100000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280b212 }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x2108ecff }, + { 0x00009940, 0x00750604 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x00009970, 0x190fb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x006f0000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000200 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099fc, 0x00001042 }, + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b28, 0x0000000c }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b38, 0x00000012 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009b9c, 0x00000033 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, + { 0x0000a210, 0x40806333 }, + { 0x0000a214, 0x00106c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x018830c6 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x001a0bb5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000e000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000001 }, + { 0x0000a26c, 0x0ebae9c6 }, + { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000c26c, 0x0ebae9c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79bfaa03 }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, +}; + +static const u32 ar5416Bank0_9160[][2] = { + { 0x000098b0, 0x1e5795e5 }, + { 0x000098e0, 0x02008020 }, +}; + +static const u32 ar5416BB_RfGain_9160[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000040, 0x00000040 }, + { 0x00009a08, 0x00000080, 0x00000080 }, + { 0x00009a0c, 0x000001a1, 0x00000141 }, + { 0x00009a10, 0x000001e1, 0x00000181 }, + { 0x00009a14, 0x00000021, 0x000001c1 }, + { 0x00009a18, 0x00000061, 0x00000001 }, + { 0x00009a1c, 0x00000168, 0x00000041 }, + { 0x00009a20, 0x000001a8, 0x000001a8 }, + { 0x00009a24, 0x000001e8, 0x000001e8 }, + { 0x00009a28, 0x00000028, 0x00000028 }, + { 0x00009a2c, 0x00000068, 0x00000068 }, + { 0x00009a30, 0x00000189, 0x000000a8 }, + { 0x00009a34, 0x000001c9, 0x00000169 }, + { 0x00009a38, 0x00000009, 0x000001a9 }, + { 0x00009a3c, 0x00000049, 0x000001e9 }, + { 0x00009a40, 0x00000089, 0x00000029 }, + { 0x00009a44, 0x00000170, 0x00000069 }, + { 0x00009a48, 0x000001b0, 0x00000190 }, + { 0x00009a4c, 0x000001f0, 0x000001d0 }, + { 0x00009a50, 0x00000030, 0x00000010 }, + { 0x00009a54, 0x00000070, 0x00000050 }, + { 0x00009a58, 0x00000191, 0x00000090 }, + { 0x00009a5c, 0x000001d1, 0x00000151 }, + { 0x00009a60, 0x00000011, 0x00000191 }, + { 0x00009a64, 0x00000051, 0x000001d1 }, + { 0x00009a68, 0x00000091, 0x00000011 }, + { 0x00009a6c, 0x000001b8, 0x00000051 }, + { 0x00009a70, 0x000001f8, 0x00000198 }, + { 0x00009a74, 0x00000038, 0x000001d8 }, + { 0x00009a78, 0x00000078, 0x00000018 }, + { 0x00009a7c, 0x00000199, 0x00000058 }, + { 0x00009a80, 0x000001d9, 0x00000098 }, + { 0x00009a84, 0x00000019, 0x00000159 }, + { 0x00009a88, 0x00000059, 0x00000199 }, + { 0x00009a8c, 0x00000099, 0x000001d9 }, + { 0x00009a90, 0x000000d9, 0x00000019 }, + { 0x00009a94, 0x000000f9, 0x00000059 }, + { 0x00009a98, 0x000000f9, 0x00000099 }, + { 0x00009a9c, 0x000000f9, 0x000000d9 }, + { 0x00009aa0, 0x000000f9, 0x000000f9 }, + { 0x00009aa4, 0x000000f9, 0x000000f9 }, + { 0x00009aa8, 0x000000f9, 0x000000f9 }, + { 0x00009aac, 0x000000f9, 0x000000f9 }, + { 0x00009ab0, 0x000000f9, 0x000000f9 }, + { 0x00009ab4, 0x000000f9, 0x000000f9 }, + { 0x00009ab8, 0x000000f9, 0x000000f9 }, + { 0x00009abc, 0x000000f9, 0x000000f9 }, + { 0x00009ac0, 0x000000f9, 0x000000f9 }, + { 0x00009ac4, 0x000000f9, 0x000000f9 }, + { 0x00009ac8, 0x000000f9, 0x000000f9 }, + { 0x00009acc, 0x000000f9, 0x000000f9 }, + { 0x00009ad0, 0x000000f9, 0x000000f9 }, + { 0x00009ad4, 0x000000f9, 0x000000f9 }, + { 0x00009ad8, 0x000000f9, 0x000000f9 }, + { 0x00009adc, 0x000000f9, 0x000000f9 }, + { 0x00009ae0, 0x000000f9, 0x000000f9 }, + { 0x00009ae4, 0x000000f9, 0x000000f9 }, + { 0x00009ae8, 0x000000f9, 0x000000f9 }, + { 0x00009aec, 0x000000f9, 0x000000f9 }, + { 0x00009af0, 0x000000f9, 0x000000f9 }, + { 0x00009af4, 0x000000f9, 0x000000f9 }, + { 0x00009af8, 0x000000f9, 0x000000f9 }, + { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const u32 ar5416Bank1_9160[][2] = { + { 0x000098b0, 0x02108421 }, + { 0x000098ec, 0x00000008 }, +}; + +static const u32 ar5416Bank2_9160[][2] = { + { 0x000098b0, 0x0e73ff17 }, + { 0x000098e0, 0x00000420 }, +}; + +static const u32 ar5416Bank3_9160[][3] = { + { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +static const u32 ar5416Bank6_9160[][3] = { + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x004210a2, 0x004210a2 }, + { 0x0000989c, 0x0014008f, 0x0014008f }, + { 0x0000989c, 0x00c40003, 0x00c40003 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000f1, 0x000000f1 }, + { 0x0000989c, 0x00002081, 0x00002081 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank6TPC_9160[][3] = { + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x00423022, 0x00423022 }, + { 0x0000989c, 0x2014008f, 0x2014008f }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000e1, 0x000000e1 }, + { 0x0000989c, 0x00007080, 0x00007080 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank7_9160[][2] = { + { 0x0000989c, 0x00000500 }, + { 0x0000989c, 0x00000800 }, + { 0x000098cc, 0x0000000e }, +}; + +static u32 ar5416Addac_9160[][2] = { + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000018 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000019 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000003 }, + {0x0000989c, 0x00000008 }, + {0x0000989c, 0x00000000 }, + {0x000098cc, 0x00000000 }, +}; + +static u32 ar5416Addac_91601_1[][2] = { + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000018 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000019 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x000098cc, 0x00000000 }, +}; + diff --git a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h new file mode 100644 index 000000000000..0f74ea764e8c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h @@ -0,0 +1,5230 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef INITVALS_9002_10_H +#define INITVALS_9002_10_H + +static const u32 ar9280Modes_9280[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 }, + { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, + { 0x00009848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 }, + { 0x0000a848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 }, + { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, + { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d20, 0x00049d20, 0x00049d18 }, + { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190 }, + { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 }, + { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, + { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, + { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, + { 0x0000c9b8, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a }, + { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009a00, 0x00008184, 0x00008184, 0x00000214, 0x00000214, 0x00000214 }, + { 0x00009a04, 0x00008188, 0x00008188, 0x00000218, 0x00000218, 0x00000218 }, + { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000224, 0x00000224, 0x00000224 }, + { 0x00009a0c, 0x00008190, 0x00008190, 0x00000228, 0x00000228, 0x00000228 }, + { 0x00009a10, 0x00008194, 0x00008194, 0x0000022c, 0x0000022c, 0x0000022c }, + { 0x00009a14, 0x00008200, 0x00008200, 0x00000230, 0x00000230, 0x00000230 }, + { 0x00009a18, 0x00008204, 0x00008204, 0x000002a4, 0x000002a4, 0x000002a4 }, + { 0x00009a1c, 0x00008208, 0x00008208, 0x000002a8, 0x000002a8, 0x000002a8 }, + { 0x00009a20, 0x0000820c, 0x0000820c, 0x000002ac, 0x000002ac, 0x000002ac }, + { 0x00009a24, 0x00008210, 0x00008210, 0x000002b0, 0x000002b0, 0x000002b0 }, + { 0x00009a28, 0x00008214, 0x00008214, 0x000002b4, 0x000002b4, 0x000002b4 }, + { 0x00009a2c, 0x00008280, 0x00008280, 0x000002b8, 0x000002b8, 0x000002b8 }, + { 0x00009a30, 0x00008284, 0x00008284, 0x00000390, 0x00000390, 0x00000390 }, + { 0x00009a34, 0x00008288, 0x00008288, 0x00000394, 0x00000394, 0x00000394 }, + { 0x00009a38, 0x0000828c, 0x0000828c, 0x00000398, 0x00000398, 0x00000398 }, + { 0x00009a3c, 0x00008290, 0x00008290, 0x00000334, 0x00000334, 0x00000334 }, + { 0x00009a40, 0x00008300, 0x00008300, 0x00000338, 0x00000338, 0x00000338 }, + { 0x00009a44, 0x00008304, 0x00008304, 0x000003ac, 0x000003ac, 0x000003ac }, + { 0x00009a48, 0x00008308, 0x00008308, 0x000003b0, 0x000003b0, 0x000003b0 }, + { 0x00009a4c, 0x0000830c, 0x0000830c, 0x000003b4, 0x000003b4, 0x000003b4 }, + { 0x00009a50, 0x00008310, 0x00008310, 0x000003b8, 0x000003b8, 0x000003b8 }, + { 0x00009a54, 0x00008314, 0x00008314, 0x000003a5, 0x000003a5, 0x000003a5 }, + { 0x00009a58, 0x00008380, 0x00008380, 0x000003a9, 0x000003a9, 0x000003a9 }, + { 0x00009a5c, 0x00008384, 0x00008384, 0x000003ad, 0x000003ad, 0x000003ad }, + { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, + { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, + { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, + { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, + { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, + { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, + { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, + { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, + { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, + { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, + { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, + { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, + { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, + { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, + { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, + { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, + { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, + { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, + { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, + { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, + { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, + { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, + { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, + { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, + { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, + { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, + { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, + { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, + { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, + { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, + { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, + { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, + { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, + { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, + { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, + { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, + { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, + { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, + { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, + { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, + { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, + { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, + { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, + { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, + { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, + { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, + { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, + { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, + { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, + { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, + { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, + { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, + { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, + { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, + { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, + { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, + { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, + { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, + { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, + { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, + { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, + { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, + { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, + { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, + { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, + { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, + { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, + { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, + { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, + { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, + { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, + { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, + { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, + { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, + { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, + { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, + { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 }, + { 0x0000a20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 }, + { 0x0000b20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, + { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, + { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, + { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, + { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, + { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, + { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, + { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, + { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, + { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, + { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, + { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, + { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, + { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, + { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, + { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, + { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, + { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, + { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, + { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, + { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, + { 0x0000784c, 0x0e4f048c, 0x0e4f048c, 0x0e4d048c, 0x0e4d048c, 0x0e4d048c }, + { 0x00007854, 0x12031828, 0x12031828, 0x12035828, 0x12035828, 0x12035828 }, + { 0x00007870, 0x807ec400, 0x807ec400, 0x807ec000, 0x807ec000, 0x807ec000 }, + { 0x0000788c, 0x00010000, 0x00010000, 0x00110000, 0x00110000, 0x00110000 }, +}; + +static const u32 ar9280Common_9280[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00007010, 0x00000033 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0x00000000 }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00000000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00008344, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xaf268e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a01ae }, + { 0x0000984c, 0x0040233c }, + { 0x0000a84c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x0000a920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0xe250a51e }, + { 0x00009958, 0x3388ffff }, + { 0x00009940, 0x00781204 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x0000c968, 0x000003ce }, + { 0x00009970, 0x190fb514 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x006f00c4 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099fc, 0x00001042 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x40206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x23277200 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x001da000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cdbd380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0ebae9c6 }, + { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce }, + { 0x0000a358, 0x7999aa0f }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x0000a3ec, 0x00f38081 }, + { 0x00007800, 0x00040000 }, + { 0x00007804, 0xdb005012 }, + { 0x00007808, 0x04924914 }, + { 0x0000780c, 0x21084210 }, + { 0x00007810, 0x6d801300 }, + { 0x00007814, 0x0019beff }, + { 0x00007818, 0x07e40000 }, + { 0x0000781c, 0x00492000 }, + { 0x00007820, 0x92492480 }, + { 0x00007824, 0x00040000 }, + { 0x00007828, 0xdb005012 }, + { 0x0000782c, 0x04924914 }, + { 0x00007830, 0x21084210 }, + { 0x00007834, 0x6d801300 }, + { 0x00007838, 0x0019beff }, + { 0x0000783c, 0x07e40000 }, + { 0x00007840, 0x00492000 }, + { 0x00007844, 0x92492480 }, + { 0x00007848, 0x00120000 }, + { 0x00007850, 0x54214514 }, + { 0x00007858, 0x92592692 }, + { 0x00007860, 0x52802000 }, + { 0x00007864, 0x0a8e370e }, + { 0x00007868, 0xc0102850 }, + { 0x0000786c, 0x812d4000 }, + { 0x00007874, 0x001b6db0 }, + { 0x00007878, 0x00376b63 }, + { 0x0000787c, 0x06db6db6 }, + { 0x00007880, 0x006d8000 }, + { 0x00007884, 0xffeffffe }, + { 0x00007888, 0xffeffffe }, + { 0x00007890, 0x00060aeb }, + { 0x00007894, 0x5a108000 }, + { 0x00007898, 0x2a850160 }, +}; + +/* XXX 9280 2 */ +static const u32 ar9280Modes_9280_2[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, + { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, + { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, + { 0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, + { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, + { 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e }, + { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, + { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, + { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 }, + { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, + { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, + { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, + { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, + { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c }, + { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, + { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, + { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000, 0x13c88000 }, + { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 }, + { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, + { 0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000, 0x0c000000 }, + { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 }, +}; + +static const u32 ar9280Common_9280_2[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00004060, 0x00000000 }, + { 0x00004064, 0x00000000 }, + { 0x00007010, 0x00000033 }, + { 0x00007034, 0x00000002 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080c0, 0x2a80001a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c0, 0x00000000 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008264, 0xa8a00010 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x0000829c, 0x00000000 }, + { 0x00008300, 0x00000040 }, + { 0x00008314, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00ff0000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00008344, 0x00481043 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xafa68e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x0040233c }, + { 0x0000a84c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x00009910, 0x01002310 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x0000a920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x2108ecff }, + { 0x00009940, 0x14750604 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x00009970, 0x190fb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x006f0000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099f0, 0x00000000 }, + { 0x000099fc, 0x00001042 }, + { 0x0000a208, 0x803e4788 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x40206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x233f7180 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cdbd380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0e79e5c6 }, + { 0x0000b26c, 0x0e79e5c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x0000a3ec, 0x00f70081 }, + { 0x00007800, 0x00040000 }, + { 0x00007804, 0xdb005012 }, + { 0x00007808, 0x04924914 }, + { 0x0000780c, 0x21084210 }, + { 0x00007810, 0x6d801300 }, + { 0x00007818, 0x07e41000 }, + { 0x00007824, 0x00040000 }, + { 0x00007828, 0xdb005012 }, + { 0x0000782c, 0x04924914 }, + { 0x00007830, 0x21084210 }, + { 0x00007834, 0x6d801300 }, + { 0x0000783c, 0x07e40000 }, + { 0x00007848, 0x00100000 }, + { 0x0000784c, 0x773f0567 }, + { 0x00007850, 0x54214514 }, + { 0x00007854, 0x12035828 }, + { 0x00007858, 0x9259269a }, + { 0x00007860, 0x52802000 }, + { 0x00007864, 0x0a8e370e }, + { 0x00007868, 0xc0102850 }, + { 0x0000786c, 0x812d4000 }, + { 0x00007870, 0x807ec400 }, + { 0x00007874, 0x001b6db0 }, + { 0x00007878, 0x00376b63 }, + { 0x0000787c, 0x06db6db6 }, + { 0x00007880, 0x006d8000 }, + { 0x00007884, 0xffeffffe }, + { 0x00007888, 0xffeffffe }, + { 0x0000788c, 0x00010000 }, + { 0x00007890, 0x02060aeb }, + { 0x00007898, 0x2a850160 }, +}; + +static const u32 ar9280Modes_fast_clock_9280_2[][3] = { + { 0x00001030, 0x00000268, 0x000004d0 }, + { 0x00001070, 0x0000018c, 0x00000318 }, + { 0x000010b0, 0x00000fd0, 0x00001fa0 }, + { 0x00008014, 0x044c044c, 0x08980898 }, + { 0x0000801c, 0x148ec02b, 0x148ec057 }, + { 0x00008318, 0x000044c0, 0x00008980 }, + { 0x00009820, 0x02020200, 0x02020200 }, + { 0x00009824, 0x01000f0f, 0x01000f0f }, + { 0x00009828, 0x0b020001, 0x0b020001 }, + { 0x00009834, 0x00000f0f, 0x00000f0f }, + { 0x00009844, 0x03721821, 0x03721821 }, + { 0x00009914, 0x00000898, 0x00001130 }, + { 0x00009918, 0x0000000b, 0x00000016 }, +}; + +static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = { + { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, + { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, + { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, + { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, + { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, + { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, + { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, + { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, + { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, + { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, + { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, + { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, + { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, + { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, + { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, + { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, + { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, + { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, + { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, + { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, + { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, + { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, + { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, + { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, + { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, + { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, + { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, + { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, + { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, + { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, + { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, + { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, + { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, + { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, + { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, + { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, + { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, + { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, + { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, + { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, + { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, + { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, + { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, + { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, + { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, + { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, + { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, + { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10 }, + { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b14, 0x00008b14, 0x00008b14 }, + { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b01, 0x00008b01, 0x00008b01 }, + { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b05, 0x00008b05, 0x00008b05 }, + { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b09, 0x00008b09, 0x00008b09 }, + { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b0d, 0x00008b0d, 0x00008b0d }, + { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b11, 0x00008b11, 0x00008b11 }, + { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b15, 0x00008b15, 0x00008b15 }, + { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008b02, 0x00008b02, 0x00008b02 }, + { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008b06, 0x00008b06, 0x00008b06 }, + { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008b0a, 0x00008b0a, 0x00008b0a }, + { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008b0e, 0x00008b0e, 0x00008b0e }, + { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008b12, 0x00008b12, 0x00008b12 }, + { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008b16, 0x00008b16, 0x00008b16 }, + { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008b03, 0x00008b03, 0x00008b03 }, + { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008b07, 0x00008b07, 0x00008b07 }, + { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008b0b, 0x00008b0b, 0x00008b0b }, + { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008b0f, 0x00008b0f, 0x00008b0f }, + { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008b13, 0x00008b13, 0x00008b13 }, + { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008b17, 0x00008b17, 0x00008b17 }, + { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008b23, 0x00008b23, 0x00008b23 }, + { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008b27, 0x00008b27, 0x00008b27 }, + { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008b2b, 0x00008b2b, 0x00008b2b }, + { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008b2f, 0x00008b2f, 0x00008b2f }, + { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008b33, 0x00008b33, 0x00008b33 }, + { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008b37, 0x00008b37, 0x00008b37 }, + { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008b43, 0x00008b43, 0x00008b43 }, + { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008b47, 0x00008b47, 0x00008b47 }, + { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008b4b, 0x00008b4b, 0x00008b4b }, + { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008b4f, 0x00008b4f, 0x00008b4f }, + { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008b53, 0x00008b53, 0x00008b53 }, + { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008b57, 0x00008b57, 0x00008b57 }, + { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 }, + { 0x0000a848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 }, +}; + +static const u32 ar9280Modes_original_rxgain_9280_2[][6] = { + { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, + { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, + { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, + { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, + { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, + { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, + { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, + { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, + { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, + { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, + { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, + { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, + { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, + { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, + { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, + { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, + { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, + { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, + { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, + { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, + { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, + { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, + { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, + { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, + { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, + { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, + { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, + { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, + { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, + { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, + { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, + { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, + { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, + { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, + { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, + { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, + { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, + { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, + { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, + { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, + { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, + { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, + { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, + { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, + { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, + { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, + { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, + { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, + { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, + { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, + { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, + { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, + { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, + { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, + { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, + { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, + { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, + { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, + { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, + { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, + { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, + { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, + { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, + { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, + { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, + { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, + { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, + { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, + { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, + { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, + { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, + { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, + { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, + { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, + { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, + { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, + { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, + { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, + { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, + { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, + { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, + { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, + { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, + { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, + { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, + { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, + { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, + { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, + { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, + { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, + { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, + { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, + { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, + { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, + { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, + { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, + { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, + { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, + { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, + { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, +}; + +static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = { + { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, + { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, + { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, + { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, + { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, + { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, + { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, + { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, + { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, + { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, + { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, + { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, + { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, + { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, + { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, + { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, + { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, + { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, + { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, + { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, + { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, + { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, + { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, + { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, + { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, + { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, + { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, + { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, + { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, + { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, + { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, + { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, + { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, + { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, + { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, + { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, + { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, + { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, + { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, + { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, + { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, + { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, + { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, + { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, + { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, + { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, + { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, + { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, + { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, + { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, + { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, + { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, + { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, + { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, + { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, + { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, + { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, + { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310 }, + { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314 }, + { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320 }, + { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324 }, + { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328 }, + { 0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c }, + { 0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330 }, + { 0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334 }, + { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321 }, + { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325 }, + { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329 }, + { 0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d }, + { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331 }, + { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335 }, + { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322 }, + { 0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326 }, + { 0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a }, + { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e }, + { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332 }, + { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336 }, + { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323 }, + { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327 }, + { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b }, + { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f }, + { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333 }, + { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337 }, + { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343 }, + { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347 }, + { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b }, + { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f }, + { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353 }, + { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357 }, + { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a }, + { 0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a }, +}; + +static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = { + { 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, + { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce }, + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 }, + { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 }, + { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010 }, + { 0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012 }, + { 0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014 }, + { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a }, + { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 }, + { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, + { 0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411 }, + { 0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413 }, + { 0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811 }, + { 0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813 }, + { 0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14 }, + { 0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50 }, + { 0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c }, + { 0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a }, + { 0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92 }, + { 0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 }, + { 0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 }, + { 0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 }, + { 0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5 }, + { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, + { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, + { 0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, + { 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, + { 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, + { 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, +}; + +static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = { + { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, + { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, + { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, + { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, + { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, + { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, + { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, + { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, + { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, + { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, + { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, + { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, + { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, + { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, + { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, + { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, + { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, + { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, + { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, + { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, + { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, + { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, + { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, + { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, + { 0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, + { 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, + { 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, + { 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, +}; + +static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffc }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffd }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +/* AR9285 Revsion 10*/ +static const u_int32_t ar9285Modes_9285[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020, 0x037216a0 }, + { 0x00009848, 0x00001066, 0x00001066, 0x0000004e, 0x0000004e, 0x00001059 }, + { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, + { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e, 0x3139605e }, + { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 }, + { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, + { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, + { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1020, 0xdfbc1020, 0xdfbc1010 }, + { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099b8, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c }, + { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 }, + { 0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 }, + { 0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 }, + { 0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 }, + { 0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 }, + { 0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 }, + { 0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, + { 0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114, 0x00000000 }, + { 0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 }, + { 0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 }, + { 0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 }, + { 0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 }, + { 0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 }, + { 0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 }, + { 0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 }, + { 0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 }, + { 0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 }, + { 0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284, 0x00000000 }, + { 0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288, 0x00000000 }, + { 0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220, 0x00000000 }, + { 0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 }, + { 0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 }, + { 0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304, 0x00000000 }, + { 0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 }, + { 0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 }, + { 0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380, 0x00000000 }, + { 0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384, 0x00000000 }, + { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, + { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, + { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, + { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, + { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, + { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, + { 0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04, 0x00000000 }, + { 0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 }, + { 0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 }, + { 0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c, 0x00000000 }, + { 0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80, 0x00000000 }, + { 0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84, 0x00000000 }, + { 0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88, 0x00000000 }, + { 0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c, 0x00000000 }, + { 0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90, 0x00000000 }, + { 0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80, 0x00000000 }, + { 0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, + { 0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 }, + { 0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c, 0x00000000 }, + { 0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90, 0x00000000 }, + { 0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c, 0x00000000 }, + { 0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310, 0x00000000 }, + { 0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 }, + { 0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 }, + { 0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324, 0x00000000 }, + { 0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704, 0x00000000 }, + { 0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4, 0x00000000 }, + { 0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8, 0x00000000 }, + { 0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 }, + { 0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 }, + { 0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720, 0x00000000 }, + { 0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724, 0x00000000 }, + { 0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728, 0x00000000 }, + { 0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c, 0x00000000 }, + { 0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0, 0x00000000 }, + { 0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4, 0x00000000 }, + { 0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 }, + { 0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 }, + { 0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4, 0x00000000 }, + { 0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 }, + { 0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 }, + { 0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 }, + { 0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad, 0x00000000 }, + { 0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 }, + { 0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 }, + { 0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9, 0x00000000 }, + { 0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5, 0x00000000 }, + { 0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 }, + { 0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 }, + { 0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5, 0x00000000 }, + { 0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 }, + { 0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 }, + { 0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 }, + { 0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 }, + { 0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 }, + { 0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 }, + { 0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 }, + { 0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7, 0x00000000 }, + { 0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 }, + { 0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf, 0x00000000 }, + { 0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7, 0x00000000 }, + { 0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 }, + { 0x0000aa04, 0x00000000, 0x00000000, 0x00068080, 0x00068080, 0x00000000 }, + { 0x0000aa08, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 }, + { 0x0000aa0c, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 }, + { 0x0000aa10, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 }, + { 0x0000aa14, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 }, + { 0x0000aa18, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 }, + { 0x0000aa1c, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 }, + { 0x0000aa20, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 }, + { 0x0000aa24, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, + { 0x0000aa28, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, + { 0x0000aa2c, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 }, + { 0x0000aa30, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 }, + { 0x0000aa34, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 }, + { 0x0000aa38, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 }, + { 0x0000aa3c, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 }, + { 0x0000aa40, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 }, + { 0x0000aa44, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 }, + { 0x0000aa48, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 }, + { 0x0000aa4c, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 }, + { 0x0000aa50, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac, 0x00000000 }, + { 0x0000aa54, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c, 0x00000000 }, + { 0x0000aa58, 0x00000000, 0x00000000, 0x00068224, 0x00068224, 0x00000000 }, + { 0x0000aa5c, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 }, + { 0x0000aa60, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 }, + { 0x0000aa64, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 }, + { 0x0000aa68, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 }, + { 0x0000aa6c, 0x00000000, 0x00000000, 0x00068310, 0x00068310, 0x00000000 }, + { 0x0000aa70, 0x00000000, 0x00000000, 0x00068788, 0x00068788, 0x00000000 }, + { 0x0000aa74, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c, 0x00000000 }, + { 0x0000aa78, 0x00000000, 0x00000000, 0x00068790, 0x00068790, 0x00000000 }, + { 0x0000aa7c, 0x00000000, 0x00000000, 0x00068794, 0x00068794, 0x00000000 }, + { 0x0000aa80, 0x00000000, 0x00000000, 0x00068798, 0x00068798, 0x00000000 }, + { 0x0000aa84, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c, 0x00000000 }, + { 0x0000aa88, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89, 0x00000000 }, + { 0x0000aa8c, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d, 0x00000000 }, + { 0x0000aa90, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91, 0x00000000 }, + { 0x0000aa94, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95, 0x00000000 }, + { 0x0000aa98, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99, 0x00000000 }, + { 0x0000aa9c, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5, 0x00000000 }, + { 0x0000aaa0, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9, 0x00000000 }, + { 0x0000aaa4, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad, 0x00000000 }, + { 0x0000aaa8, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c, 0x00000000 }, + { 0x0000aaac, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10, 0x00000000 }, + { 0x0000aab0, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14, 0x00000000 }, + { 0x0000aab4, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, + { 0x0000aab8, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, + { 0x0000aabc, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 }, + { 0x0000aac0, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380, 0x00000000 }, + { 0x0000aac4, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 }, + { 0x0000aac8, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 }, + { 0x0000aacc, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c, 0x00000000 }, + { 0x0000aad0, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394, 0x00000000 }, + { 0x0000aad4, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798, 0x00000000 }, + { 0x0000aad8, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c, 0x00000000 }, + { 0x0000aadc, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 }, + { 0x0000aae0, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 }, + { 0x0000aae4, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718, 0x00000000 }, + { 0x0000aae8, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705, 0x00000000 }, + { 0x0000aaec, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709, 0x00000000 }, + { 0x0000aaf0, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d, 0x00000000 }, + { 0x0000aaf4, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711, 0x00000000 }, + { 0x0000aaf8, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715, 0x00000000 }, + { 0x0000aafc, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719, 0x00000000 }, + { 0x0000ab00, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4, 0x00000000 }, + { 0x0000ab04, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 }, + { 0x0000ab08, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 }, + { 0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 }, + { 0x0000ab10, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 }, + { 0x0000ab14, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 }, + { 0x0000ab18, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc, 0x00000000 }, + { 0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1, 0x00000000 }, + { 0x0000ab20, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 }, + { 0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 }, + { 0x0000ab28, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 }, + { 0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 }, + { 0x0000ab30, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd, 0x00000000 }, + { 0x0000ab34, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 }, + { 0x0000ab38, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd, 0x00000000 }, + { 0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 }, + { 0x0000ab40, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 }, + { 0x0000ab44, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2, 0x00000000 }, + { 0x0000ab48, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 }, + { 0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 }, + { 0x0000ab50, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 }, + { 0x0000ab54, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 }, + { 0x0000ab58, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 }, + { 0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 }, + { 0x0000ab60, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 }, + { 0x0000ab64, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab68, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, + { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000, 0x0001f000 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a250, 0x001ff000, 0x001ff000, 0x001ca000, 0x001ca000, 0x001da000 }, + { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652, 0x0a82a652 }, + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0002c89a, 0x0002c89a, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0002e89b, 0x0002e89b, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0003089c, 0x0003089c, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0003289d, 0x0003289d, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0003489e, 0x0003489e, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x000388de, 0x000388de, 0x00000000 }, + { 0x0000a338, 0x00000000, 0x00000000, 0x0003b91e, 0x0003b91e, 0x00000000 }, + { 0x0000a33c, 0x00000000, 0x00000000, 0x0003d95e, 0x0003d95e, 0x00000000 }, + { 0x0000a340, 0x00000000, 0x00000000, 0x000419df, 0x000419df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, +}; + +static const u_int32_t ar9285Common_9285[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020045 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00004060, 0x00000000 }, + { 0x00004064, 0x00000000 }, + { 0x00007010, 0x00000031 }, + { 0x00007034, 0x00000002 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x00000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080c0, 0x2a80001a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0x00000000 }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c0, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008264, 0xa8a00010 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x0000829c, 0x00000000 }, + { 0x00008300, 0x00000040 }, + { 0x00008314, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000001 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00000000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x00010380 }, + { 0x00008344, 0x00481043 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xafe68e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x00009910, 0x01002310 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009940, 0x14750604 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x2108ecff }, + { 0x00009968, 0x000003ce }, + { 0x00009970, 0x1927b515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x2def0a00 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099f0, 0x00000000 }, + { 0x0000a208, 0x803e6788 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x00206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a244, 0x00000000 }, + { 0x0000a248, 0xfffffffc }, + { 0x0000a24c, 0x00000000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0ccb5380 }, + { 0x0000a25c, 0x15151501 }, + { 0x0000a260, 0xdfa90f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0ebae9e6 }, + { 0x0000d270, 0x0d820820 }, + { 0x0000a278, 0x39ce739c }, + { 0x0000a27c, 0x050e039c }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x39ce739c }, + { 0x0000a398, 0x0000039c }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x39ce739c }, + { 0x0000a3e0, 0x0000039c }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x0000a3ec, 0x00f70081 }, + { 0x00007800, 0x00140000 }, + { 0x00007804, 0x0e4548d8 }, + { 0x00007808, 0x54214514 }, + { 0x0000780c, 0x02025820 }, + { 0x00007810, 0x71c0d388 }, + { 0x00007814, 0x924934a8 }, + { 0x0000781c, 0x00000000 }, + { 0x00007820, 0x00000c04 }, + { 0x00007824, 0x00d86fff }, + { 0x00007828, 0x26d2491b }, + { 0x0000782c, 0x6e36d97b }, + { 0x00007830, 0xedb6d96c }, + { 0x00007834, 0x71400086 }, + { 0x00007838, 0xfac68800 }, + { 0x0000783c, 0x0001fffe }, + { 0x00007840, 0xffeb1a20 }, + { 0x00007844, 0x000c0db6 }, + { 0x00007848, 0x6db61b6f }, + { 0x0000784c, 0x6d9b66db }, + { 0x00007850, 0x6d8c6dba }, + { 0x00007854, 0x00040000 }, + { 0x00007858, 0xdb003012 }, + { 0x0000785c, 0x04924914 }, + { 0x00007860, 0x21084210 }, + { 0x00007864, 0xf7d7ffde }, + { 0x00007868, 0xc2034080 }, + { 0x0000786c, 0x48609eb4 }, + { 0x00007870, 0x10142c00 }, +}; + +static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffd }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffc }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +/* AR9285 v1_2 PCI Register Writes. Created: 04/13/09 */ +static const u_int32_t ar9285Modes_9285_1_2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 }, + { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, + { 0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, + { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, + { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, + { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 }, + { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, + { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, + { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 }, + { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c }, + { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, + { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, + { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, + { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, + { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, + { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, + { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, + { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, + { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, + { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, + { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, + { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, + { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, + { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, + { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, + { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, + { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, + { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, + { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, + { 0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, + { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, + { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, + { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, + { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, + { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, + { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, + { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, + { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, + { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, + { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, + { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, + { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, + { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, + { 0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, + { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, + { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, + { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, + { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, + { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, + { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, + { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, + { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, + { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, + { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, + { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, + { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, + { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, + { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, + { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, + { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, + { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, + { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, + { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, + { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, + { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, + { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, + { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, + { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, + { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, + { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, + { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, + { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, + { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, + { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, + { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, + { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, + { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, + { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, + { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, + { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, + { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, + { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, + { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, + { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, + { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, + { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, + { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, + { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, + { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, + { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, + { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, + { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, + { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, + { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, + { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, + { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, + { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, + { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, + { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, + { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, + { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, + { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, + { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, + { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, + { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, + { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, + { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, + { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, + { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, + { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, + { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, + { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, + { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, + { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, + { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, + { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, + { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, + { 0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, + { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, + { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, + { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, + { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, + { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, + { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, + { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, + { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, + { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, + { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, + { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, + { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, + { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, + { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, + { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, + { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, + { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, + { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, + { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, + { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, + { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, + { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, + { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, + { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, + { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, + { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, + { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, + { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, + { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, + { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, + { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, + { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, + { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, + { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, + { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, + { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, + { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, + { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, + { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, + { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, + { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, + { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, + { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, + { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, + { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, + { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, + { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, + { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, + { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, + { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, + { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, + { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, + { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, + { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, + { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, + { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, + { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, + { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, + { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, + { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, + { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, + { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, + { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, + { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, + { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, + { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, + { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, + { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, + { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, + { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, + { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, +}; + +static const u_int32_t ar9285Common_9285_1_2[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020045 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00004060, 0x00000000 }, + { 0x00004064, 0x00000000 }, + { 0x00007010, 0x00000031 }, + { 0x00007034, 0x00000002 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x00000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080c0, 0x2a80001a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04810 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c0, 0x00000000 }, + { 0x000081d0, 0x0000320a }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008264, 0x88a00010 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x0000829c, 0x00000000 }, + { 0x00008300, 0x00000040 }, + { 0x00008314, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000001 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00ff0000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x00010380 }, + { 0x00008344, 0x00481043 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xafe68e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x00009910, 0x01002310 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009940, 0x14750604 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x2108ecff }, + { 0x00009968, 0x000003ce }, + { 0x00009970, 0x192bb514 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x2def0400 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099f0, 0x00000000 }, + { 0x0000a208, 0x803e68c8 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x00206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a244, 0x00000000 }, + { 0x0000a248, 0xfffffffc }, + { 0x0000a24c, 0x00000000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0ccb5380 }, + { 0x0000a25c, 0x15151501 }, + { 0x0000a260, 0xdfa90f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0ebae9e6 }, + { 0x0000d270, 0x0d820820 }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x0000a3ec, 0x00f70081 }, + { 0x00007800, 0x00140000 }, + { 0x00007804, 0x0e4548d8 }, + { 0x00007808, 0x54214514 }, + { 0x0000780c, 0x02025830 }, + { 0x00007810, 0x71c0d388 }, + { 0x0000781c, 0x00000000 }, + { 0x00007824, 0x00d86fff }, + { 0x0000782c, 0x6e36d97b }, + { 0x00007834, 0x71400087 }, + { 0x00007844, 0x000c0db6 }, + { 0x00007848, 0x6db6246f }, + { 0x0000784c, 0x6d9b66db }, + { 0x00007850, 0x6d8c6dba }, + { 0x00007854, 0x00040000 }, + { 0x00007858, 0xdb003012 }, + { 0x0000785c, 0x04924914 }, + { 0x00007860, 0x21084210 }, + { 0x00007864, 0xf7d7ffde }, + { 0x00007868, 0xc2034080 }, + { 0x00007870, 0x10142c00 }, +}; + +static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 }, + { 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b }, + { 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e }, + { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, + { 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe }, + { 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 }, + { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, + { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, + { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 }, + { 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, + { 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, +}; + +static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 }, + { 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b }, + { 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e }, + { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 }, + { 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe }, + { 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 }, + { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, + { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, + { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, + { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, + { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, + { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, +}; + +static const u_int32_t ar9285Modes_XE2_0_normal_power[][6] = { + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 }, + { 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b }, + { 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6dbae }, + { 0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441 }, + { 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe }, + { 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c }, + { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, + { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, + { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, + { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, + { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, + { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, +}; + +static const u_int32_t ar9285Modes_XE2_0_high_power[][6] = { + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 }, + { 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b }, + { 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e }, + { 0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443 }, + { 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe }, + { 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c }, + { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, + { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, + { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 }, + { 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, + { 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, +}; + +static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffd }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffc }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +/* AR9287 Revision 10 */ +static const u_int32_t ar9287Modes_9287_1_0[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, + { 0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, + { 0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a }, + { 0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880 }, + { 0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e }, + { 0x00009828, 0x00000000, 0x00000000, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e }, + { 0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0 }, + { 0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, + { 0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, + { 0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e }, + { 0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18 }, + { 0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, + { 0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010 }, + { 0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 }, + { 0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210 }, + { 0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce }, + { 0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c }, + { 0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444 }, + { 0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000 }, + { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, + { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const u_int32_t ar9287Common_9287_1_0[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00004060, 0x00000000 }, + { 0x00004064, 0x00000000 }, + { 0x00007010, 0x00000033 }, + { 0x00007020, 0x00000000 }, + { 0x00007034, 0x00000002 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080c0, 0x2a80001a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x18487320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c0, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d4, 0x00000000 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008264, 0xa8a00010 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x000000ff }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x0000829c, 0x00000000 }, + { 0x00008300, 0x00000040 }, + { 0x00008314, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00ff0000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00008344, 0x01c81043 }, + { 0x00008360, 0xffffffff }, + { 0x00008364, 0xffffffff }, + { 0x00008368, 0x00000000 }, + { 0x00008370, 0x00000000 }, + { 0x00008374, 0x000000ff }, + { 0x00008378, 0x00000000 }, + { 0x0000837c, 0x00000000 }, + { 0x00008380, 0xffffffff }, + { 0x00008384, 0xffffffff }, + { 0x00008390, 0x0fffffff }, + { 0x00008394, 0x0fffffff }, + { 0x00008398, 0x00000000 }, + { 0x0000839c, 0x00000000 }, + { 0x000083a0, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xafe68e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x0040233c }, + { 0x0000a84c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x00009910, 0x10002310 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x0000a920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009930, 0x00000000 }, + { 0x0000a930, 0x00000000 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x0108ecff }, + { 0x00009940, 0x14750604 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x00009970, 0x990bb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x0c6f0000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099c4, 0x06336f77 }, + { 0x000099c8, 0x6af65329 }, + { 0x000099cc, 0x08f186c8 }, + { 0x000099d0, 0x00046384 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099f0, 0x00000000 }, + { 0x000099fc, 0x00001042 }, + { 0x0000a1f4, 0x00fffeff }, + { 0x0000a1f8, 0x00f5f9ff }, + { 0x0000a1fc, 0xb79f6427 }, + { 0x0000a208, 0x803e4788 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x40206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x233f7180 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00000000 }, + { 0x0000a248, 0xfffffffc }, + { 0x0000a24c, 0x00000000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cdbd380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a264, 0x00418a11 }, + { 0x0000b264, 0x00418a11 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0e79e5c6 }, + { 0x0000b26c, 0x0e79e5c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000b398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x0000a3ec, 0x00f70081 }, + { 0x0000a3f0, 0x01036a1e }, + { 0x0000a3f4, 0x00000000 }, + { 0x0000b3f4, 0x00000000 }, + { 0x0000a7d8, 0x00000001 }, + { 0x00007800, 0x00000800 }, + { 0x00007804, 0x6c35ffb0 }, + { 0x00007808, 0x6db6c000 }, + { 0x0000780c, 0x6db6cb30 }, + { 0x00007810, 0x6db6cb6c }, + { 0x00007814, 0x0501e200 }, + { 0x00007818, 0x0094128d }, + { 0x0000781c, 0x976ee392 }, + { 0x00007820, 0xf75ff6fc }, + { 0x00007824, 0x00040000 }, + { 0x00007828, 0xdb003012 }, + { 0x0000782c, 0x04924914 }, + { 0x00007830, 0x21084210 }, + { 0x00007834, 0x00140000 }, + { 0x00007838, 0x0e4548d8 }, + { 0x0000783c, 0x54214514 }, + { 0x00007840, 0x02025820 }, + { 0x00007844, 0x71c0d388 }, + { 0x00007848, 0x934934a8 }, + { 0x00007850, 0x00000000 }, + { 0x00007854, 0x00000800 }, + { 0x00007858, 0x6c35ffb0 }, + { 0x0000785c, 0x6db6c000 }, + { 0x00007860, 0x6db6cb2c }, + { 0x00007864, 0x6db6cb6c }, + { 0x00007868, 0x0501e200 }, + { 0x0000786c, 0x0094128d }, + { 0x00007870, 0x976ee392 }, + { 0x00007874, 0xf75ff6fc }, + { 0x00007878, 0x00040000 }, + { 0x0000787c, 0xdb003012 }, + { 0x00007880, 0x04924914 }, + { 0x00007884, 0x21084210 }, + { 0x00007888, 0x001b6db0 }, + { 0x0000788c, 0x00376b63 }, + { 0x00007890, 0x06db6db6 }, + { 0x00007894, 0x006d8000 }, + { 0x00007898, 0x48100000 }, + { 0x0000789c, 0x00000000 }, + { 0x000078a0, 0x08000000 }, + { 0x000078a4, 0x0007ffd8 }, + { 0x000078a8, 0x0007ffd8 }, + { 0x000078ac, 0x001c0020 }, + { 0x000078b0, 0x000611eb }, + { 0x000078b4, 0x40008080 }, + { 0x000078b8, 0x2a850160 }, +}; + +static const u_int32_t ar9287Modes_tx_gain_9287_1_0[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a }, + { 0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b }, + { 0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a }, + { 0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a }, + { 0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a }, + { 0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c }, + { 0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc }, + { 0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4 }, + { 0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc }, + { 0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede }, + { 0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e }, + { 0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e }, + { 0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e }, + { 0x0000a780, 0x00000000, 0x00000000, 0x00000060, 0x00000060, 0x00000060 }, + { 0x0000a784, 0x00000000, 0x00000000, 0x00004062, 0x00004062, 0x00004062 }, + { 0x0000a788, 0x00000000, 0x00000000, 0x00008064, 0x00008064, 0x00008064 }, + { 0x0000a78c, 0x00000000, 0x00000000, 0x0000c0a4, 0x0000c0a4, 0x0000c0a4 }, + { 0x0000a790, 0x00000000, 0x00000000, 0x000100b0, 0x000100b0, 0x000100b0 }, + { 0x0000a794, 0x00000000, 0x00000000, 0x000140b2, 0x000140b2, 0x000140b2 }, + { 0x0000a798, 0x00000000, 0x00000000, 0x000180b4, 0x000180b4, 0x000180b4 }, + { 0x0000a79c, 0x00000000, 0x00000000, 0x0001c0f4, 0x0001c0f4, 0x0001c0f4 }, + { 0x0000a7a0, 0x00000000, 0x00000000, 0x00020134, 0x00020134, 0x00020134 }, + { 0x0000a7a4, 0x00000000, 0x00000000, 0x000240fe, 0x000240fe, 0x000240fe }, + { 0x0000a7a8, 0x00000000, 0x00000000, 0x0002813e, 0x0002813e, 0x0002813e }, + { 0x0000a7ac, 0x00000000, 0x00000000, 0x0002c17e, 0x0002c17e, 0x0002c17e }, + { 0x0000a7b0, 0x00000000, 0x00000000, 0x000301be, 0x000301be, 0x000301be }, + { 0x0000a7b4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, + { 0x0000a7b8, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, + { 0x0000a7bc, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, + { 0x0000a7c0, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, + { 0x0000a7c4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, + { 0x0000a7c8, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, + { 0x0000a7cc, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, + { 0x0000a7d0, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, + { 0x0000a7d4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, + { 0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000 }, +}; + + +static const u_int32_t ar9287Modes_rx_gain_9287_1_0[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 }, + { 0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, + { 0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 }, + { 0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c }, + { 0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 }, + { 0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 }, + { 0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 }, + { 0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c }, + { 0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 }, + { 0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 }, + { 0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 }, + { 0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c }, + { 0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 }, + { 0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 }, + { 0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 }, + { 0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 }, + { 0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 }, + { 0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac }, + { 0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 }, + { 0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 }, + { 0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 }, + { 0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 }, + { 0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 }, + { 0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c }, + { 0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 }, + { 0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 }, + { 0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 }, + { 0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c }, + { 0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 }, + { 0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 }, + { 0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 }, + { 0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c }, + { 0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 }, + { 0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 }, + { 0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 }, + { 0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 }, + { 0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 }, + { 0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 }, + { 0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 }, + { 0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c }, + { 0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 }, + { 0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 }, + { 0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 }, + { 0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c }, + { 0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 }, + { 0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 }, + { 0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 }, + { 0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 }, + { 0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 }, + { 0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 }, + { 0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c }, + { 0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 }, + { 0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 }, + { 0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 }, + { 0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 }, + { 0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 }, + { 0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac }, + { 0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 }, + { 0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 }, + { 0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 }, + { 0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 }, + { 0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 }, + { 0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 }, + { 0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 }, + { 0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 }, + { 0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 }, + { 0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 }, + { 0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c }, + { 0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 }, + { 0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 }, + { 0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c }, + { 0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 }, + { 0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 }, + { 0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 }, + { 0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 }, + { 0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 }, + { 0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac }, + { 0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 }, + { 0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 }, + { 0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 }, + { 0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 }, + { 0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 }, + { 0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad }, + { 0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 }, + { 0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 }, + { 0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 }, + { 0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 }, + { 0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 }, + { 0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd }, + { 0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 }, + { 0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 }, + { 0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 }, + { 0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 }, + { 0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca }, + { 0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce }, + { 0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 }, + { 0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 }, + { 0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda }, + { 0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 }, + { 0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb }, + { 0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf }, + { 0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 }, + { 0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 }, + { 0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 }, + { 0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, + { 0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 }, + { 0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c }, + { 0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 }, + { 0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 }, + { 0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 }, + { 0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c }, + { 0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 }, + { 0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 }, + { 0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 }, + { 0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c }, + { 0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 }, + { 0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 }, + { 0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 }, + { 0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 }, + { 0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 }, + { 0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac }, + { 0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 }, + { 0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 }, + { 0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 }, + { 0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 }, + { 0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 }, + { 0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c }, + { 0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 }, + { 0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 }, + { 0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 }, + { 0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c }, + { 0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 }, + { 0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 }, + { 0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 }, + { 0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c }, + { 0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 }, + { 0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 }, + { 0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 }, + { 0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 }, + { 0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 }, + { 0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 }, + { 0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 }, + { 0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c }, + { 0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 }, + { 0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 }, + { 0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 }, + { 0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c }, + { 0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 }, + { 0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 }, + { 0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 }, + { 0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 }, + { 0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 }, + { 0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 }, + { 0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c }, + { 0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 }, + { 0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 }, + { 0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 }, + { 0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 }, + { 0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 }, + { 0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac }, + { 0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 }, + { 0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 }, + { 0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 }, + { 0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 }, + { 0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 }, + { 0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 }, + { 0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 }, + { 0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 }, + { 0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 }, + { 0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 }, + { 0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c }, + { 0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 }, + { 0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 }, + { 0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c }, + { 0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 }, + { 0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 }, + { 0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 }, + { 0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 }, + { 0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 }, + { 0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac }, + { 0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 }, + { 0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 }, + { 0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 }, + { 0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 }, + { 0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 }, + { 0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad }, + { 0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 }, + { 0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 }, + { 0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 }, + { 0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 }, + { 0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 }, + { 0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd }, + { 0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 }, + { 0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 }, + { 0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 }, + { 0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 }, + { 0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca }, + { 0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce }, + { 0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 }, + { 0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 }, + { 0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda }, + { 0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 }, + { 0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb }, + { 0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf }, + { 0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 }, + { 0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 }, + { 0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 }, + { 0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 }, +}; + +static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_0[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffd }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_0[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffc }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +/* AR9287 Revision 11 */ + +static const u_int32_t ar9287Modes_9287_1_1[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, + { 0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, + { 0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a }, + { 0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880 }, + { 0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e }, + { 0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001, 0x3a020001 }, + { 0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e }, + { 0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0 }, + { 0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, + { 0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, + { 0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e }, + { 0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18 }, + { 0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, + { 0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010 }, + { 0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 }, + { 0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210 }, + { 0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce }, + { 0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c }, + { 0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444 }, + { 0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000 }, + { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, + { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const u_int32_t ar9287Common_9287_1_1[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00004060, 0x00000000 }, + { 0x00004064, 0x00000000 }, + { 0x00007010, 0x00000033 }, + { 0x00007020, 0x00000000 }, + { 0x00007034, 0x00000002 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080c0, 0x2a80001a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x18487320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c0, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d4, 0x00000000 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008264, 0x88a00010 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x000000ff }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x0000829c, 0x00000000 }, + { 0x00008300, 0x00000040 }, + { 0x00008314, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00ff0000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00008344, 0x01c81043 }, + { 0x00008360, 0xffffffff }, + { 0x00008364, 0xffffffff }, + { 0x00008368, 0x00000000 }, + { 0x00008370, 0x00000000 }, + { 0x00008374, 0x000000ff }, + { 0x00008378, 0x00000000 }, + { 0x0000837c, 0x00000000 }, + { 0x00008380, 0xffffffff }, + { 0x00008384, 0xffffffff }, + { 0x00008390, 0x0fffffff }, + { 0x00008394, 0x0fffffff }, + { 0x00008398, 0x00000000 }, + { 0x0000839c, 0x00000000 }, + { 0x000083a0, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xafe68e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x0040233c }, + { 0x0000a84c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x00009910, 0x10002310 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x0000a920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009930, 0x00000000 }, + { 0x0000a930, 0x00000000 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x0108ecff }, + { 0x00009940, 0x14750604 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x00009970, 0x990bb514 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x0c6f0000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099c4, 0x06336f77 }, + { 0x000099c8, 0x6af6532f }, + { 0x000099cc, 0x08f186c8 }, + { 0x000099d0, 0x00046384 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099f0, 0x00000000 }, + { 0x000099fc, 0x00001042 }, + { 0x0000a208, 0x803e4788 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x40206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x233f7180 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00000000 }, + { 0x0000a248, 0xfffffffc }, + { 0x0000a24c, 0x00000000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cdbd380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a264, 0x00418a11 }, + { 0x0000b264, 0x00418a11 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0e79e5c6 }, + { 0x0000b26c, 0x0e79e5c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000b398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x0000a3ec, 0x00f70081 }, + { 0x0000a3f0, 0x01036a1e }, + { 0x0000a3f4, 0x00000000 }, + { 0x0000b3f4, 0x00000000 }, + { 0x0000a7d8, 0x000003f1 }, + { 0x00007800, 0x00000800 }, + { 0x00007804, 0x6c35ffd2 }, + { 0x00007808, 0x6db6c000 }, + { 0x0000780c, 0x6db6cb30 }, + { 0x00007810, 0x6db6cb6c }, + { 0x00007814, 0x0501e200 }, + { 0x00007818, 0x0094128d }, + { 0x0000781c, 0x976ee392 }, + { 0x00007820, 0xf75ff6fc }, + { 0x00007824, 0x00040000 }, + { 0x00007828, 0xdb003012 }, + { 0x0000782c, 0x04924914 }, + { 0x00007830, 0x21084210 }, + { 0x00007834, 0x00140000 }, + { 0x00007838, 0x0e4548d8 }, + { 0x0000783c, 0x54214514 }, + { 0x00007840, 0x02025830 }, + { 0x00007844, 0x71c0d388 }, + { 0x00007848, 0x934934a8 }, + { 0x00007850, 0x00000000 }, + { 0x00007854, 0x00000800 }, + { 0x00007858, 0x6c35ffd2 }, + { 0x0000785c, 0x6db6c000 }, + { 0x00007860, 0x6db6cb30 }, + { 0x00007864, 0x6db6cb6c }, + { 0x00007868, 0x0501e200 }, + { 0x0000786c, 0x0094128d }, + { 0x00007870, 0x976ee392 }, + { 0x00007874, 0xf75ff6fc }, + { 0x00007878, 0x00040000 }, + { 0x0000787c, 0xdb003012 }, + { 0x00007880, 0x04924914 }, + { 0x00007884, 0x21084210 }, + { 0x00007888, 0x001b6db0 }, + { 0x0000788c, 0x00376b63 }, + { 0x00007890, 0x06db6db6 }, + { 0x00007894, 0x006d8000 }, + { 0x00007898, 0x48100000 }, + { 0x0000789c, 0x00000000 }, + { 0x000078a0, 0x08000000 }, + { 0x000078a4, 0x0007ffd8 }, + { 0x000078a8, 0x0007ffd8 }, + { 0x000078ac, 0x001c0020 }, + { 0x000078b0, 0x00060aeb }, + { 0x000078b4, 0x40008080 }, + { 0x000078b8, 0x2a850160 }, +}; + +/* + * For Japanese regulatory requirements, 2484 MHz requires the following three + * registers be programmed differently from the channel between 2412 and + * 2472 MHz. + */ +static const u_int32_t ar9287Common_normal_cck_fir_coeff_92871_1[][2] = { + { 0x0000a1f4, 0x00fffeff }, + { 0x0000a1f8, 0x00f5f9ff }, + { 0x0000a1fc, 0xb79f6427 }, +}; + +static const u_int32_t ar9287Common_japan_2484_cck_fir_coeff_92871_1[][2] = { + { 0x0000a1f4, 0x00000000 }, + { 0x0000a1f8, 0xefff0301 }, + { 0x0000a1fc, 0xca9228ee }, +}; + +static const u_int32_t ar9287Modes_tx_gain_9287_1_1[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a }, + { 0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b }, + { 0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a }, + { 0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a }, + { 0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a }, + { 0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c }, + { 0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc }, + { 0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4 }, + { 0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc }, + { 0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede }, + { 0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e }, + { 0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e }, + { 0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e }, + { 0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062, 0x00000062 }, + { 0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064, 0x00004064 }, + { 0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4, 0x000080a4 }, + { 0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa, 0x0000c0aa }, + { 0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac, 0x000100ac }, + { 0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4, 0x000140b4 }, + { 0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4, 0x000180f4 }, + { 0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134, 0x0001c134 }, + { 0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174, 0x00020174 }, + { 0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c, 0x0002417c }, + { 0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e, 0x0002817e }, + { 0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be, 0x0002c1be }, + { 0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, + { 0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, + { 0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, + { 0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, + { 0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, + { 0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, + { 0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, + { 0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, + { 0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, + { 0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, + { 0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000 }, +}; + +static const u_int32_t ar9287Modes_rx_gain_9287_1_1[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 }, + { 0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, + { 0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 }, + { 0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c }, + { 0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 }, + { 0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 }, + { 0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 }, + { 0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c }, + { 0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 }, + { 0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 }, + { 0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 }, + { 0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c }, + { 0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 }, + { 0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 }, + { 0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 }, + { 0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 }, + { 0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 }, + { 0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac }, + { 0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 }, + { 0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 }, + { 0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 }, + { 0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 }, + { 0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 }, + { 0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c }, + { 0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 }, + { 0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 }, + { 0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 }, + { 0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c }, + { 0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 }, + { 0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 }, + { 0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 }, + { 0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c }, + { 0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 }, + { 0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 }, + { 0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 }, + { 0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 }, + { 0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 }, + { 0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 }, + { 0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 }, + { 0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c }, + { 0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 }, + { 0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 }, + { 0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 }, + { 0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c }, + { 0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 }, + { 0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 }, + { 0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 }, + { 0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 }, + { 0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 }, + { 0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 }, + { 0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c }, + { 0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 }, + { 0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 }, + { 0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 }, + { 0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 }, + { 0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 }, + { 0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac }, + { 0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 }, + { 0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 }, + { 0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 }, + { 0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 }, + { 0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 }, + { 0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 }, + { 0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 }, + { 0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 }, + { 0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 }, + { 0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 }, + { 0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c }, + { 0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 }, + { 0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 }, + { 0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c }, + { 0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 }, + { 0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 }, + { 0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 }, + { 0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 }, + { 0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 }, + { 0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac }, + { 0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 }, + { 0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 }, + { 0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 }, + { 0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 }, + { 0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 }, + { 0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad }, + { 0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 }, + { 0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 }, + { 0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 }, + { 0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 }, + { 0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 }, + { 0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd }, + { 0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 }, + { 0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 }, + { 0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 }, + { 0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 }, + { 0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca }, + { 0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce }, + { 0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 }, + { 0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 }, + { 0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda }, + { 0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 }, + { 0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb }, + { 0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf }, + { 0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 }, + { 0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 }, + { 0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 }, + { 0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, + { 0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 }, + { 0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c }, + { 0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 }, + { 0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 }, + { 0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 }, + { 0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c }, + { 0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 }, + { 0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 }, + { 0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 }, + { 0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c }, + { 0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 }, + { 0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 }, + { 0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 }, + { 0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 }, + { 0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 }, + { 0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac }, + { 0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 }, + { 0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 }, + { 0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 }, + { 0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 }, + { 0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 }, + { 0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c }, + { 0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 }, + { 0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 }, + { 0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 }, + { 0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c }, + { 0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 }, + { 0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 }, + { 0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 }, + { 0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c }, + { 0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 }, + { 0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 }, + { 0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 }, + { 0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 }, + { 0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 }, + { 0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 }, + { 0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 }, + { 0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c }, + { 0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 }, + { 0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 }, + { 0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 }, + { 0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c }, + { 0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 }, + { 0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 }, + { 0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 }, + { 0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 }, + { 0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 }, + { 0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 }, + { 0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c }, + { 0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 }, + { 0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 }, + { 0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 }, + { 0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 }, + { 0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 }, + { 0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac }, + { 0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 }, + { 0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 }, + { 0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 }, + { 0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 }, + { 0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 }, + { 0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 }, + { 0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 }, + { 0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 }, + { 0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 }, + { 0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 }, + { 0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c }, + { 0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 }, + { 0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 }, + { 0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c }, + { 0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 }, + { 0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 }, + { 0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 }, + { 0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 }, + { 0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 }, + { 0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac }, + { 0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 }, + { 0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 }, + { 0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 }, + { 0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 }, + { 0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 }, + { 0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad }, + { 0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 }, + { 0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 }, + { 0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 }, + { 0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 }, + { 0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 }, + { 0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd }, + { 0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 }, + { 0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 }, + { 0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 }, + { 0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 }, + { 0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca }, + { 0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce }, + { 0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 }, + { 0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 }, + { 0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda }, + { 0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 }, + { 0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb }, + { 0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf }, + { 0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 }, + { 0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 }, + { 0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, + { 0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 }, + { 0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 }, +}; + +static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffd }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffc }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + + +/* AR9271 initialization values automaticaly created: 06/04/09 */ +static const u_int32_t ar9271Modes_9271[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e }, + { 0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 }, + { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, + { 0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, + { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, + { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, + { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18 }, + { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, + { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310, 0x30002310 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, + { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 }, + { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c }, + { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, + { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, + { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, + { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, + { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, + { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, + { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, + { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, + { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, + { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, + { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, + { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, + { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, + { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, + { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, + { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, + { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, + { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, + { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, + { 0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, + { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, + { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, + { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, + { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, + { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, + { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, + { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, + { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, + { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, + { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, + { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, + { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, + { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, + { 0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, + { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, + { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, + { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, + { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, + { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, + { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, + { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, + { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, + { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, + { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, + { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, + { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, + { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, + { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, + { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, + { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, + { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, + { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, + { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, + { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, + { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, + { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, + { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, + { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, + { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, + { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, + { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, + { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, + { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, + { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, + { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, + { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, + { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, + { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, + { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, + { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, + { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, + { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, + { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, + { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, + { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, + { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, + { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, + { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, + { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, + { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, + { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, + { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, + { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, + { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, + { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, + { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, + { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, + { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, + { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, + { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, + { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, + { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, + { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, + { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, + { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, + { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, + { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, + { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, + { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, + { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, + { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, + { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, + { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, + { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, + { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, + { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, + { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, + { 0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, + { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, + { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, + { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, + { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, + { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, + { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, + { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, + { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, + { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, + { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, + { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, + { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, + { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, + { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, + { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, + { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, + { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, + { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, + { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, + { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, + { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, + { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, + { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, + { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, + { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, + { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, + { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, + { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, + { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, + { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, + { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, + { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, + { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, + { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, + { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, + { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, + { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, + { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, + { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, + { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, + { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, + { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, + { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, + { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, + { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, + { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, + { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, + { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, + { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, + { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, + { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, + { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, + { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, + { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, + { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, + { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, + { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, + { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, + { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, + { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, + { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, + { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, + { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, + { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, + { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, + { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, + { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, + { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, + { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, + { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, + { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, +}; + +static const u_int32_t ar9271Common_9271[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020045 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00004060, 0x00000000 }, + { 0x00004064, 0x00000000 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x00000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080b0, 0x00000000 }, + { 0x000080b4, 0x00000000 }, + { 0x000080b8, 0x00000000 }, + { 0x000080bc, 0x00000000 }, + { 0x000080c0, 0x2a80001a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04810 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c0, 0x00000000 }, + { 0x000081d0, 0x0000320a }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008264, 0xa8a00010 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x0000829c, 0x00000000 }, + { 0x00008300, 0x00000040 }, + { 0x00008314, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000001 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00ff0000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x00010380 }, + { 0x00008344, 0x00581043 }, + { 0x00007010, 0x00000030 }, + { 0x00007034, 0x00000002 }, + { 0x00007038, 0x000004c2 }, + { 0x00007800, 0x00140000 }, + { 0x00007804, 0x0e4548d8 }, + { 0x00007808, 0x54214514 }, + { 0x0000780c, 0x02025820 }, + { 0x00007810, 0x71c0d388 }, + { 0x00007814, 0x924934a8 }, + { 0x0000781c, 0x00000000 }, + { 0x00007828, 0x66964300 }, + { 0x0000782c, 0x8db6d961 }, + { 0x00007830, 0x8db6d96c }, + { 0x00007834, 0x6140008b }, + { 0x0000783c, 0x72ee0a72 }, + { 0x00007840, 0xbbfffffc }, + { 0x00007844, 0x000c0db6 }, + { 0x00007848, 0x6db61b6f }, + { 0x0000784c, 0x6d9b66db }, + { 0x00007850, 0x6d8c6dba }, + { 0x00007854, 0x00040000 }, + { 0x00007858, 0xdb003012 }, + { 0x0000785c, 0x04924914 }, + { 0x00007860, 0x21084210 }, + { 0x00007864, 0xf7d7ffde }, + { 0x00007868, 0xc2034080 }, + { 0x00007870, 0x10142c00 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xafe68e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009940, 0x14750604 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x0108ecff }, + { 0x00009968, 0x000003ce }, + { 0x00009970, 0x192bb514 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x2def0400 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099f0, 0x00000000 }, + { 0x0000a208, 0x803e68c8 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x00206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a244, 0x00000000 }, + { 0x0000a248, 0xfffffffc }, + { 0x0000a24c, 0x00000000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0ccb5380 }, + { 0x0000a25c, 0x15151501 }, + { 0x0000a260, 0xdfa90f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0ebae9e6 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x0000a3ec, 0x00f70081 }, + { 0x0000a3f0, 0x01036a2f }, + { 0x0000a3f4, 0x00000000 }, + { 0x0000d270, 0x0d820820 }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, +}; + +static const u_int32_t ar9271Common_normal_cck_fir_coeff_9271[][2] = { + { 0x0000a1f4, 0x00fffeff }, + { 0x0000a1f8, 0x00f5f9ff }, + { 0x0000a1fc, 0xb79f6427 }, +}; + +static const u_int32_t ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = { + { 0x0000a1f4, 0x00000000 }, + { 0x0000a1f8, 0xefff0301 }, + { 0x0000a1fc, 0xca9228ee }, +}; + +static const u_int32_t ar9271Modes_9271_1_0_only[][6] = { + { 0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311 }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, +}; + +static const u_int32_t ar9271Modes_9271_ANI_reg[][6] = { + { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, + { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, + { 0x0000986c, 0x06903881, 0x06903881, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, + { 0x0000a208, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8 }, + { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, +}; + +static const u_int32_t ar9271Modes_normal_power_tx_gain_9271[][6] = { + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000 }, + { 0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007838, 0x00000029, 0x00000029, 0x00000029, 0x00000029, 0x00000029 }, + { 0x00007824, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff }, + { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, + { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, + { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652 }, + { 0x0000a278, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd }, + { 0x0000a27c, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd }, + { 0x0000a394, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd }, + { 0x0000a398, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd }, + { 0x0000a3dc, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd }, + { 0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd }, +}; + +static const u_int32_t ar9271Modes_high_power_tx_gain_9271[][6] = { + { 0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0001b240, 0x0001b240, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x0001d241, 0x0001d241, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0001f600, 0x0001f600, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00022800, 0x00022800, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00026802, 0x00026802, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0002b805, 0x0002b805, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0002ea41, 0x0002ea41, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x00038b00, 0x00038b00, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0003ab40, 0x0003ab40, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0003cd80, 0x0003cd80, 0x00000000 }, + { 0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007838, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b }, + { 0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff }, + { 0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba, 0x08609eb6 }, + { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a212652, 0x0a212652, 0x0a22a652 }, + { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063, 0x05018063 }, + { 0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63 }, + { 0x0000a398, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063 }, + { 0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63 }, + { 0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063 }, +}; + +#endif /* INITVALS_9002_10_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 601dbf79cc0d..8949debeb0fe 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -20,7 +20,9 @@ #include "hw.h" #include "hw-ops.h" #include "rc.h" -#include "initvals.h" +#include "ar5008_initvals.h" +#include "ar9001_initvals.h" +#include "ar9002_initvals.h" #define ATH9K_CLOCK_RATE_CCK 22 #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h deleted file mode 100644 index 455e9d3b3f13..000000000000 --- a/drivers/net/wireless/ath/ath9k/initvals.h +++ /dev/null @@ -1,7200 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -static const u32 ar5416Modes[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, - { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, - { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, - { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de }, - { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, - { 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e }, - { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 }, - { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, - { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 }, - { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b }, - { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, - { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, - { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, - { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, - { 0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, - { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, - { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, - { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, - { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, - { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, - { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, - { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, - { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, - { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, - { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, - { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, - { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, - { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, - { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u32 ar5416Common[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00007010, 0x00000000 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x000080c0, 0x2a82301a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8000010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x00008300, 0x00000000 }, - { 0x00008304, 0x00000000 }, - { 0x00008308, 0x00000000 }, - { 0x0000830c, 0x00000000 }, - { 0x00008310, 0x00000000 }, - { 0x00008314, 0x00000000 }, - { 0x00008318, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00070000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xad848e19 }, - { 0x00009810, 0x7d14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x00009840, 0x206a002e }, - { 0x0000984c, 0x1284233c }, - { 0x00009854, 0x00000859 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x05100000 }, - { 0x0000a920, 0x05100000 }, - { 0x0000b920, 0x05100000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280b212 }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5d50e188 }, - { 0x00009958, 0x00081fff }, - { 0x0000c95c, 0x004b6a8e }, - { 0x0000c968, 0x000003ce }, - { 0x00009970, 0x190fb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x001fff00 }, - { 0x000099ac, 0x00000000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000200 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x000000aa }, - { 0x000099fc, 0x00001042 }, - { 0x00009b00, 0x00000000 }, - { 0x00009b04, 0x00000001 }, - { 0x00009b08, 0x00000002 }, - { 0x00009b0c, 0x00000003 }, - { 0x00009b10, 0x00000004 }, - { 0x00009b14, 0x00000005 }, - { 0x00009b18, 0x00000008 }, - { 0x00009b1c, 0x00000009 }, - { 0x00009b20, 0x0000000a }, - { 0x00009b24, 0x0000000b }, - { 0x00009b28, 0x0000000c }, - { 0x00009b2c, 0x0000000d }, - { 0x00009b30, 0x00000010 }, - { 0x00009b34, 0x00000011 }, - { 0x00009b38, 0x00000012 }, - { 0x00009b3c, 0x00000013 }, - { 0x00009b40, 0x00000014 }, - { 0x00009b44, 0x00000015 }, - { 0x00009b48, 0x00000018 }, - { 0x00009b4c, 0x00000019 }, - { 0x00009b50, 0x0000001a }, - { 0x00009b54, 0x0000001b }, - { 0x00009b58, 0x0000001c }, - { 0x00009b5c, 0x0000001d }, - { 0x00009b60, 0x00000020 }, - { 0x00009b64, 0x00000021 }, - { 0x00009b68, 0x00000022 }, - { 0x00009b6c, 0x00000023 }, - { 0x00009b70, 0x00000024 }, - { 0x00009b74, 0x00000025 }, - { 0x00009b78, 0x00000028 }, - { 0x00009b7c, 0x00000029 }, - { 0x00009b80, 0x0000002a }, - { 0x00009b84, 0x0000002b }, - { 0x00009b88, 0x0000002c }, - { 0x00009b8c, 0x0000002d }, - { 0x00009b90, 0x00000030 }, - { 0x00009b94, 0x00000031 }, - { 0x00009b98, 0x00000032 }, - { 0x00009b9c, 0x00000033 }, - { 0x00009ba0, 0x00000034 }, - { 0x00009ba4, 0x00000035 }, - { 0x00009ba8, 0x00000035 }, - { 0x00009bac, 0x00000035 }, - { 0x00009bb0, 0x00000035 }, - { 0x00009bb4, 0x00000035 }, - { 0x00009bb8, 0x00000035 }, - { 0x00009bbc, 0x00000035 }, - { 0x00009bc0, 0x00000035 }, - { 0x00009bc4, 0x00000035 }, - { 0x00009bc8, 0x00000035 }, - { 0x00009bcc, 0x00000035 }, - { 0x00009bd0, 0x00000035 }, - { 0x00009bd4, 0x00000035 }, - { 0x00009bd8, 0x00000035 }, - { 0x00009bdc, 0x00000035 }, - { 0x00009be0, 0x00000035 }, - { 0x00009be4, 0x00000035 }, - { 0x00009be8, 0x00000035 }, - { 0x00009bec, 0x00000035 }, - { 0x00009bf0, 0x00000035 }, - { 0x00009bf4, 0x00000035 }, - { 0x00009bf8, 0x00000010 }, - { 0x00009bfc, 0x0000001a }, - { 0x0000a210, 0x40806333 }, - { 0x0000a214, 0x00106c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x018830c6 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x00000bb5 }, - { 0x0000a22c, 0x00000011 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889af }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000001 }, - { 0x0000a250, 0x0000a000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cc75380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0e79e5c6 }, - { 0x0000b26c, 0x0e79e5c6 }, - { 0x0000c26c, 0x0e79e5c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x051701ce }, - { 0x0000a338, 0x00000000 }, - { 0x0000a33c, 0x00000000 }, - { 0x0000a340, 0x00000000 }, - { 0x0000a344, 0x00000000 }, - { 0x0000a348, 0x3fffffff }, - { 0x0000a34c, 0x3fffffff }, - { 0x0000a350, 0x3fffffff }, - { 0x0000a354, 0x0003ffff }, - { 0x0000a358, 0x79a8aa1f }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x08000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, -}; - -static const u32 ar5416Bank0[][2] = { - { 0x000098b0, 0x1e5795e5 }, - { 0x000098e0, 0x02008020 }, -}; - -static const u32 ar5416BB_RfGain[][3] = { - { 0x00009a00, 0x00000000, 0x00000000 }, - { 0x00009a04, 0x00000040, 0x00000040 }, - { 0x00009a08, 0x00000080, 0x00000080 }, - { 0x00009a0c, 0x000001a1, 0x00000141 }, - { 0x00009a10, 0x000001e1, 0x00000181 }, - { 0x00009a14, 0x00000021, 0x000001c1 }, - { 0x00009a18, 0x00000061, 0x00000001 }, - { 0x00009a1c, 0x00000168, 0x00000041 }, - { 0x00009a20, 0x000001a8, 0x000001a8 }, - { 0x00009a24, 0x000001e8, 0x000001e8 }, - { 0x00009a28, 0x00000028, 0x00000028 }, - { 0x00009a2c, 0x00000068, 0x00000068 }, - { 0x00009a30, 0x00000189, 0x000000a8 }, - { 0x00009a34, 0x000001c9, 0x00000169 }, - { 0x00009a38, 0x00000009, 0x000001a9 }, - { 0x00009a3c, 0x00000049, 0x000001e9 }, - { 0x00009a40, 0x00000089, 0x00000029 }, - { 0x00009a44, 0x00000170, 0x00000069 }, - { 0x00009a48, 0x000001b0, 0x00000190 }, - { 0x00009a4c, 0x000001f0, 0x000001d0 }, - { 0x00009a50, 0x00000030, 0x00000010 }, - { 0x00009a54, 0x00000070, 0x00000050 }, - { 0x00009a58, 0x00000191, 0x00000090 }, - { 0x00009a5c, 0x000001d1, 0x00000151 }, - { 0x00009a60, 0x00000011, 0x00000191 }, - { 0x00009a64, 0x00000051, 0x000001d1 }, - { 0x00009a68, 0x00000091, 0x00000011 }, - { 0x00009a6c, 0x000001b8, 0x00000051 }, - { 0x00009a70, 0x000001f8, 0x00000198 }, - { 0x00009a74, 0x00000038, 0x000001d8 }, - { 0x00009a78, 0x00000078, 0x00000018 }, - { 0x00009a7c, 0x00000199, 0x00000058 }, - { 0x00009a80, 0x000001d9, 0x00000098 }, - { 0x00009a84, 0x00000019, 0x00000159 }, - { 0x00009a88, 0x00000059, 0x00000199 }, - { 0x00009a8c, 0x00000099, 0x000001d9 }, - { 0x00009a90, 0x000000d9, 0x00000019 }, - { 0x00009a94, 0x000000f9, 0x00000059 }, - { 0x00009a98, 0x000000f9, 0x00000099 }, - { 0x00009a9c, 0x000000f9, 0x000000d9 }, - { 0x00009aa0, 0x000000f9, 0x000000f9 }, - { 0x00009aa4, 0x000000f9, 0x000000f9 }, - { 0x00009aa8, 0x000000f9, 0x000000f9 }, - { 0x00009aac, 0x000000f9, 0x000000f9 }, - { 0x00009ab0, 0x000000f9, 0x000000f9 }, - { 0x00009ab4, 0x000000f9, 0x000000f9 }, - { 0x00009ab8, 0x000000f9, 0x000000f9 }, - { 0x00009abc, 0x000000f9, 0x000000f9 }, - { 0x00009ac0, 0x000000f9, 0x000000f9 }, - { 0x00009ac4, 0x000000f9, 0x000000f9 }, - { 0x00009ac8, 0x000000f9, 0x000000f9 }, - { 0x00009acc, 0x000000f9, 0x000000f9 }, - { 0x00009ad0, 0x000000f9, 0x000000f9 }, - { 0x00009ad4, 0x000000f9, 0x000000f9 }, - { 0x00009ad8, 0x000000f9, 0x000000f9 }, - { 0x00009adc, 0x000000f9, 0x000000f9 }, - { 0x00009ae0, 0x000000f9, 0x000000f9 }, - { 0x00009ae4, 0x000000f9, 0x000000f9 }, - { 0x00009ae8, 0x000000f9, 0x000000f9 }, - { 0x00009aec, 0x000000f9, 0x000000f9 }, - { 0x00009af0, 0x000000f9, 0x000000f9 }, - { 0x00009af4, 0x000000f9, 0x000000f9 }, - { 0x00009af8, 0x000000f9, 0x000000f9 }, - { 0x00009afc, 0x000000f9, 0x000000f9 }, -}; - -static const u32 ar5416Bank1[][2] = { - { 0x000098b0, 0x02108421 }, - { 0x000098ec, 0x00000008 }, -}; - -static const u32 ar5416Bank2[][2] = { - { 0x000098b0, 0x0e73ff17 }, - { 0x000098e0, 0x00000420 }, -}; - -static const u32 ar5416Bank3[][3] = { - { 0x000098f0, 0x01400018, 0x01c00018 }, -}; - -static const u32 ar5416Bank6[][3] = { - - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x004210a2, 0x004210a2 }, - { 0x0000989c, 0x0014008f, 0x0014008f }, - { 0x0000989c, 0x00c40003, 0x00c40003 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000f1, 0x000000f1 }, - { 0x0000989c, 0x00002081, 0x00002081 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank6TPC[][3] = { - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x00423022, 0x00423022 }, - { 0x0000989c, 0x201400df, 0x201400df }, - { 0x0000989c, 0x00c40002, 0x00c40002 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000e1, 0x000000e1 }, - { 0x0000989c, 0x00007081, 0x00007081 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank7[][2] = { - { 0x0000989c, 0x00000500 }, - { 0x0000989c, 0x00000800 }, - { 0x000098cc, 0x0000000e }, -}; - -static const u32 ar5416Addac[][2] = { - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000003 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x0000000c }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000030 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000060 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000058 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x000098cc, 0x00000000 }, -}; - -static const u32 ar5416Modes_9100[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, - { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 }, - { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec86d2e, 0x7ec84d2e, 0x7ec82d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, - { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, - { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, - { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, - { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a11, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009940, 0x00754604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204 }, - { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, - { 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e }, - { 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff }, -#ifdef TB243 - { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, - { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, - { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 }, -#else - { 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, - { 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, - { 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, - { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, -#endif - { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00 }, - { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, - { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, - { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, - { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, - { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, - { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, - { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, - { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, - { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, - { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, - { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, - { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, - { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, - { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u32 ar5416Common_9100[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00020010, 0x00000003 }, - { 0x00020038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00004000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x000080c0, 0x2a82301a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0x00000000 }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d0, 0x00003210 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x00008300, 0x00000000 }, - { 0x00008304, 0x00000000 }, - { 0x00008308, 0x00000000 }, - { 0x0000830c, 0x00000000 }, - { 0x00008310, 0x00000000 }, - { 0x00008314, 0x00000000 }, - { 0x00008318, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00000000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xad848e19 }, - { 0x00009810, 0x7d14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x00009840, 0x206a01ae }, - { 0x0000984c, 0x1284233c }, - { 0x00009854, 0x00000859 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x05100000 }, - { 0x0000a920, 0x05100000 }, - { 0x0000b920, 0x05100000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280b212 }, - { 0x0000994c, 0x00020028 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x0000c968, 0x000003ce }, - { 0x00009970, 0x190fb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x006f0000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000200 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099fc, 0x00001042 }, - { 0x00009b00, 0x00000000 }, - { 0x00009b04, 0x00000001 }, - { 0x00009b08, 0x00000002 }, - { 0x00009b0c, 0x00000003 }, - { 0x00009b10, 0x00000004 }, - { 0x00009b14, 0x00000005 }, - { 0x00009b18, 0x00000008 }, - { 0x00009b1c, 0x00000009 }, - { 0x00009b20, 0x0000000a }, - { 0x00009b24, 0x0000000b }, - { 0x00009b28, 0x0000000c }, - { 0x00009b2c, 0x0000000d }, - { 0x00009b30, 0x00000010 }, - { 0x00009b34, 0x00000011 }, - { 0x00009b38, 0x00000012 }, - { 0x00009b3c, 0x00000013 }, - { 0x00009b40, 0x00000014 }, - { 0x00009b44, 0x00000015 }, - { 0x00009b48, 0x00000018 }, - { 0x00009b4c, 0x00000019 }, - { 0x00009b50, 0x0000001a }, - { 0x00009b54, 0x0000001b }, - { 0x00009b58, 0x0000001c }, - { 0x00009b5c, 0x0000001d }, - { 0x00009b60, 0x00000020 }, - { 0x00009b64, 0x00000021 }, - { 0x00009b68, 0x00000022 }, - { 0x00009b6c, 0x00000023 }, - { 0x00009b70, 0x00000024 }, - { 0x00009b74, 0x00000025 }, - { 0x00009b78, 0x00000028 }, - { 0x00009b7c, 0x00000029 }, - { 0x00009b80, 0x0000002a }, - { 0x00009b84, 0x0000002b }, - { 0x00009b88, 0x0000002c }, - { 0x00009b8c, 0x0000002d }, - { 0x00009b90, 0x00000030 }, - { 0x00009b94, 0x00000031 }, - { 0x00009b98, 0x00000032 }, - { 0x00009b9c, 0x00000033 }, - { 0x00009ba0, 0x00000034 }, - { 0x00009ba4, 0x00000035 }, - { 0x00009ba8, 0x00000035 }, - { 0x00009bac, 0x00000035 }, - { 0x00009bb0, 0x00000035 }, - { 0x00009bb4, 0x00000035 }, - { 0x00009bb8, 0x00000035 }, - { 0x00009bbc, 0x00000035 }, - { 0x00009bc0, 0x00000035 }, - { 0x00009bc4, 0x00000035 }, - { 0x00009bc8, 0x00000035 }, - { 0x00009bcc, 0x00000035 }, - { 0x00009bd0, 0x00000035 }, - { 0x00009bd4, 0x00000035 }, - { 0x00009bd8, 0x00000035 }, - { 0x00009bdc, 0x00000035 }, - { 0x00009be0, 0x00000035 }, - { 0x00009be4, 0x00000035 }, - { 0x00009be8, 0x00000035 }, - { 0x00009bec, 0x00000035 }, - { 0x00009bf0, 0x00000035 }, - { 0x00009bf4, 0x00000035 }, - { 0x00009bf8, 0x00000010 }, - { 0x00009bfc, 0x0000001a }, - { 0x0000a210, 0x40806333 }, - { 0x0000a214, 0x00106c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x018830c6 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x001a0bb5 }, - { 0x0000a22c, 0x00000000 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889ae }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000001 }, - { 0x0000a250, 0x0000a000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cc75380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000001 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, - { 0x0000c26c, 0x0ebae9c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce }, - { 0x0000a338, 0x00000000 }, - { 0x0000a33c, 0x00000000 }, - { 0x0000a340, 0x00000000 }, - { 0x0000a344, 0x00000000 }, - { 0x0000a348, 0x3fffffff }, - { 0x0000a34c, 0x3fffffff }, - { 0x0000a350, 0x3fffffff }, - { 0x0000a354, 0x0003ffff }, - { 0x0000a358, 0x79a8aa33 }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, -}; - -static const u32 ar5416Bank0_9100[][2] = { - { 0x000098b0, 0x1e5795e5 }, - { 0x000098e0, 0x02008020 }, -}; - -static const u32 ar5416BB_RfGain_9100[][3] = { - { 0x00009a00, 0x00000000, 0x00000000 }, - { 0x00009a04, 0x00000040, 0x00000040 }, - { 0x00009a08, 0x00000080, 0x00000080 }, - { 0x00009a0c, 0x000001a1, 0x00000141 }, - { 0x00009a10, 0x000001e1, 0x00000181 }, - { 0x00009a14, 0x00000021, 0x000001c1 }, - { 0x00009a18, 0x00000061, 0x00000001 }, - { 0x00009a1c, 0x00000168, 0x00000041 }, - { 0x00009a20, 0x000001a8, 0x000001a8 }, - { 0x00009a24, 0x000001e8, 0x000001e8 }, - { 0x00009a28, 0x00000028, 0x00000028 }, - { 0x00009a2c, 0x00000068, 0x00000068 }, - { 0x00009a30, 0x00000189, 0x000000a8 }, - { 0x00009a34, 0x000001c9, 0x00000169 }, - { 0x00009a38, 0x00000009, 0x000001a9 }, - { 0x00009a3c, 0x00000049, 0x000001e9 }, - { 0x00009a40, 0x00000089, 0x00000029 }, - { 0x00009a44, 0x00000170, 0x00000069 }, - { 0x00009a48, 0x000001b0, 0x00000190 }, - { 0x00009a4c, 0x000001f0, 0x000001d0 }, - { 0x00009a50, 0x00000030, 0x00000010 }, - { 0x00009a54, 0x00000070, 0x00000050 }, - { 0x00009a58, 0x00000191, 0x00000090 }, - { 0x00009a5c, 0x000001d1, 0x00000151 }, - { 0x00009a60, 0x00000011, 0x00000191 }, - { 0x00009a64, 0x00000051, 0x000001d1 }, - { 0x00009a68, 0x00000091, 0x00000011 }, - { 0x00009a6c, 0x000001b8, 0x00000051 }, - { 0x00009a70, 0x000001f8, 0x00000198 }, - { 0x00009a74, 0x00000038, 0x000001d8 }, - { 0x00009a78, 0x00000078, 0x00000018 }, - { 0x00009a7c, 0x00000199, 0x00000058 }, - { 0x00009a80, 0x000001d9, 0x00000098 }, - { 0x00009a84, 0x00000019, 0x00000159 }, - { 0x00009a88, 0x00000059, 0x00000199 }, - { 0x00009a8c, 0x00000099, 0x000001d9 }, - { 0x00009a90, 0x000000d9, 0x00000019 }, - { 0x00009a94, 0x000000f9, 0x00000059 }, - { 0x00009a98, 0x000000f9, 0x00000099 }, - { 0x00009a9c, 0x000000f9, 0x000000d9 }, - { 0x00009aa0, 0x000000f9, 0x000000f9 }, - { 0x00009aa4, 0x000000f9, 0x000000f9 }, - { 0x00009aa8, 0x000000f9, 0x000000f9 }, - { 0x00009aac, 0x000000f9, 0x000000f9 }, - { 0x00009ab0, 0x000000f9, 0x000000f9 }, - { 0x00009ab4, 0x000000f9, 0x000000f9 }, - { 0x00009ab8, 0x000000f9, 0x000000f9 }, - { 0x00009abc, 0x000000f9, 0x000000f9 }, - { 0x00009ac0, 0x000000f9, 0x000000f9 }, - { 0x00009ac4, 0x000000f9, 0x000000f9 }, - { 0x00009ac8, 0x000000f9, 0x000000f9 }, - { 0x00009acc, 0x000000f9, 0x000000f9 }, - { 0x00009ad0, 0x000000f9, 0x000000f9 }, - { 0x00009ad4, 0x000000f9, 0x000000f9 }, - { 0x00009ad8, 0x000000f9, 0x000000f9 }, - { 0x00009adc, 0x000000f9, 0x000000f9 }, - { 0x00009ae0, 0x000000f9, 0x000000f9 }, - { 0x00009ae4, 0x000000f9, 0x000000f9 }, - { 0x00009ae8, 0x000000f9, 0x000000f9 }, - { 0x00009aec, 0x000000f9, 0x000000f9 }, - { 0x00009af0, 0x000000f9, 0x000000f9 }, - { 0x00009af4, 0x000000f9, 0x000000f9 }, - { 0x00009af8, 0x000000f9, 0x000000f9 }, - { 0x00009afc, 0x000000f9, 0x000000f9 }, -}; - -static const u32 ar5416Bank1_9100[][2] = { - { 0x000098b0, 0x02108421}, - { 0x000098ec, 0x00000008}, -}; - -static const u32 ar5416Bank2_9100[][2] = { - { 0x000098b0, 0x0e73ff17}, - { 0x000098e0, 0x00000420}, -}; - -static const u32 ar5416Bank3_9100[][3] = { - { 0x000098f0, 0x01400018, 0x01c00018 }, -}; - -static const u32 ar5416Bank6_9100[][3] = { - - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x004210a2, 0x004210a2 }, - { 0x0000989c, 0x0014000f, 0x0014000f }, - { 0x0000989c, 0x00c40002, 0x00c40002 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x000180d6, 0x000180d6 }, - { 0x0000989c, 0x0000c0aa, 0x0000c0aa }, - { 0x0000989c, 0x000000b1, 0x000000b1 }, - { 0x0000989c, 0x00002000, 0x00002000 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - - -static const u32 ar5416Bank6TPC_9100[][3] = { - - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x00423022, 0x00423022 }, - { 0x0000989c, 0x2014008f, 0x2014008f }, - { 0x0000989c, 0x00c40002, 0x00c40002 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000e1, 0x000000e1 }, - { 0x0000989c, 0x00007080, 0x00007080 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank7_9100[][2] = { - { 0x0000989c, 0x00000500 }, - { 0x0000989c, 0x00000800 }, - { 0x000098cc, 0x0000000e }, -}; - -static const u32 ar5416Addac_9100[][2] = { - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000010 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000015 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x000098cc, 0x00000000 }, -}; - -static const u32 ar5416Modes_9160[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, - { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 }, - { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, - { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, - { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, - { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, - { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, - { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, - { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, - { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, - { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, - { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, - { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, - { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, - { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, - { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, - { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, - { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, - { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, - { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, - { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, - { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, - { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, - { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, - { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, - { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, - { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u32 ar5416Common_9160[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00007010, 0x00000020 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x000080c0, 0x2a82301a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d0, 0x00003210 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x00008300, 0x00000000 }, - { 0x00008304, 0x00000000 }, - { 0x00008308, 0x00000000 }, - { 0x0000830c, 0x00000000 }, - { 0x00008310, 0x00000000 }, - { 0x00008314, 0x00000000 }, - { 0x00008318, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xad848e19 }, - { 0x00009810, 0x7d14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x00009840, 0x206a01ae }, - { 0x0000984c, 0x1284233c }, - { 0x00009854, 0x00000859 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x05100000 }, - { 0x0000a920, 0x05100000 }, - { 0x0000b920, 0x05100000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280b212 }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x2108ecff }, - { 0x00009940, 0x00750604 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x00009970, 0x190fb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x006f0000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000200 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099fc, 0x00001042 }, - { 0x00009b00, 0x00000000 }, - { 0x00009b04, 0x00000001 }, - { 0x00009b08, 0x00000002 }, - { 0x00009b0c, 0x00000003 }, - { 0x00009b10, 0x00000004 }, - { 0x00009b14, 0x00000005 }, - { 0x00009b18, 0x00000008 }, - { 0x00009b1c, 0x00000009 }, - { 0x00009b20, 0x0000000a }, - { 0x00009b24, 0x0000000b }, - { 0x00009b28, 0x0000000c }, - { 0x00009b2c, 0x0000000d }, - { 0x00009b30, 0x00000010 }, - { 0x00009b34, 0x00000011 }, - { 0x00009b38, 0x00000012 }, - { 0x00009b3c, 0x00000013 }, - { 0x00009b40, 0x00000014 }, - { 0x00009b44, 0x00000015 }, - { 0x00009b48, 0x00000018 }, - { 0x00009b4c, 0x00000019 }, - { 0x00009b50, 0x0000001a }, - { 0x00009b54, 0x0000001b }, - { 0x00009b58, 0x0000001c }, - { 0x00009b5c, 0x0000001d }, - { 0x00009b60, 0x00000020 }, - { 0x00009b64, 0x00000021 }, - { 0x00009b68, 0x00000022 }, - { 0x00009b6c, 0x00000023 }, - { 0x00009b70, 0x00000024 }, - { 0x00009b74, 0x00000025 }, - { 0x00009b78, 0x00000028 }, - { 0x00009b7c, 0x00000029 }, - { 0x00009b80, 0x0000002a }, - { 0x00009b84, 0x0000002b }, - { 0x00009b88, 0x0000002c }, - { 0x00009b8c, 0x0000002d }, - { 0x00009b90, 0x00000030 }, - { 0x00009b94, 0x00000031 }, - { 0x00009b98, 0x00000032 }, - { 0x00009b9c, 0x00000033 }, - { 0x00009ba0, 0x00000034 }, - { 0x00009ba4, 0x00000035 }, - { 0x00009ba8, 0x00000035 }, - { 0x00009bac, 0x00000035 }, - { 0x00009bb0, 0x00000035 }, - { 0x00009bb4, 0x00000035 }, - { 0x00009bb8, 0x00000035 }, - { 0x00009bbc, 0x00000035 }, - { 0x00009bc0, 0x00000035 }, - { 0x00009bc4, 0x00000035 }, - { 0x00009bc8, 0x00000035 }, - { 0x00009bcc, 0x00000035 }, - { 0x00009bd0, 0x00000035 }, - { 0x00009bd4, 0x00000035 }, - { 0x00009bd8, 0x00000035 }, - { 0x00009bdc, 0x00000035 }, - { 0x00009be0, 0x00000035 }, - { 0x00009be4, 0x00000035 }, - { 0x00009be8, 0x00000035 }, - { 0x00009bec, 0x00000035 }, - { 0x00009bf0, 0x00000035 }, - { 0x00009bf4, 0x00000035 }, - { 0x00009bf8, 0x00000010 }, - { 0x00009bfc, 0x0000001a }, - { 0x0000a210, 0x40806333 }, - { 0x0000a214, 0x00106c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x018830c6 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x001a0bb5 }, - { 0x0000a22c, 0x00000000 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889af }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000001 }, - { 0x0000a250, 0x0000e000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cc75380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000001 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, - { 0x0000c26c, 0x0ebae9c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce }, - { 0x0000a338, 0x00000000 }, - { 0x0000a33c, 0x00000000 }, - { 0x0000a340, 0x00000000 }, - { 0x0000a344, 0x00000000 }, - { 0x0000a348, 0x3fffffff }, - { 0x0000a34c, 0x3fffffff }, - { 0x0000a350, 0x3fffffff }, - { 0x0000a354, 0x0003ffff }, - { 0x0000a358, 0x79bfaa03 }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, -}; - -static const u32 ar5416Bank0_9160[][2] = { - { 0x000098b0, 0x1e5795e5 }, - { 0x000098e0, 0x02008020 }, -}; - -static const u32 ar5416BB_RfGain_9160[][3] = { - { 0x00009a00, 0x00000000, 0x00000000 }, - { 0x00009a04, 0x00000040, 0x00000040 }, - { 0x00009a08, 0x00000080, 0x00000080 }, - { 0x00009a0c, 0x000001a1, 0x00000141 }, - { 0x00009a10, 0x000001e1, 0x00000181 }, - { 0x00009a14, 0x00000021, 0x000001c1 }, - { 0x00009a18, 0x00000061, 0x00000001 }, - { 0x00009a1c, 0x00000168, 0x00000041 }, - { 0x00009a20, 0x000001a8, 0x000001a8 }, - { 0x00009a24, 0x000001e8, 0x000001e8 }, - { 0x00009a28, 0x00000028, 0x00000028 }, - { 0x00009a2c, 0x00000068, 0x00000068 }, - { 0x00009a30, 0x00000189, 0x000000a8 }, - { 0x00009a34, 0x000001c9, 0x00000169 }, - { 0x00009a38, 0x00000009, 0x000001a9 }, - { 0x00009a3c, 0x00000049, 0x000001e9 }, - { 0x00009a40, 0x00000089, 0x00000029 }, - { 0x00009a44, 0x00000170, 0x00000069 }, - { 0x00009a48, 0x000001b0, 0x00000190 }, - { 0x00009a4c, 0x000001f0, 0x000001d0 }, - { 0x00009a50, 0x00000030, 0x00000010 }, - { 0x00009a54, 0x00000070, 0x00000050 }, - { 0x00009a58, 0x00000191, 0x00000090 }, - { 0x00009a5c, 0x000001d1, 0x00000151 }, - { 0x00009a60, 0x00000011, 0x00000191 }, - { 0x00009a64, 0x00000051, 0x000001d1 }, - { 0x00009a68, 0x00000091, 0x00000011 }, - { 0x00009a6c, 0x000001b8, 0x00000051 }, - { 0x00009a70, 0x000001f8, 0x00000198 }, - { 0x00009a74, 0x00000038, 0x000001d8 }, - { 0x00009a78, 0x00000078, 0x00000018 }, - { 0x00009a7c, 0x00000199, 0x00000058 }, - { 0x00009a80, 0x000001d9, 0x00000098 }, - { 0x00009a84, 0x00000019, 0x00000159 }, - { 0x00009a88, 0x00000059, 0x00000199 }, - { 0x00009a8c, 0x00000099, 0x000001d9 }, - { 0x00009a90, 0x000000d9, 0x00000019 }, - { 0x00009a94, 0x000000f9, 0x00000059 }, - { 0x00009a98, 0x000000f9, 0x00000099 }, - { 0x00009a9c, 0x000000f9, 0x000000d9 }, - { 0x00009aa0, 0x000000f9, 0x000000f9 }, - { 0x00009aa4, 0x000000f9, 0x000000f9 }, - { 0x00009aa8, 0x000000f9, 0x000000f9 }, - { 0x00009aac, 0x000000f9, 0x000000f9 }, - { 0x00009ab0, 0x000000f9, 0x000000f9 }, - { 0x00009ab4, 0x000000f9, 0x000000f9 }, - { 0x00009ab8, 0x000000f9, 0x000000f9 }, - { 0x00009abc, 0x000000f9, 0x000000f9 }, - { 0x00009ac0, 0x000000f9, 0x000000f9 }, - { 0x00009ac4, 0x000000f9, 0x000000f9 }, - { 0x00009ac8, 0x000000f9, 0x000000f9 }, - { 0x00009acc, 0x000000f9, 0x000000f9 }, - { 0x00009ad0, 0x000000f9, 0x000000f9 }, - { 0x00009ad4, 0x000000f9, 0x000000f9 }, - { 0x00009ad8, 0x000000f9, 0x000000f9 }, - { 0x00009adc, 0x000000f9, 0x000000f9 }, - { 0x00009ae0, 0x000000f9, 0x000000f9 }, - { 0x00009ae4, 0x000000f9, 0x000000f9 }, - { 0x00009ae8, 0x000000f9, 0x000000f9 }, - { 0x00009aec, 0x000000f9, 0x000000f9 }, - { 0x00009af0, 0x000000f9, 0x000000f9 }, - { 0x00009af4, 0x000000f9, 0x000000f9 }, - { 0x00009af8, 0x000000f9, 0x000000f9 }, - { 0x00009afc, 0x000000f9, 0x000000f9 }, -}; - -static const u32 ar5416Bank1_9160[][2] = { - { 0x000098b0, 0x02108421 }, - { 0x000098ec, 0x00000008 }, -}; - -static const u32 ar5416Bank2_9160[][2] = { - { 0x000098b0, 0x0e73ff17 }, - { 0x000098e0, 0x00000420 }, -}; - -static const u32 ar5416Bank3_9160[][3] = { - { 0x000098f0, 0x01400018, 0x01c00018 }, -}; - -static const u32 ar5416Bank6_9160[][3] = { - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x004210a2, 0x004210a2 }, - { 0x0000989c, 0x0014008f, 0x0014008f }, - { 0x0000989c, 0x00c40003, 0x00c40003 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000f1, 0x000000f1 }, - { 0x0000989c, 0x00002081, 0x00002081 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank6TPC_9160[][3] = { - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x00423022, 0x00423022 }, - { 0x0000989c, 0x2014008f, 0x2014008f }, - { 0x0000989c, 0x00c40002, 0x00c40002 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000e1, 0x000000e1 }, - { 0x0000989c, 0x00007080, 0x00007080 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank7_9160[][2] = { - { 0x0000989c, 0x00000500 }, - { 0x0000989c, 0x00000800 }, - { 0x000098cc, 0x0000000e }, -}; - -static u32 ar5416Addac_9160[][2] = { - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000018 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000019 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000003 }, - {0x0000989c, 0x00000008 }, - {0x0000989c, 0x00000000 }, - {0x000098cc, 0x00000000 }, -}; - -static u32 ar5416Addac_91601_1[][2] = { - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000018 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000019 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x000098cc, 0x00000000 }, -}; - -/* XXX 9280 1 */ -static const u32 ar9280Modes_9280[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 }, - { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, - { 0x00009848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 }, - { 0x0000a848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 }, - { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, - { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, - { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d20, 0x00049d20, 0x00049d18 }, - { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190 }, - { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 }, - { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, - { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, - { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, - { 0x0000c9b8, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a }, - { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009a00, 0x00008184, 0x00008184, 0x00000214, 0x00000214, 0x00000214 }, - { 0x00009a04, 0x00008188, 0x00008188, 0x00000218, 0x00000218, 0x00000218 }, - { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000224, 0x00000224, 0x00000224 }, - { 0x00009a0c, 0x00008190, 0x00008190, 0x00000228, 0x00000228, 0x00000228 }, - { 0x00009a10, 0x00008194, 0x00008194, 0x0000022c, 0x0000022c, 0x0000022c }, - { 0x00009a14, 0x00008200, 0x00008200, 0x00000230, 0x00000230, 0x00000230 }, - { 0x00009a18, 0x00008204, 0x00008204, 0x000002a4, 0x000002a4, 0x000002a4 }, - { 0x00009a1c, 0x00008208, 0x00008208, 0x000002a8, 0x000002a8, 0x000002a8 }, - { 0x00009a20, 0x0000820c, 0x0000820c, 0x000002ac, 0x000002ac, 0x000002ac }, - { 0x00009a24, 0x00008210, 0x00008210, 0x000002b0, 0x000002b0, 0x000002b0 }, - { 0x00009a28, 0x00008214, 0x00008214, 0x000002b4, 0x000002b4, 0x000002b4 }, - { 0x00009a2c, 0x00008280, 0x00008280, 0x000002b8, 0x000002b8, 0x000002b8 }, - { 0x00009a30, 0x00008284, 0x00008284, 0x00000390, 0x00000390, 0x00000390 }, - { 0x00009a34, 0x00008288, 0x00008288, 0x00000394, 0x00000394, 0x00000394 }, - { 0x00009a38, 0x0000828c, 0x0000828c, 0x00000398, 0x00000398, 0x00000398 }, - { 0x00009a3c, 0x00008290, 0x00008290, 0x00000334, 0x00000334, 0x00000334 }, - { 0x00009a40, 0x00008300, 0x00008300, 0x00000338, 0x00000338, 0x00000338 }, - { 0x00009a44, 0x00008304, 0x00008304, 0x000003ac, 0x000003ac, 0x000003ac }, - { 0x00009a48, 0x00008308, 0x00008308, 0x000003b0, 0x000003b0, 0x000003b0 }, - { 0x00009a4c, 0x0000830c, 0x0000830c, 0x000003b4, 0x000003b4, 0x000003b4 }, - { 0x00009a50, 0x00008310, 0x00008310, 0x000003b8, 0x000003b8, 0x000003b8 }, - { 0x00009a54, 0x00008314, 0x00008314, 0x000003a5, 0x000003a5, 0x000003a5 }, - { 0x00009a58, 0x00008380, 0x00008380, 0x000003a9, 0x000003a9, 0x000003a9 }, - { 0x00009a5c, 0x00008384, 0x00008384, 0x000003ad, 0x000003ad, 0x000003ad }, - { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, - { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, - { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, - { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, - { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, - { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, - { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, - { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, - { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, - { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, - { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, - { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, - { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, - { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, - { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, - { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, - { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, - { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, - { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, - { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, - { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, - { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, - { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, - { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, - { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, - { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, - { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, - { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, - { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, - { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, - { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, - { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, - { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, - { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, - { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, - { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, - { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, - { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, - { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, - { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, - { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, - { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, - { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, - { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, - { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, - { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, - { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, - { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, - { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, - { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, - { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, - { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, - { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, - { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, - { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, - { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, - { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, - { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, - { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, - { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, - { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, - { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, - { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, - { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, - { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, - { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, - { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, - { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, - { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, - { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, - { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, - { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, - { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, - { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, - { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, - { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, - { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 }, - { 0x0000a20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 }, - { 0x0000b20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, - { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, - { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, - { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, - { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, - { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, - { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, - { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, - { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, - { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, - { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, - { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, - { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, - { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, - { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, - { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, - { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, - { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, - { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, - { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, - { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, - { 0x0000784c, 0x0e4f048c, 0x0e4f048c, 0x0e4d048c, 0x0e4d048c, 0x0e4d048c }, - { 0x00007854, 0x12031828, 0x12031828, 0x12035828, 0x12035828, 0x12035828 }, - { 0x00007870, 0x807ec400, 0x807ec400, 0x807ec000, 0x807ec000, 0x807ec000 }, - { 0x0000788c, 0x00010000, 0x00010000, 0x00110000, 0x00110000, 0x00110000 }, -}; - -static const u32 ar9280Common_9280[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00007010, 0x00000033 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a82301a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0x00000000 }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d0, 0x00003210 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x00008300, 0x00000000 }, - { 0x00008304, 0x00000000 }, - { 0x00008308, 0x00000000 }, - { 0x0000830c, 0x00000000 }, - { 0x00008310, 0x00000000 }, - { 0x00008314, 0x00000000 }, - { 0x00008318, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00000000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00008344, 0x00000000 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xaf268e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x00009840, 0x206a01ae }, - { 0x0000984c, 0x0040233c }, - { 0x0000a84c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x0000a920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0xe250a51e }, - { 0x00009958, 0x3388ffff }, - { 0x00009940, 0x00781204 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x0000c968, 0x000003ce }, - { 0x00009970, 0x190fb514 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x006f00c4 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099fc, 0x00001042 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x40206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x23277200 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889af }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000001 }, - { 0x0000a250, 0x001da000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cdbd380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce }, - { 0x0000a358, 0x7999aa0f }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f38081 }, - { 0x00007800, 0x00040000 }, - { 0x00007804, 0xdb005012 }, - { 0x00007808, 0x04924914 }, - { 0x0000780c, 0x21084210 }, - { 0x00007810, 0x6d801300 }, - { 0x00007814, 0x0019beff }, - { 0x00007818, 0x07e40000 }, - { 0x0000781c, 0x00492000 }, - { 0x00007820, 0x92492480 }, - { 0x00007824, 0x00040000 }, - { 0x00007828, 0xdb005012 }, - { 0x0000782c, 0x04924914 }, - { 0x00007830, 0x21084210 }, - { 0x00007834, 0x6d801300 }, - { 0x00007838, 0x0019beff }, - { 0x0000783c, 0x07e40000 }, - { 0x00007840, 0x00492000 }, - { 0x00007844, 0x92492480 }, - { 0x00007848, 0x00120000 }, - { 0x00007850, 0x54214514 }, - { 0x00007858, 0x92592692 }, - { 0x00007860, 0x52802000 }, - { 0x00007864, 0x0a8e370e }, - { 0x00007868, 0xc0102850 }, - { 0x0000786c, 0x812d4000 }, - { 0x00007874, 0x001b6db0 }, - { 0x00007878, 0x00376b63 }, - { 0x0000787c, 0x06db6db6 }, - { 0x00007880, 0x006d8000 }, - { 0x00007884, 0xffeffffe }, - { 0x00007888, 0xffeffffe }, - { 0x00007890, 0x00060aeb }, - { 0x00007894, 0x5a108000 }, - { 0x00007898, 0x2a850160 }, -}; - -/* XXX 9280 2 */ -static const u32 ar9280Modes_9280_2[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, - { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, - { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, - { 0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, - { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e }, - { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, - { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 }, - { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, - { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, - { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, - { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, - { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c }, - { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, - { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, - { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000, 0x13c88000 }, - { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, - { 0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000, 0x0c000000 }, - { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 }, -}; - -static const u32 ar9280Common_9280_2[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00007010, 0x00000033 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00008344, 0x00481043 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafa68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x0000a84c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x01002310 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x0000a920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x2108ecff }, - { 0x00009940, 0x14750604 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x00009970, 0x190fb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x006f0000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x000099fc, 0x00001042 }, - { 0x0000a208, 0x803e4788 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x40206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x233f7180 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cdbd380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0e79e5c6 }, - { 0x0000b26c, 0x0e79e5c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x00007800, 0x00040000 }, - { 0x00007804, 0xdb005012 }, - { 0x00007808, 0x04924914 }, - { 0x0000780c, 0x21084210 }, - { 0x00007810, 0x6d801300 }, - { 0x00007818, 0x07e41000 }, - { 0x00007824, 0x00040000 }, - { 0x00007828, 0xdb005012 }, - { 0x0000782c, 0x04924914 }, - { 0x00007830, 0x21084210 }, - { 0x00007834, 0x6d801300 }, - { 0x0000783c, 0x07e40000 }, - { 0x00007848, 0x00100000 }, - { 0x0000784c, 0x773f0567 }, - { 0x00007850, 0x54214514 }, - { 0x00007854, 0x12035828 }, - { 0x00007858, 0x9259269a }, - { 0x00007860, 0x52802000 }, - { 0x00007864, 0x0a8e370e }, - { 0x00007868, 0xc0102850 }, - { 0x0000786c, 0x812d4000 }, - { 0x00007870, 0x807ec400 }, - { 0x00007874, 0x001b6db0 }, - { 0x00007878, 0x00376b63 }, - { 0x0000787c, 0x06db6db6 }, - { 0x00007880, 0x006d8000 }, - { 0x00007884, 0xffeffffe }, - { 0x00007888, 0xffeffffe }, - { 0x0000788c, 0x00010000 }, - { 0x00007890, 0x02060aeb }, - { 0x00007898, 0x2a850160 }, -}; - -static const u32 ar9280Modes_fast_clock_9280_2[][3] = { - { 0x00001030, 0x00000268, 0x000004d0 }, - { 0x00001070, 0x0000018c, 0x00000318 }, - { 0x000010b0, 0x00000fd0, 0x00001fa0 }, - { 0x00008014, 0x044c044c, 0x08980898 }, - { 0x0000801c, 0x148ec02b, 0x148ec057 }, - { 0x00008318, 0x000044c0, 0x00008980 }, - { 0x00009820, 0x02020200, 0x02020200 }, - { 0x00009824, 0x01000f0f, 0x01000f0f }, - { 0x00009828, 0x0b020001, 0x0b020001 }, - { 0x00009834, 0x00000f0f, 0x00000f0f }, - { 0x00009844, 0x03721821, 0x03721821 }, - { 0x00009914, 0x00000898, 0x00001130 }, - { 0x00009918, 0x0000000b, 0x00000016 }, -}; - -static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = { - { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, - { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, - { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, - { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, - { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, - { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, - { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, - { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, - { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, - { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, - { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, - { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, - { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, - { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, - { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, - { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, - { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, - { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, - { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, - { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, - { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, - { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, - { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, - { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, - { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, - { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, - { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, - { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, - { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, - { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, - { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, - { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, - { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, - { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, - { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, - { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, - { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, - { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, - { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, - { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, - { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, - { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, - { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, - { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, - { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, - { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, - { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, - { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, - { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10 }, - { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b14, 0x00008b14, 0x00008b14 }, - { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b01, 0x00008b01, 0x00008b01 }, - { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b05, 0x00008b05, 0x00008b05 }, - { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b09, 0x00008b09, 0x00008b09 }, - { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b0d, 0x00008b0d, 0x00008b0d }, - { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b11, 0x00008b11, 0x00008b11 }, - { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b15, 0x00008b15, 0x00008b15 }, - { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008b02, 0x00008b02, 0x00008b02 }, - { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008b06, 0x00008b06, 0x00008b06 }, - { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008b0a, 0x00008b0a, 0x00008b0a }, - { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008b0e, 0x00008b0e, 0x00008b0e }, - { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008b12, 0x00008b12, 0x00008b12 }, - { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008b16, 0x00008b16, 0x00008b16 }, - { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008b03, 0x00008b03, 0x00008b03 }, - { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008b07, 0x00008b07, 0x00008b07 }, - { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008b0b, 0x00008b0b, 0x00008b0b }, - { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008b0f, 0x00008b0f, 0x00008b0f }, - { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008b13, 0x00008b13, 0x00008b13 }, - { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008b17, 0x00008b17, 0x00008b17 }, - { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008b23, 0x00008b23, 0x00008b23 }, - { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008b27, 0x00008b27, 0x00008b27 }, - { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008b2b, 0x00008b2b, 0x00008b2b }, - { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008b2f, 0x00008b2f, 0x00008b2f }, - { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008b33, 0x00008b33, 0x00008b33 }, - { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008b37, 0x00008b37, 0x00008b37 }, - { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008b43, 0x00008b43, 0x00008b43 }, - { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008b47, 0x00008b47, 0x00008b47 }, - { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008b4b, 0x00008b4b, 0x00008b4b }, - { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008b4f, 0x00008b4f, 0x00008b4f }, - { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008b53, 0x00008b53, 0x00008b53 }, - { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008b57, 0x00008b57, 0x00008b57 }, - { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 }, - { 0x0000a848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 }, -}; - -static const u32 ar9280Modes_original_rxgain_9280_2[][6] = { - { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, - { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, - { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, - { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, - { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, - { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, - { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, - { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, - { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, - { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, - { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, - { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, - { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, - { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, - { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, - { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, - { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, - { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, - { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, - { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, - { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, - { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, - { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, - { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, - { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, - { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, - { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, - { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, - { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, - { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, - { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, - { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, - { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, - { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, - { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, - { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, - { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, - { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, - { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, - { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, - { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, - { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, - { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, - { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, - { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, - { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, - { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, - { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, - { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, - { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, - { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, - { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, - { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, - { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, - { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, - { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, - { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, - { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, - { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, - { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, - { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, - { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, - { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, - { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, - { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, - { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, - { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, - { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, - { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, - { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, - { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, - { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, - { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, - { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, - { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, - { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, - { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, - { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, - { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, - { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, - { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, - { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, - { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, - { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, - { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, - { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, - { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, - { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, - { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, - { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, - { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, - { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, - { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, - { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, - { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, - { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, - { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, - { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, - { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, - { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, - { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, -}; - -static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = { - { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, - { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, - { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, - { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, - { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, - { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, - { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, - { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, - { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, - { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, - { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, - { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, - { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, - { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, - { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, - { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, - { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, - { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, - { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, - { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, - { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, - { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, - { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, - { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, - { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, - { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, - { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, - { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, - { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, - { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, - { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, - { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, - { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, - { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, - { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, - { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, - { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, - { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, - { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, - { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, - { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, - { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, - { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, - { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, - { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, - { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, - { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, - { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, - { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, - { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, - { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, - { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, - { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, - { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, - { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, - { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, - { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, - { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, - { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310 }, - { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314 }, - { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320 }, - { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324 }, - { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328 }, - { 0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c }, - { 0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330 }, - { 0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334 }, - { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321 }, - { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325 }, - { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329 }, - { 0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d }, - { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331 }, - { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335 }, - { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322 }, - { 0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326 }, - { 0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a }, - { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e }, - { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332 }, - { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336 }, - { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323 }, - { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327 }, - { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b }, - { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f }, - { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333 }, - { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337 }, - { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343 }, - { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347 }, - { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b }, - { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f }, - { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353 }, - { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357 }, - { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a }, - { 0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a }, -}; - -static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = { - { 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, - { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce }, - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 }, - { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 }, - { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010 }, - { 0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012 }, - { 0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014 }, - { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a }, - { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 }, - { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, - { 0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411 }, - { 0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413 }, - { 0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811 }, - { 0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813 }, - { 0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14 }, - { 0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50 }, - { 0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c }, - { 0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a }, - { 0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92 }, - { 0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 }, - { 0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 }, - { 0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 }, - { 0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5 }, - { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, - { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, - { 0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, - { 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, - { 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, - { 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, -}; - -static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = { - { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, - { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, - { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, - { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, - { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, - { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, - { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, - { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, - { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, - { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, - { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, - { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, - { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, - { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, - { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, - { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, - { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, - { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, - { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, - { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, - { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, - { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, - { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, - { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, - { 0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, - { 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, - { 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, - { 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, -}; - -static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffc }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffd }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -/* AR9285 Revsion 10*/ -static const u_int32_t ar9285Modes_9285[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020, 0x037216a0 }, - { 0x00009848, 0x00001066, 0x00001066, 0x0000004e, 0x0000004e, 0x00001059 }, - { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, - { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e, 0x3139605e }, - { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 }, - { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, - { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1020, 0xdfbc1020, 0xdfbc1010 }, - { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099b8, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c }, - { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 }, - { 0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 }, - { 0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 }, - { 0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 }, - { 0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 }, - { 0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 }, - { 0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 }, - { 0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, - { 0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114, 0x00000000 }, - { 0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 }, - { 0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 }, - { 0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 }, - { 0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 }, - { 0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 }, - { 0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 }, - { 0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 }, - { 0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 }, - { 0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 }, - { 0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284, 0x00000000 }, - { 0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288, 0x00000000 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220, 0x00000000 }, - { 0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 }, - { 0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 }, - { 0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304, 0x00000000 }, - { 0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 }, - { 0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 }, - { 0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380, 0x00000000 }, - { 0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384, 0x00000000 }, - { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, - { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, - { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, - { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, - { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, - { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04, 0x00000000 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 }, - { 0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 }, - { 0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c, 0x00000000 }, - { 0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80, 0x00000000 }, - { 0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84, 0x00000000 }, - { 0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88, 0x00000000 }, - { 0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c, 0x00000000 }, - { 0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90, 0x00000000 }, - { 0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80, 0x00000000 }, - { 0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, - { 0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 }, - { 0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c, 0x00000000 }, - { 0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90, 0x00000000 }, - { 0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c, 0x00000000 }, - { 0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310, 0x00000000 }, - { 0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 }, - { 0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 }, - { 0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324, 0x00000000 }, - { 0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704, 0x00000000 }, - { 0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4, 0x00000000 }, - { 0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8, 0x00000000 }, - { 0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 }, - { 0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 }, - { 0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720, 0x00000000 }, - { 0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724, 0x00000000 }, - { 0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728, 0x00000000 }, - { 0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c, 0x00000000 }, - { 0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0, 0x00000000 }, - { 0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4, 0x00000000 }, - { 0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 }, - { 0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 }, - { 0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4, 0x00000000 }, - { 0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 }, - { 0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 }, - { 0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 }, - { 0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad, 0x00000000 }, - { 0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 }, - { 0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 }, - { 0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9, 0x00000000 }, - { 0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5, 0x00000000 }, - { 0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 }, - { 0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 }, - { 0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5, 0x00000000 }, - { 0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 }, - { 0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 }, - { 0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 }, - { 0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 }, - { 0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 }, - { 0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 }, - { 0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 }, - { 0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7, 0x00000000 }, - { 0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 }, - { 0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf, 0x00000000 }, - { 0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7, 0x00000000 }, - { 0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 }, - { 0x0000aa04, 0x00000000, 0x00000000, 0x00068080, 0x00068080, 0x00000000 }, - { 0x0000aa08, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 }, - { 0x0000aa0c, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 }, - { 0x0000aa10, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 }, - { 0x0000aa14, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 }, - { 0x0000aa18, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 }, - { 0x0000aa1c, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 }, - { 0x0000aa20, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 }, - { 0x0000aa24, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, - { 0x0000aa28, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, - { 0x0000aa2c, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 }, - { 0x0000aa30, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 }, - { 0x0000aa34, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 }, - { 0x0000aa38, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 }, - { 0x0000aa3c, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 }, - { 0x0000aa40, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 }, - { 0x0000aa44, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 }, - { 0x0000aa48, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 }, - { 0x0000aa4c, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac, 0x00000000 }, - { 0x0000aa54, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c, 0x00000000 }, - { 0x0000aa58, 0x00000000, 0x00000000, 0x00068224, 0x00068224, 0x00000000 }, - { 0x0000aa5c, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 }, - { 0x0000aa60, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 }, - { 0x0000aa64, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 }, - { 0x0000aa68, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 }, - { 0x0000aa6c, 0x00000000, 0x00000000, 0x00068310, 0x00068310, 0x00000000 }, - { 0x0000aa70, 0x00000000, 0x00000000, 0x00068788, 0x00068788, 0x00000000 }, - { 0x0000aa74, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c, 0x00000000 }, - { 0x0000aa78, 0x00000000, 0x00000000, 0x00068790, 0x00068790, 0x00000000 }, - { 0x0000aa7c, 0x00000000, 0x00000000, 0x00068794, 0x00068794, 0x00000000 }, - { 0x0000aa80, 0x00000000, 0x00000000, 0x00068798, 0x00068798, 0x00000000 }, - { 0x0000aa84, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c, 0x00000000 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89, 0x00000000 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d, 0x00000000 }, - { 0x0000aa90, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91, 0x00000000 }, - { 0x0000aa94, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95, 0x00000000 }, - { 0x0000aa98, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99, 0x00000000 }, - { 0x0000aa9c, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5, 0x00000000 }, - { 0x0000aaa0, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9, 0x00000000 }, - { 0x0000aaa4, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad, 0x00000000 }, - { 0x0000aaa8, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c, 0x00000000 }, - { 0x0000aaac, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10, 0x00000000 }, - { 0x0000aab0, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14, 0x00000000 }, - { 0x0000aab4, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, - { 0x0000aab8, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, - { 0x0000aabc, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 }, - { 0x0000aac0, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380, 0x00000000 }, - { 0x0000aac4, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 }, - { 0x0000aac8, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 }, - { 0x0000aacc, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c, 0x00000000 }, - { 0x0000aad0, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394, 0x00000000 }, - { 0x0000aad4, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798, 0x00000000 }, - { 0x0000aad8, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c, 0x00000000 }, - { 0x0000aadc, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 }, - { 0x0000aae0, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 }, - { 0x0000aae4, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718, 0x00000000 }, - { 0x0000aae8, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705, 0x00000000 }, - { 0x0000aaec, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709, 0x00000000 }, - { 0x0000aaf0, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d, 0x00000000 }, - { 0x0000aaf4, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711, 0x00000000 }, - { 0x0000aaf8, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715, 0x00000000 }, - { 0x0000aafc, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719, 0x00000000 }, - { 0x0000ab00, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4, 0x00000000 }, - { 0x0000ab04, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 }, - { 0x0000ab08, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 }, - { 0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 }, - { 0x0000ab10, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 }, - { 0x0000ab14, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 }, - { 0x0000ab18, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc, 0x00000000 }, - { 0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1, 0x00000000 }, - { 0x0000ab20, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 }, - { 0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 }, - { 0x0000ab28, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 }, - { 0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 }, - { 0x0000ab30, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd, 0x00000000 }, - { 0x0000ab34, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 }, - { 0x0000ab38, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd, 0x00000000 }, - { 0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 }, - { 0x0000ab40, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 }, - { 0x0000ab44, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2, 0x00000000 }, - { 0x0000ab48, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 }, - { 0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 }, - { 0x0000ab50, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 }, - { 0x0000ab54, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 }, - { 0x0000ab58, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 }, - { 0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 }, - { 0x0000ab60, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 }, - { 0x0000ab64, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab68, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, - { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000, 0x0001f000 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a250, 0x001ff000, 0x001ff000, 0x001ca000, 0x001ca000, 0x001da000 }, - { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652, 0x0a82a652 }, - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0002c89a, 0x0002c89a, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0002e89b, 0x0002e89b, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x0003089c, 0x0003089c, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0003289d, 0x0003289d, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0003489e, 0x0003489e, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x000388de, 0x000388de, 0x00000000 }, - { 0x0000a338, 0x00000000, 0x00000000, 0x0003b91e, 0x0003b91e, 0x00000000 }, - { 0x0000a33c, 0x00000000, 0x00000000, 0x0003d95e, 0x0003d95e, 0x00000000 }, - { 0x0000a340, 0x00000000, 0x00000000, 0x000419df, 0x000419df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, -}; - -static const u_int32_t ar9285Common_9285[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020045 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00007010, 0x00000031 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x00000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0x00000000 }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081d0, 0x00003210 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000001 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00000000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x00010380 }, - { 0x00008344, 0x00481043 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafe68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x01002310 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009940, 0x14750604 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x2108ecff }, - { 0x00009968, 0x000003ce }, - { 0x00009970, 0x1927b515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x2def0a00 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x0000a208, 0x803e6788 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x00206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x00000000 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a244, 0x00000000 }, - { 0x0000a248, 0xfffffffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0ccb5380 }, - { 0x0000a25c, 0x15151501 }, - { 0x0000a260, 0xdfa90f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9e6 }, - { 0x0000d270, 0x0d820820 }, - { 0x0000a278, 0x39ce739c }, - { 0x0000a27c, 0x050e039c }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x39ce739c }, - { 0x0000a398, 0x0000039c }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x39ce739c }, - { 0x0000a3e0, 0x0000039c }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x00007800, 0x00140000 }, - { 0x00007804, 0x0e4548d8 }, - { 0x00007808, 0x54214514 }, - { 0x0000780c, 0x02025820 }, - { 0x00007810, 0x71c0d388 }, - { 0x00007814, 0x924934a8 }, - { 0x0000781c, 0x00000000 }, - { 0x00007820, 0x00000c04 }, - { 0x00007824, 0x00d86fff }, - { 0x00007828, 0x26d2491b }, - { 0x0000782c, 0x6e36d97b }, - { 0x00007830, 0xedb6d96c }, - { 0x00007834, 0x71400086 }, - { 0x00007838, 0xfac68800 }, - { 0x0000783c, 0x0001fffe }, - { 0x00007840, 0xffeb1a20 }, - { 0x00007844, 0x000c0db6 }, - { 0x00007848, 0x6db61b6f }, - { 0x0000784c, 0x6d9b66db }, - { 0x00007850, 0x6d8c6dba }, - { 0x00007854, 0x00040000 }, - { 0x00007858, 0xdb003012 }, - { 0x0000785c, 0x04924914 }, - { 0x00007860, 0x21084210 }, - { 0x00007864, 0xf7d7ffde }, - { 0x00007868, 0xc2034080 }, - { 0x0000786c, 0x48609eb4 }, - { 0x00007870, 0x10142c00 }, -}; - -static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffd }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffc }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -/* AR9285 v1_2 PCI Register Writes. Created: 04/13/09 */ -static const u_int32_t ar9285Modes_9285_1_2[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 }, - { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, - { 0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, - { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, - { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, - { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 }, - { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, - { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 }, - { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c }, - { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, - { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, - { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, - { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, - { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, - { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, - { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, - { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, - { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, - { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, - { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, - { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, - { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, - { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, - { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, - { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, - { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, - { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, - { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, - { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, - { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, - { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, - { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, - { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, - { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, - { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, - { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, - { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, - { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, - { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, - { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, - { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, - { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, - { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, - { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, - { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, - { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, - { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, - { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, - { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, - { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, - { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, - { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, - { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, - { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, - { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, - { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, - { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, - { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, - { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, - { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, - { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, - { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, - { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, - { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, - { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, - { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, - { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, - { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, - { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, - { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, - { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, - { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, - { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, - { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, - { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, - { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, - { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, - { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, - { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, - { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, - { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, - { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, - { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, - { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, - { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, - { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, - { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, - { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, - { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, - { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, - { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, - { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, - { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, - { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, - { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, - { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, - { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, - { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, - { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, - { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, - { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, - { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, - { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, - { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, - { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, - { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, - { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, - { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, - { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, - { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, - { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, - { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, - { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, - { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, - { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, - { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, - { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, - { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, - { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, - { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, - { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, - { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, - { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, - { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, - { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, - { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, - { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, - { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, - { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, - { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, - { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, - { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, - { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, - { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, - { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, - { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, - { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, - { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, - { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, - { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, - { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, - { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, - { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, - { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, - { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, - { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, - { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, - { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, - { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, - { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, - { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, - { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, - { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, - { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, - { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, - { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, - { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, - { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, - { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, - { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, - { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, - { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, - { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, - { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, - { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, - { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, - { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, - { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, - { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, - { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, - { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, - { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, - { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, - { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, - { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, - { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, - { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, - { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, - { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, - { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, -}; - -static const u_int32_t ar9285Common_9285_1_2[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020045 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00007010, 0x00000031 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x00000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04810 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081d0, 0x0000320a }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0x88a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000001 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x00010380 }, - { 0x00008344, 0x00481043 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafe68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x01002310 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009940, 0x14750604 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x2108ecff }, - { 0x00009968, 0x000003ce }, - { 0x00009970, 0x192bb514 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x2def0400 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x0000a208, 0x803e68c8 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x00206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x00000000 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a244, 0x00000000 }, - { 0x0000a248, 0xfffffffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0ccb5380 }, - { 0x0000a25c, 0x15151501 }, - { 0x0000a260, 0xdfa90f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9e6 }, - { 0x0000d270, 0x0d820820 }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x00007800, 0x00140000 }, - { 0x00007804, 0x0e4548d8 }, - { 0x00007808, 0x54214514 }, - { 0x0000780c, 0x02025830 }, - { 0x00007810, 0x71c0d388 }, - { 0x0000781c, 0x00000000 }, - { 0x00007824, 0x00d86fff }, - { 0x0000782c, 0x6e36d97b }, - { 0x00007834, 0x71400087 }, - { 0x00007844, 0x000c0db6 }, - { 0x00007848, 0x6db6246f }, - { 0x0000784c, 0x6d9b66db }, - { 0x00007850, 0x6d8c6dba }, - { 0x00007854, 0x00040000 }, - { 0x00007858, 0xdb003012 }, - { 0x0000785c, 0x04924914 }, - { 0x00007860, 0x21084210 }, - { 0x00007864, 0xf7d7ffde }, - { 0x00007868, 0xc2034080 }, - { 0x00007870, 0x10142c00 }, -}; - -static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, - { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, - { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, - { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 }, - { 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b }, - { 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e }, - { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, - { 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe }, - { 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 }, - { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, - { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, - { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, - { 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 }, - { 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, - { 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, - { 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, - { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, -}; - -static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, - { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, - { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, - { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 }, - { 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b }, - { 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e }, - { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 }, - { 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe }, - { 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 }, - { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, - { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, - { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, - { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, - { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, - { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, - { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, - { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, - { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, -}; - -static const u_int32_t ar9285Modes_XE2_0_normal_power[][6] = { - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, - { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, - { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, - { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 }, - { 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b }, - { 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6dbae }, - { 0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441 }, - { 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe }, - { 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c }, - { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, - { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, - { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, - { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, - { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, - { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, - { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, - { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, - { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, -}; - -static const u_int32_t ar9285Modes_XE2_0_high_power[][6] = { - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, - { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, - { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, - { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 }, - { 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b }, - { 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e }, - { 0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443 }, - { 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe }, - { 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c }, - { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, - { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, - { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, - { 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 }, - { 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, - { 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, - { 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, - { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, -}; - -static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffd }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffc }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -/* AR9287 Revision 10 */ -static const u_int32_t ar9287Modes_9287_1_0[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, - { 0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a }, - { 0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e }, - { 0x00009828, 0x00000000, 0x00000000, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0 }, - { 0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, - { 0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e }, - { 0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18 }, - { 0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010 }, - { 0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 }, - { 0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210 }, - { 0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce }, - { 0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c }, - { 0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444 }, - { 0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, - { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u_int32_t ar9287Common_9287_1_0[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00007010, 0x00000033 }, - { 0x00007020, 0x00000000 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x18487320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d4, 0x00000000 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x000000ff }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00008344, 0x01c81043 }, - { 0x00008360, 0xffffffff }, - { 0x00008364, 0xffffffff }, - { 0x00008368, 0x00000000 }, - { 0x00008370, 0x00000000 }, - { 0x00008374, 0x000000ff }, - { 0x00008378, 0x00000000 }, - { 0x0000837c, 0x00000000 }, - { 0x00008380, 0xffffffff }, - { 0x00008384, 0xffffffff }, - { 0x00008390, 0x0fffffff }, - { 0x00008394, 0x0fffffff }, - { 0x00008398, 0x00000000 }, - { 0x0000839c, 0x00000000 }, - { 0x000083a0, 0x00000000 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafe68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x0000a84c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x10002310 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x0000a920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009930, 0x00000000 }, - { 0x0000a930, 0x00000000 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x0108ecff }, - { 0x00009940, 0x14750604 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x00009970, 0x990bb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x0c6f0000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099c4, 0x06336f77 }, - { 0x000099c8, 0x6af65329 }, - { 0x000099cc, 0x08f186c8 }, - { 0x000099d0, 0x00046384 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x000099fc, 0x00001042 }, - { 0x0000a1f4, 0x00fffeff }, - { 0x0000a1f8, 0x00f5f9ff }, - { 0x0000a1fc, 0xb79f6427 }, - { 0x0000a208, 0x803e4788 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x40206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x233f7180 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889af }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00000000 }, - { 0x0000a248, 0xfffffffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cdbd380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a264, 0x00418a11 }, - { 0x0000b264, 0x00418a11 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0e79e5c6 }, - { 0x0000b26c, 0x0e79e5c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000b398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x0000a3f0, 0x01036a1e }, - { 0x0000a3f4, 0x00000000 }, - { 0x0000b3f4, 0x00000000 }, - { 0x0000a7d8, 0x00000001 }, - { 0x00007800, 0x00000800 }, - { 0x00007804, 0x6c35ffb0 }, - { 0x00007808, 0x6db6c000 }, - { 0x0000780c, 0x6db6cb30 }, - { 0x00007810, 0x6db6cb6c }, - { 0x00007814, 0x0501e200 }, - { 0x00007818, 0x0094128d }, - { 0x0000781c, 0x976ee392 }, - { 0x00007820, 0xf75ff6fc }, - { 0x00007824, 0x00040000 }, - { 0x00007828, 0xdb003012 }, - { 0x0000782c, 0x04924914 }, - { 0x00007830, 0x21084210 }, - { 0x00007834, 0x00140000 }, - { 0x00007838, 0x0e4548d8 }, - { 0x0000783c, 0x54214514 }, - { 0x00007840, 0x02025820 }, - { 0x00007844, 0x71c0d388 }, - { 0x00007848, 0x934934a8 }, - { 0x00007850, 0x00000000 }, - { 0x00007854, 0x00000800 }, - { 0x00007858, 0x6c35ffb0 }, - { 0x0000785c, 0x6db6c000 }, - { 0x00007860, 0x6db6cb2c }, - { 0x00007864, 0x6db6cb6c }, - { 0x00007868, 0x0501e200 }, - { 0x0000786c, 0x0094128d }, - { 0x00007870, 0x976ee392 }, - { 0x00007874, 0xf75ff6fc }, - { 0x00007878, 0x00040000 }, - { 0x0000787c, 0xdb003012 }, - { 0x00007880, 0x04924914 }, - { 0x00007884, 0x21084210 }, - { 0x00007888, 0x001b6db0 }, - { 0x0000788c, 0x00376b63 }, - { 0x00007890, 0x06db6db6 }, - { 0x00007894, 0x006d8000 }, - { 0x00007898, 0x48100000 }, - { 0x0000789c, 0x00000000 }, - { 0x000078a0, 0x08000000 }, - { 0x000078a4, 0x0007ffd8 }, - { 0x000078a8, 0x0007ffd8 }, - { 0x000078ac, 0x001c0020 }, - { 0x000078b0, 0x000611eb }, - { 0x000078b4, 0x40008080 }, - { 0x000078b8, 0x2a850160 }, -}; - -static const u_int32_t ar9287Modes_tx_gain_9287_1_0[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a }, - { 0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b }, - { 0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a }, - { 0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a }, - { 0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a }, - { 0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c }, - { 0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc }, - { 0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4 }, - { 0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc }, - { 0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede }, - { 0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e }, - { 0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e }, - { 0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e }, - { 0x0000a780, 0x00000000, 0x00000000, 0x00000060, 0x00000060, 0x00000060 }, - { 0x0000a784, 0x00000000, 0x00000000, 0x00004062, 0x00004062, 0x00004062 }, - { 0x0000a788, 0x00000000, 0x00000000, 0x00008064, 0x00008064, 0x00008064 }, - { 0x0000a78c, 0x00000000, 0x00000000, 0x0000c0a4, 0x0000c0a4, 0x0000c0a4 }, - { 0x0000a790, 0x00000000, 0x00000000, 0x000100b0, 0x000100b0, 0x000100b0 }, - { 0x0000a794, 0x00000000, 0x00000000, 0x000140b2, 0x000140b2, 0x000140b2 }, - { 0x0000a798, 0x00000000, 0x00000000, 0x000180b4, 0x000180b4, 0x000180b4 }, - { 0x0000a79c, 0x00000000, 0x00000000, 0x0001c0f4, 0x0001c0f4, 0x0001c0f4 }, - { 0x0000a7a0, 0x00000000, 0x00000000, 0x00020134, 0x00020134, 0x00020134 }, - { 0x0000a7a4, 0x00000000, 0x00000000, 0x000240fe, 0x000240fe, 0x000240fe }, - { 0x0000a7a8, 0x00000000, 0x00000000, 0x0002813e, 0x0002813e, 0x0002813e }, - { 0x0000a7ac, 0x00000000, 0x00000000, 0x0002c17e, 0x0002c17e, 0x0002c17e }, - { 0x0000a7b0, 0x00000000, 0x00000000, 0x000301be, 0x000301be, 0x000301be }, - { 0x0000a7b4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7b8, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7bc, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7c0, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7c4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7c8, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7cc, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7d0, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7d4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000 }, -}; - - -static const u_int32_t ar9287Modes_rx_gain_9287_1_0[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 }, - { 0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, - { 0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 }, - { 0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c }, - { 0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 }, - { 0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 }, - { 0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 }, - { 0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c }, - { 0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 }, - { 0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 }, - { 0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 }, - { 0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c }, - { 0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 }, - { 0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 }, - { 0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 }, - { 0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 }, - { 0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 }, - { 0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac }, - { 0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 }, - { 0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 }, - { 0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 }, - { 0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 }, - { 0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c }, - { 0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 }, - { 0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 }, - { 0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 }, - { 0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c }, - { 0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 }, - { 0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 }, - { 0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 }, - { 0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c }, - { 0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 }, - { 0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 }, - { 0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 }, - { 0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 }, - { 0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 }, - { 0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c }, - { 0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 }, - { 0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 }, - { 0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 }, - { 0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c }, - { 0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 }, - { 0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 }, - { 0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 }, - { 0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 }, - { 0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 }, - { 0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 }, - { 0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c }, - { 0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 }, - { 0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 }, - { 0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 }, - { 0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 }, - { 0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 }, - { 0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac }, - { 0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 }, - { 0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 }, - { 0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 }, - { 0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 }, - { 0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 }, - { 0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 }, - { 0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 }, - { 0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 }, - { 0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 }, - { 0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 }, - { 0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c }, - { 0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 }, - { 0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 }, - { 0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c }, - { 0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 }, - { 0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 }, - { 0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 }, - { 0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 }, - { 0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 }, - { 0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac }, - { 0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 }, - { 0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 }, - { 0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 }, - { 0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 }, - { 0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 }, - { 0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad }, - { 0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 }, - { 0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 }, - { 0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 }, - { 0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 }, - { 0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 }, - { 0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd }, - { 0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 }, - { 0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 }, - { 0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 }, - { 0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 }, - { 0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca }, - { 0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce }, - { 0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 }, - { 0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 }, - { 0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda }, - { 0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 }, - { 0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb }, - { 0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf }, - { 0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 }, - { 0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 }, - { 0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 }, - { 0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, - { 0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 }, - { 0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c }, - { 0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 }, - { 0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 }, - { 0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 }, - { 0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c }, - { 0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 }, - { 0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 }, - { 0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 }, - { 0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c }, - { 0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 }, - { 0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 }, - { 0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 }, - { 0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 }, - { 0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 }, - { 0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac }, - { 0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 }, - { 0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 }, - { 0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 }, - { 0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 }, - { 0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c }, - { 0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 }, - { 0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 }, - { 0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 }, - { 0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c }, - { 0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 }, - { 0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 }, - { 0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 }, - { 0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c }, - { 0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 }, - { 0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 }, - { 0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 }, - { 0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 }, - { 0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 }, - { 0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c }, - { 0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 }, - { 0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 }, - { 0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 }, - { 0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c }, - { 0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 }, - { 0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 }, - { 0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 }, - { 0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 }, - { 0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 }, - { 0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 }, - { 0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c }, - { 0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 }, - { 0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 }, - { 0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 }, - { 0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 }, - { 0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 }, - { 0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac }, - { 0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 }, - { 0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 }, - { 0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 }, - { 0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 }, - { 0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 }, - { 0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 }, - { 0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 }, - { 0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 }, - { 0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 }, - { 0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 }, - { 0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c }, - { 0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 }, - { 0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 }, - { 0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c }, - { 0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 }, - { 0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 }, - { 0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 }, - { 0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 }, - { 0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 }, - { 0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac }, - { 0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 }, - { 0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 }, - { 0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 }, - { 0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 }, - { 0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 }, - { 0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad }, - { 0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 }, - { 0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 }, - { 0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 }, - { 0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 }, - { 0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 }, - { 0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd }, - { 0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 }, - { 0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 }, - { 0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 }, - { 0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 }, - { 0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca }, - { 0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce }, - { 0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 }, - { 0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 }, - { 0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda }, - { 0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 }, - { 0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb }, - { 0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf }, - { 0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 }, - { 0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 }, - { 0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 }, - { 0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 }, -}; - -static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_0[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffd }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_0[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffc }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -/* AR9287 Revision 11 */ - -static const u_int32_t ar9287Modes_9287_1_1[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, - { 0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a }, - { 0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e }, - { 0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001, 0x3a020001 }, - { 0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0 }, - { 0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, - { 0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e }, - { 0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18 }, - { 0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010 }, - { 0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 }, - { 0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210 }, - { 0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce }, - { 0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c }, - { 0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444 }, - { 0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, - { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u_int32_t ar9287Common_9287_1_1[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00007010, 0x00000033 }, - { 0x00007020, 0x00000000 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x18487320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d4, 0x00000000 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0x88a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x000000ff }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00008344, 0x01c81043 }, - { 0x00008360, 0xffffffff }, - { 0x00008364, 0xffffffff }, - { 0x00008368, 0x00000000 }, - { 0x00008370, 0x00000000 }, - { 0x00008374, 0x000000ff }, - { 0x00008378, 0x00000000 }, - { 0x0000837c, 0x00000000 }, - { 0x00008380, 0xffffffff }, - { 0x00008384, 0xffffffff }, - { 0x00008390, 0x0fffffff }, - { 0x00008394, 0x0fffffff }, - { 0x00008398, 0x00000000 }, - { 0x0000839c, 0x00000000 }, - { 0x000083a0, 0x00000000 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafe68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x0000a84c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x10002310 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x0000a920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009930, 0x00000000 }, - { 0x0000a930, 0x00000000 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x0108ecff }, - { 0x00009940, 0x14750604 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x00009970, 0x990bb514 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x0c6f0000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099c4, 0x06336f77 }, - { 0x000099c8, 0x6af6532f }, - { 0x000099cc, 0x08f186c8 }, - { 0x000099d0, 0x00046384 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x000099fc, 0x00001042 }, - { 0x0000a208, 0x803e4788 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x40206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x233f7180 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889af }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00000000 }, - { 0x0000a248, 0xfffffffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cdbd380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a264, 0x00418a11 }, - { 0x0000b264, 0x00418a11 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0e79e5c6 }, - { 0x0000b26c, 0x0e79e5c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000b398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x0000a3f0, 0x01036a1e }, - { 0x0000a3f4, 0x00000000 }, - { 0x0000b3f4, 0x00000000 }, - { 0x0000a7d8, 0x000003f1 }, - { 0x00007800, 0x00000800 }, - { 0x00007804, 0x6c35ffd2 }, - { 0x00007808, 0x6db6c000 }, - { 0x0000780c, 0x6db6cb30 }, - { 0x00007810, 0x6db6cb6c }, - { 0x00007814, 0x0501e200 }, - { 0x00007818, 0x0094128d }, - { 0x0000781c, 0x976ee392 }, - { 0x00007820, 0xf75ff6fc }, - { 0x00007824, 0x00040000 }, - { 0x00007828, 0xdb003012 }, - { 0x0000782c, 0x04924914 }, - { 0x00007830, 0x21084210 }, - { 0x00007834, 0x00140000 }, - { 0x00007838, 0x0e4548d8 }, - { 0x0000783c, 0x54214514 }, - { 0x00007840, 0x02025830 }, - { 0x00007844, 0x71c0d388 }, - { 0x00007848, 0x934934a8 }, - { 0x00007850, 0x00000000 }, - { 0x00007854, 0x00000800 }, - { 0x00007858, 0x6c35ffd2 }, - { 0x0000785c, 0x6db6c000 }, - { 0x00007860, 0x6db6cb30 }, - { 0x00007864, 0x6db6cb6c }, - { 0x00007868, 0x0501e200 }, - { 0x0000786c, 0x0094128d }, - { 0x00007870, 0x976ee392 }, - { 0x00007874, 0xf75ff6fc }, - { 0x00007878, 0x00040000 }, - { 0x0000787c, 0xdb003012 }, - { 0x00007880, 0x04924914 }, - { 0x00007884, 0x21084210 }, - { 0x00007888, 0x001b6db0 }, - { 0x0000788c, 0x00376b63 }, - { 0x00007890, 0x06db6db6 }, - { 0x00007894, 0x006d8000 }, - { 0x00007898, 0x48100000 }, - { 0x0000789c, 0x00000000 }, - { 0x000078a0, 0x08000000 }, - { 0x000078a4, 0x0007ffd8 }, - { 0x000078a8, 0x0007ffd8 }, - { 0x000078ac, 0x001c0020 }, - { 0x000078b0, 0x00060aeb }, - { 0x000078b4, 0x40008080 }, - { 0x000078b8, 0x2a850160 }, -}; - -/* - * For Japanese regulatory requirements, 2484 MHz requires the following three - * registers be programmed differently from the channel between 2412 and 2472 MHz. - */ -static const u_int32_t ar9287Common_normal_cck_fir_coeff_92871_1[][2] = { - { 0x0000a1f4, 0x00fffeff }, - { 0x0000a1f8, 0x00f5f9ff }, - { 0x0000a1fc, 0xb79f6427 }, -}; - -static const u_int32_t ar9287Common_japan_2484_cck_fir_coeff_92871_1[][2] = { - { 0x0000a1f4, 0x00000000 }, - { 0x0000a1f8, 0xefff0301 }, - { 0x0000a1fc, 0xca9228ee }, -}; - -static const u_int32_t ar9287Modes_tx_gain_9287_1_1[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a }, - { 0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b }, - { 0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a }, - { 0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a }, - { 0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a }, - { 0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c }, - { 0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc }, - { 0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4 }, - { 0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc }, - { 0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede }, - { 0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e }, - { 0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e }, - { 0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e }, - { 0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062, 0x00000062 }, - { 0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064, 0x00004064 }, - { 0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4, 0x000080a4 }, - { 0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa, 0x0000c0aa }, - { 0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac, 0x000100ac }, - { 0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4, 0x000140b4 }, - { 0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4, 0x000180f4 }, - { 0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134, 0x0001c134 }, - { 0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174, 0x00020174 }, - { 0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c, 0x0002417c }, - { 0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e, 0x0002817e }, - { 0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be, 0x0002c1be }, - { 0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000 }, -}; - -static const u_int32_t ar9287Modes_rx_gain_9287_1_1[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 }, - { 0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, - { 0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 }, - { 0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c }, - { 0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 }, - { 0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 }, - { 0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 }, - { 0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c }, - { 0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 }, - { 0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 }, - { 0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 }, - { 0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c }, - { 0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 }, - { 0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 }, - { 0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 }, - { 0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 }, - { 0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 }, - { 0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac }, - { 0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 }, - { 0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 }, - { 0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 }, - { 0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 }, - { 0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c }, - { 0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 }, - { 0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 }, - { 0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 }, - { 0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c }, - { 0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 }, - { 0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 }, - { 0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 }, - { 0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c }, - { 0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 }, - { 0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 }, - { 0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 }, - { 0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 }, - { 0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 }, - { 0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c }, - { 0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 }, - { 0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 }, - { 0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 }, - { 0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c }, - { 0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 }, - { 0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 }, - { 0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 }, - { 0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 }, - { 0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 }, - { 0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 }, - { 0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c }, - { 0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 }, - { 0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 }, - { 0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 }, - { 0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 }, - { 0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 }, - { 0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac }, - { 0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 }, - { 0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 }, - { 0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 }, - { 0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 }, - { 0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 }, - { 0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 }, - { 0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 }, - { 0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 }, - { 0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 }, - { 0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 }, - { 0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c }, - { 0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 }, - { 0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 }, - { 0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c }, - { 0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 }, - { 0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 }, - { 0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 }, - { 0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 }, - { 0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 }, - { 0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac }, - { 0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 }, - { 0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 }, - { 0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 }, - { 0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 }, - { 0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 }, - { 0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad }, - { 0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 }, - { 0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 }, - { 0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 }, - { 0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 }, - { 0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 }, - { 0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd }, - { 0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 }, - { 0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 }, - { 0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 }, - { 0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 }, - { 0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca }, - { 0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce }, - { 0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 }, - { 0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 }, - { 0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda }, - { 0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 }, - { 0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb }, - { 0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf }, - { 0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 }, - { 0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 }, - { 0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 }, - { 0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, - { 0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 }, - { 0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c }, - { 0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 }, - { 0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 }, - { 0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 }, - { 0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c }, - { 0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 }, - { 0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 }, - { 0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 }, - { 0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c }, - { 0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 }, - { 0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 }, - { 0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 }, - { 0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 }, - { 0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 }, - { 0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac }, - { 0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 }, - { 0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 }, - { 0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 }, - { 0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 }, - { 0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c }, - { 0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 }, - { 0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 }, - { 0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 }, - { 0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c }, - { 0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 }, - { 0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 }, - { 0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 }, - { 0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c }, - { 0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 }, - { 0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 }, - { 0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 }, - { 0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 }, - { 0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 }, - { 0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c }, - { 0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 }, - { 0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 }, - { 0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 }, - { 0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c }, - { 0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 }, - { 0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 }, - { 0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 }, - { 0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 }, - { 0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 }, - { 0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 }, - { 0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c }, - { 0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 }, - { 0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 }, - { 0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 }, - { 0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 }, - { 0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 }, - { 0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac }, - { 0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 }, - { 0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 }, - { 0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 }, - { 0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 }, - { 0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 }, - { 0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 }, - { 0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 }, - { 0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 }, - { 0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 }, - { 0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 }, - { 0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c }, - { 0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 }, - { 0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 }, - { 0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c }, - { 0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 }, - { 0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 }, - { 0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 }, - { 0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 }, - { 0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 }, - { 0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac }, - { 0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 }, - { 0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 }, - { 0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 }, - { 0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 }, - { 0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 }, - { 0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad }, - { 0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 }, - { 0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 }, - { 0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 }, - { 0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 }, - { 0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 }, - { 0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd }, - { 0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 }, - { 0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 }, - { 0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 }, - { 0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 }, - { 0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca }, - { 0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce }, - { 0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 }, - { 0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 }, - { 0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda }, - { 0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 }, - { 0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb }, - { 0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf }, - { 0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 }, - { 0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 }, - { 0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 }, - { 0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 }, -}; - -static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffd }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffc }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - - -/* AR9271 initialization values automaticaly created: 06/04/09 */ -static const u_int32_t ar9271Modes_9271[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e }, - { 0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 }, - { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, - { 0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, - { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, - { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, - { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18 }, - { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310, 0x30002310 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, - { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 }, - { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c }, - { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, - { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, - { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, - { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, - { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, - { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, - { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, - { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, - { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, - { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, - { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, - { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, - { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, - { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, - { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, - { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, - { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, - { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, - { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, - { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, - { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, - { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, - { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, - { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, - { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, - { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, - { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, - { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, - { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, - { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, - { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, - { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, - { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, - { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, - { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, - { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, - { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, - { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, - { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, - { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, - { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, - { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, - { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, - { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, - { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, - { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, - { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, - { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, - { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, - { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, - { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, - { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, - { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, - { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, - { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, - { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, - { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, - { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, - { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, - { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, - { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, - { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, - { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, - { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, - { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, - { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, - { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, - { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, - { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, - { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, - { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, - { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, - { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, - { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, - { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, - { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, - { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, - { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, - { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, - { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, - { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, - { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, - { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, - { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, - { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, - { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, - { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, - { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, - { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, - { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, - { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, - { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, - { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, - { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, - { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, - { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, - { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, - { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, - { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, - { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, - { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, - { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, - { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, - { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, - { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, - { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, - { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, - { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, - { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, - { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, - { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, - { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, - { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, - { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, - { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, - { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, - { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, - { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, - { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, - { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, - { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, - { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, - { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, - { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, - { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, - { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, - { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, - { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, - { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, - { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, - { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, - { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, - { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, - { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, - { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, - { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, - { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, - { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, - { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, - { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, - { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, - { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, - { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, - { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, - { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, - { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, - { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, - { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, - { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, - { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, - { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, - { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, - { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, - { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, - { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, - { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, - { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, - { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, - { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, - { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, - { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, - { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, - { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, - { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, - { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, - { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, - { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, - { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, - { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, - { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, - { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, -}; - -static const u_int32_t ar9271Common_9271[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020045 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x00000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080b0, 0x00000000 }, - { 0x000080b4, 0x00000000 }, - { 0x000080b8, 0x00000000 }, - { 0x000080bc, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04810 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081d0, 0x0000320a }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000001 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x00010380 }, - { 0x00008344, 0x00581043 }, - { 0x00007010, 0x00000030 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00007800, 0x00140000 }, - { 0x00007804, 0x0e4548d8 }, - { 0x00007808, 0x54214514 }, - { 0x0000780c, 0x02025820 }, - { 0x00007810, 0x71c0d388 }, - { 0x00007814, 0x924934a8 }, - { 0x0000781c, 0x00000000 }, - { 0x00007828, 0x66964300 }, - { 0x0000782c, 0x8db6d961 }, - { 0x00007830, 0x8db6d96c }, - { 0x00007834, 0x6140008b }, - { 0x0000783c, 0x72ee0a72 }, - { 0x00007840, 0xbbfffffc }, - { 0x00007844, 0x000c0db6 }, - { 0x00007848, 0x6db61b6f }, - { 0x0000784c, 0x6d9b66db }, - { 0x00007850, 0x6d8c6dba }, - { 0x00007854, 0x00040000 }, - { 0x00007858, 0xdb003012 }, - { 0x0000785c, 0x04924914 }, - { 0x00007860, 0x21084210 }, - { 0x00007864, 0xf7d7ffde }, - { 0x00007868, 0xc2034080 }, - { 0x00007870, 0x10142c00 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafe68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009940, 0x14750604 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x0108ecff }, - { 0x00009968, 0x000003ce }, - { 0x00009970, 0x192bb514 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x2def0400 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x0000a208, 0x803e68c8 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x00206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x00000000 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a244, 0x00000000 }, - { 0x0000a248, 0xfffffffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0ccb5380 }, - { 0x0000a25c, 0x15151501 }, - { 0x0000a260, 0xdfa90f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9e6 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x0000a3f0, 0x01036a2f }, - { 0x0000a3f4, 0x00000000 }, - { 0x0000d270, 0x0d820820 }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, -}; - -static const u_int32_t ar9271Common_normal_cck_fir_coeff_9271[][2] = { - { 0x0000a1f4, 0x00fffeff }, - { 0x0000a1f8, 0x00f5f9ff }, - { 0x0000a1fc, 0xb79f6427 }, -}; - -static const u_int32_t ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = { - { 0x0000a1f4, 0x00000000 }, - { 0x0000a1f8, 0xefff0301 }, - { 0x0000a1fc, 0xca9228ee }, -}; - -static const u_int32_t ar9271Modes_9271_1_0_only[][6] = { - { 0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311 }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, -}; - -static const u_int32_t ar9271Modes_9271_ANI_reg[][6] = { - { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, - { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000986c, 0x06903881, 0x06903881, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000a208, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8 }, - { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, -}; - -static const u_int32_t ar9271Modes_normal_power_tx_gain_9271[][6] = { - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000 }, - { 0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000 }, - { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, - { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, - { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x00007838, 0x00000029, 0x00000029, 0x00000029, 0x00000029, 0x00000029 }, - { 0x00007824, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff }, - { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, - { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, - { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652 }, - { 0x0000a278, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd }, - { 0x0000a27c, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd }, - { 0x0000a394, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd }, - { 0x0000a398, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd }, - { 0x0000a3dc, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd }, - { 0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd }, -}; - -static const u_int32_t ar9271Modes_high_power_tx_gain_9271[][6] = { - { 0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x0001b240, 0x0001b240, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x0001d241, 0x0001d241, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0001f600, 0x0001f600, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00022800, 0x00022800, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x00026802, 0x00026802, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0002b805, 0x0002b805, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0002ea41, 0x0002ea41, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x00038b00, 0x00038b00, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0003ab40, 0x0003ab40, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0003cd80, 0x0003cd80, 0x00000000 }, - { 0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000 }, - { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, - { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, - { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x00007838, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b }, - { 0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff }, - { 0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba, 0x08609eb6 }, - { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a212652, 0x0a212652, 0x0a22a652 }, - { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, - { 0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063, 0x05018063 }, - { 0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63 }, - { 0x0000a398, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063 }, - { 0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63 }, - { 0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063 }, -}; -- cgit v1.2.3 From 13ce3e997c8a63269e49f1b6c239035d79bb18e8 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:37 -0400 Subject: ath9k_hw: add initvals for the AR9003 hardware family The AR9003 hardware family now initializes hardware by block components and into stages: pre, core and init. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_initvals.h | 1793 ++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/hw.c | 73 + drivers/net/wireless/ath/ath9k/hw.h | 13 + 3 files changed, 1879 insertions(+) create mode 100644 drivers/net/wireless/ath/ath9k/ar9003_initvals.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_initvals.h new file mode 100644 index 000000000000..e0391b12e533 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_initvals.h @@ -0,0 +1,1793 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef INITVALS_9003_H +#define INITVALS_9003_H + +/* AR9003 2.0 */ + +static const u32 ar9300_2p0_radio_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31}, + {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800}, + {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20}, + {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, +}; + +static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050da, 0x000050da, 0x000050da, 0x000050da}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, + {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, + {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402}, + {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016048, 0x60001a61, 0x60001a61, 0x60001a61, 0x60001a61}, + {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016448, 0x60001a61, 0x60001a61, 0x60001a61, 0x60001a61}, + {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016848, 0x60001a61, 0x60001a61, 0x60001a61, 0x60001a61}, + {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9300Modes_fast_clock_2p0[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + {0x00001030, 0x00000268, 0x000004d0}, + {0x00001070, 0x0000018c, 0x00000318}, + {0x000010b0, 0x00000fd0, 0x00001fa0}, + {0x00008014, 0x044c044c, 0x08980898}, + {0x0000801c, 0x148ec02b, 0x148ec057}, + {0x00008318, 0x000044c0, 0x00008980}, + {0x00009e00, 0x03721821, 0x03721821}, + {0x0000a230, 0x0000000b, 0x00000016}, + {0x0000a254, 0x00000898, 0x00001130}, +}; + +static const u32 ar9300_2p0_radio_core[][2] = { + /* Addr allmodes */ + {0x00016000, 0x36db6db6}, + {0x00016004, 0x6db6db40}, + {0x00016008, 0x73f00000}, + {0x0001600c, 0x00000000}, + {0x00016040, 0x7f80fff8}, + {0x0001604c, 0x76d005b5}, + {0x00016050, 0x556cf031}, + {0x00016054, 0x43449440}, + {0x00016058, 0x0c51c92c}, + {0x0001605c, 0x3db7fffc}, + {0x00016060, 0xfffffffc}, + {0x00016064, 0x000f0278}, + {0x0001606c, 0x6db60000}, + {0x00016080, 0x00000000}, + {0x00016084, 0x0e48048c}, + {0x00016088, 0x54214514}, + {0x0001608c, 0x119f481e}, + {0x00016090, 0x24926490}, + {0x00016098, 0xd2888888}, + {0x000160a0, 0x0a108ffe}, + {0x000160a4, 0x812fc370}, + {0x000160a8, 0x423c8000}, + {0x000160b4, 0x92480080}, + {0x000160c0, 0x00adb6d0}, + {0x000160c4, 0x6db6db60}, + {0x000160c8, 0x6db6db6c}, + {0x000160cc, 0x01e6c000}, + {0x00016100, 0x3fffbe01}, + {0x00016104, 0xfff80000}, + {0x00016108, 0x00080010}, + {0x00016140, 0x10804008}, + {0x00016144, 0x02084080}, + {0x00016148, 0x00000000}, + {0x00016280, 0x058a0001}, + {0x00016284, 0x3d840208}, + {0x00016288, 0x01a20408}, + {0x0001628c, 0x00038c07}, + {0x00016290, 0x40000004}, + {0x00016294, 0x458aa14f}, + {0x00016380, 0x00000000}, + {0x00016384, 0x00000000}, + {0x00016388, 0x00800700}, + {0x0001638c, 0x00800700}, + {0x00016390, 0x00800700}, + {0x00016394, 0x00000000}, + {0x00016398, 0x00000000}, + {0x0001639c, 0x00000000}, + {0x000163a0, 0x00000001}, + {0x000163a4, 0x00000001}, + {0x000163a8, 0x00000000}, + {0x000163ac, 0x00000000}, + {0x000163b0, 0x00000000}, + {0x000163b4, 0x00000000}, + {0x000163b8, 0x00000000}, + {0x000163bc, 0x00000000}, + {0x000163c0, 0x000000a0}, + {0x000163c4, 0x000c0000}, + {0x000163c8, 0x14021402}, + {0x000163cc, 0x00001402}, + {0x000163d0, 0x00000000}, + {0x000163d4, 0x00000000}, + {0x00016400, 0x36db6db6}, + {0x00016404, 0x6db6db40}, + {0x00016408, 0x73f00000}, + {0x0001640c, 0x00000000}, + {0x00016440, 0x7f80fff8}, + {0x0001644c, 0x76d005b5}, + {0x00016450, 0x556cf031}, + {0x00016454, 0x43449440}, + {0x00016458, 0x0c51c92c}, + {0x0001645c, 0x3db7fffc}, + {0x00016460, 0xfffffffc}, + {0x00016464, 0x000f0278}, + {0x0001646c, 0x6db60000}, + {0x00016500, 0x3fffbe01}, + {0x00016504, 0xfff80000}, + {0x00016508, 0x00080010}, + {0x00016540, 0x10804008}, + {0x00016544, 0x02084080}, + {0x00016548, 0x00000000}, + {0x00016780, 0x00000000}, + {0x00016784, 0x00000000}, + {0x00016788, 0x00800700}, + {0x0001678c, 0x00800700}, + {0x00016790, 0x00800700}, + {0x00016794, 0x00000000}, + {0x00016798, 0x00000000}, + {0x0001679c, 0x00000000}, + {0x000167a0, 0x00000001}, + {0x000167a4, 0x00000001}, + {0x000167a8, 0x00000000}, + {0x000167ac, 0x00000000}, + {0x000167b0, 0x00000000}, + {0x000167b4, 0x00000000}, + {0x000167b8, 0x00000000}, + {0x000167bc, 0x00000000}, + {0x000167c0, 0x000000a0}, + {0x000167c4, 0x000c0000}, + {0x000167c8, 0x14021402}, + {0x000167cc, 0x00001402}, + {0x000167d0, 0x00000000}, + {0x000167d4, 0x00000000}, + {0x00016800, 0x36db6db6}, + {0x00016804, 0x6db6db40}, + {0x00016808, 0x73f00000}, + {0x0001680c, 0x00000000}, + {0x00016840, 0x7f80fff8}, + {0x0001684c, 0x76d005b5}, + {0x00016850, 0x556cf031}, + {0x00016854, 0x43449440}, + {0x00016858, 0x0c51c92c}, + {0x0001685c, 0x3db7fffc}, + {0x00016860, 0xfffffffc}, + {0x00016864, 0x000f0278}, + {0x0001686c, 0x6db60000}, + {0x00016900, 0x3fffbe01}, + {0x00016904, 0xfff80000}, + {0x00016908, 0x00080010}, + {0x00016940, 0x10804008}, + {0x00016944, 0x02084080}, + {0x00016948, 0x00000000}, + {0x00016b80, 0x00000000}, + {0x00016b84, 0x00000000}, + {0x00016b88, 0x00800700}, + {0x00016b8c, 0x00800700}, + {0x00016b90, 0x00800700}, + {0x00016b94, 0x00000000}, + {0x00016b98, 0x00000000}, + {0x00016b9c, 0x00000000}, + {0x00016ba0, 0x00000001}, + {0x00016ba4, 0x00000001}, + {0x00016ba8, 0x00000000}, + {0x00016bac, 0x00000000}, + {0x00016bb0, 0x00000000}, + {0x00016bb4, 0x00000000}, + {0x00016bb8, 0x00000000}, + {0x00016bbc, 0x00000000}, + {0x00016bc0, 0x000000a0}, + {0x00016bc4, 0x000c0000}, + {0x00016bc8, 0x14021402}, + {0x00016bcc, 0x00001402}, + {0x00016bd0, 0x00000000}, + {0x00016bd4, 0x00000000}, +}; + +static const u32 ar9300Common_rx_gain_table_merlin_2p0[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x02000101}, + {0x0000a004, 0x02000102}, + {0x0000a008, 0x02000103}, + {0x0000a00c, 0x02000104}, + {0x0000a010, 0x02000200}, + {0x0000a014, 0x02000201}, + {0x0000a018, 0x02000202}, + {0x0000a01c, 0x02000203}, + {0x0000a020, 0x02000204}, + {0x0000a024, 0x02000205}, + {0x0000a028, 0x02000208}, + {0x0000a02c, 0x02000302}, + {0x0000a030, 0x02000303}, + {0x0000a034, 0x02000304}, + {0x0000a038, 0x02000400}, + {0x0000a03c, 0x02010300}, + {0x0000a040, 0x02010301}, + {0x0000a044, 0x02010302}, + {0x0000a048, 0x02000500}, + {0x0000a04c, 0x02010400}, + {0x0000a050, 0x02020300}, + {0x0000a054, 0x02020301}, + {0x0000a058, 0x02020302}, + {0x0000a05c, 0x02020303}, + {0x0000a060, 0x02020400}, + {0x0000a064, 0x02030300}, + {0x0000a068, 0x02030301}, + {0x0000a06c, 0x02030302}, + {0x0000a070, 0x02030303}, + {0x0000a074, 0x02030400}, + {0x0000a078, 0x02040300}, + {0x0000a07c, 0x02040301}, + {0x0000a080, 0x02040302}, + {0x0000a084, 0x02040303}, + {0x0000a088, 0x02030500}, + {0x0000a08c, 0x02040400}, + {0x0000a090, 0x02050203}, + {0x0000a094, 0x02050204}, + {0x0000a098, 0x02050205}, + {0x0000a09c, 0x02040500}, + {0x0000a0a0, 0x02050301}, + {0x0000a0a4, 0x02050302}, + {0x0000a0a8, 0x02050303}, + {0x0000a0ac, 0x02050400}, + {0x0000a0b0, 0x02050401}, + {0x0000a0b4, 0x02050402}, + {0x0000a0b8, 0x02050403}, + {0x0000a0bc, 0x02050500}, + {0x0000a0c0, 0x02050501}, + {0x0000a0c4, 0x02050502}, + {0x0000a0c8, 0x02050503}, + {0x0000a0cc, 0x02050504}, + {0x0000a0d0, 0x02050600}, + {0x0000a0d4, 0x02050601}, + {0x0000a0d8, 0x02050602}, + {0x0000a0dc, 0x02050603}, + {0x0000a0e0, 0x02050604}, + {0x0000a0e4, 0x02050700}, + {0x0000a0e8, 0x02050701}, + {0x0000a0ec, 0x02050702}, + {0x0000a0f0, 0x02050703}, + {0x0000a0f4, 0x02050704}, + {0x0000a0f8, 0x02050705}, + {0x0000a0fc, 0x02050708}, + {0x0000a100, 0x02050709}, + {0x0000a104, 0x0205070a}, + {0x0000a108, 0x0205070b}, + {0x0000a10c, 0x0205070c}, + {0x0000a110, 0x0205070d}, + {0x0000a114, 0x02050710}, + {0x0000a118, 0x02050711}, + {0x0000a11c, 0x02050712}, + {0x0000a120, 0x02050713}, + {0x0000a124, 0x02050714}, + {0x0000a128, 0x02050715}, + {0x0000a12c, 0x02050730}, + {0x0000a130, 0x02050731}, + {0x0000a134, 0x02050732}, + {0x0000a138, 0x02050733}, + {0x0000a13c, 0x02050734}, + {0x0000a140, 0x02050735}, + {0x0000a144, 0x02050750}, + {0x0000a148, 0x02050751}, + {0x0000a14c, 0x02050752}, + {0x0000a150, 0x02050753}, + {0x0000a154, 0x02050754}, + {0x0000a158, 0x02050755}, + {0x0000a15c, 0x02050770}, + {0x0000a160, 0x02050771}, + {0x0000a164, 0x02050772}, + {0x0000a168, 0x02050773}, + {0x0000a16c, 0x02050774}, + {0x0000a170, 0x02050775}, + {0x0000a174, 0x00000776}, + {0x0000a178, 0x00000776}, + {0x0000a17c, 0x00000776}, + {0x0000a180, 0x00000776}, + {0x0000a184, 0x00000776}, + {0x0000a188, 0x00000776}, + {0x0000a18c, 0x00000776}, + {0x0000a190, 0x00000776}, + {0x0000a194, 0x00000776}, + {0x0000a198, 0x00000776}, + {0x0000a19c, 0x00000776}, + {0x0000a1a0, 0x00000776}, + {0x0000a1a4, 0x00000776}, + {0x0000a1a8, 0x00000776}, + {0x0000a1ac, 0x00000776}, + {0x0000a1b0, 0x00000776}, + {0x0000a1b4, 0x00000776}, + {0x0000a1b8, 0x00000776}, + {0x0000a1bc, 0x00000776}, + {0x0000a1c0, 0x00000776}, + {0x0000a1c4, 0x00000776}, + {0x0000a1c8, 0x00000776}, + {0x0000a1cc, 0x00000776}, + {0x0000a1d0, 0x00000776}, + {0x0000a1d4, 0x00000776}, + {0x0000a1d8, 0x00000776}, + {0x0000a1dc, 0x00000776}, + {0x0000a1e0, 0x00000776}, + {0x0000a1e4, 0x00000776}, + {0x0000a1e8, 0x00000776}, + {0x0000a1ec, 0x00000776}, + {0x0000a1f0, 0x00000776}, + {0x0000a1f4, 0x00000776}, + {0x0000a1f8, 0x00000776}, + {0x0000a1fc, 0x00000776}, + {0x0000b000, 0x02000101}, + {0x0000b004, 0x02000102}, + {0x0000b008, 0x02000103}, + {0x0000b00c, 0x02000104}, + {0x0000b010, 0x02000200}, + {0x0000b014, 0x02000201}, + {0x0000b018, 0x02000202}, + {0x0000b01c, 0x02000203}, + {0x0000b020, 0x02000204}, + {0x0000b024, 0x02000205}, + {0x0000b028, 0x02000208}, + {0x0000b02c, 0x02000302}, + {0x0000b030, 0x02000303}, + {0x0000b034, 0x02000304}, + {0x0000b038, 0x02000400}, + {0x0000b03c, 0x02010300}, + {0x0000b040, 0x02010301}, + {0x0000b044, 0x02010302}, + {0x0000b048, 0x02000500}, + {0x0000b04c, 0x02010400}, + {0x0000b050, 0x02020300}, + {0x0000b054, 0x02020301}, + {0x0000b058, 0x02020302}, + {0x0000b05c, 0x02020303}, + {0x0000b060, 0x02020400}, + {0x0000b064, 0x02030300}, + {0x0000b068, 0x02030301}, + {0x0000b06c, 0x02030302}, + {0x0000b070, 0x02030303}, + {0x0000b074, 0x02030400}, + {0x0000b078, 0x02040300}, + {0x0000b07c, 0x02040301}, + {0x0000b080, 0x02040302}, + {0x0000b084, 0x02040303}, + {0x0000b088, 0x02030500}, + {0x0000b08c, 0x02040400}, + {0x0000b090, 0x02050203}, + {0x0000b094, 0x02050204}, + {0x0000b098, 0x02050205}, + {0x0000b09c, 0x02040500}, + {0x0000b0a0, 0x02050301}, + {0x0000b0a4, 0x02050302}, + {0x0000b0a8, 0x02050303}, + {0x0000b0ac, 0x02050400}, + {0x0000b0b0, 0x02050401}, + {0x0000b0b4, 0x02050402}, + {0x0000b0b8, 0x02050403}, + {0x0000b0bc, 0x02050500}, + {0x0000b0c0, 0x02050501}, + {0x0000b0c4, 0x02050502}, + {0x0000b0c8, 0x02050503}, + {0x0000b0cc, 0x02050504}, + {0x0000b0d0, 0x02050600}, + {0x0000b0d4, 0x02050601}, + {0x0000b0d8, 0x02050602}, + {0x0000b0dc, 0x02050603}, + {0x0000b0e0, 0x02050604}, + {0x0000b0e4, 0x02050700}, + {0x0000b0e8, 0x02050701}, + {0x0000b0ec, 0x02050702}, + {0x0000b0f0, 0x02050703}, + {0x0000b0f4, 0x02050704}, + {0x0000b0f8, 0x02050705}, + {0x0000b0fc, 0x02050708}, + {0x0000b100, 0x02050709}, + {0x0000b104, 0x0205070a}, + {0x0000b108, 0x0205070b}, + {0x0000b10c, 0x0205070c}, + {0x0000b110, 0x0205070d}, + {0x0000b114, 0x02050710}, + {0x0000b118, 0x02050711}, + {0x0000b11c, 0x02050712}, + {0x0000b120, 0x02050713}, + {0x0000b124, 0x02050714}, + {0x0000b128, 0x02050715}, + {0x0000b12c, 0x02050730}, + {0x0000b130, 0x02050731}, + {0x0000b134, 0x02050732}, + {0x0000b138, 0x02050733}, + {0x0000b13c, 0x02050734}, + {0x0000b140, 0x02050735}, + {0x0000b144, 0x02050750}, + {0x0000b148, 0x02050751}, + {0x0000b14c, 0x02050752}, + {0x0000b150, 0x02050753}, + {0x0000b154, 0x02050754}, + {0x0000b158, 0x02050755}, + {0x0000b15c, 0x02050770}, + {0x0000b160, 0x02050771}, + {0x0000b164, 0x02050772}, + {0x0000b168, 0x02050773}, + {0x0000b16c, 0x02050774}, + {0x0000b170, 0x02050775}, + {0x0000b174, 0x00000776}, + {0x0000b178, 0x00000776}, + {0x0000b17c, 0x00000776}, + {0x0000b180, 0x00000776}, + {0x0000b184, 0x00000776}, + {0x0000b188, 0x00000776}, + {0x0000b18c, 0x00000776}, + {0x0000b190, 0x00000776}, + {0x0000b194, 0x00000776}, + {0x0000b198, 0x00000776}, + {0x0000b19c, 0x00000776}, + {0x0000b1a0, 0x00000776}, + {0x0000b1a4, 0x00000776}, + {0x0000b1a8, 0x00000776}, + {0x0000b1ac, 0x00000776}, + {0x0000b1b0, 0x00000776}, + {0x0000b1b4, 0x00000776}, + {0x0000b1b8, 0x00000776}, + {0x0000b1bc, 0x00000776}, + {0x0000b1c0, 0x00000776}, + {0x0000b1c4, 0x00000776}, + {0x0000b1c8, 0x00000776}, + {0x0000b1cc, 0x00000776}, + {0x0000b1d0, 0x00000776}, + {0x0000b1d4, 0x00000776}, + {0x0000b1d8, 0x00000776}, + {0x0000b1dc, 0x00000776}, + {0x0000b1e0, 0x00000776}, + {0x0000b1e4, 0x00000776}, + {0x0000b1e8, 0x00000776}, + {0x0000b1ec, 0x00000776}, + {0x0000b1f0, 0x00000776}, + {0x0000b1f4, 0x00000776}, + {0x0000b1f8, 0x00000776}, + {0x0000b1fc, 0x00000776}, +}; + +static const u32 ar9300_2p0_mac_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, + {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, + {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, + {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, + {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, + {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, +}; + +static const u32 ar9300_2p0_soc_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00007010, 0x00000023, 0x00000023, 0x00000022, 0x00000022}, +}; + +static const u32 ar9200_merlin_2p0_radio_core[][2] = { + /* Addr common */ + {0x00007800, 0x00040000}, + {0x00007804, 0xdb005012}, + {0x00007808, 0x04924914}, + {0x0000780c, 0x21084210}, + {0x00007810, 0x6d801300}, + {0x00007814, 0x0019beff}, + {0x00007818, 0x07e41000}, + {0x0000781c, 0x00392000}, + {0x00007820, 0x92592480}, + {0x00007824, 0x00040000}, + {0x00007828, 0xdb005012}, + {0x0000782c, 0x04924914}, + {0x00007830, 0x21084210}, + {0x00007834, 0x6d801300}, + {0x00007838, 0x0019beff}, + {0x0000783c, 0x07e40000}, + {0x00007840, 0x00392000}, + {0x00007844, 0x92592480}, + {0x00007848, 0x00100000}, + {0x0000784c, 0x773f0567}, + {0x00007850, 0x54214514}, + {0x00007854, 0x12035828}, + {0x00007858, 0x92592692}, + {0x0000785c, 0x00000000}, + {0x00007860, 0x56400000}, + {0x00007864, 0x0a8e370e}, + {0x00007868, 0xc0102850}, + {0x0000786c, 0x812d4000}, + {0x00007870, 0x807ec400}, + {0x00007874, 0x001b6db0}, + {0x00007878, 0x00376b63}, + {0x0000787c, 0x06db6db6}, + {0x00007880, 0x006d8000}, + {0x00007884, 0xffeffffe}, + {0x00007888, 0xffeffffe}, + {0x0000788c, 0x00010000}, + {0x00007890, 0x02060aeb}, + {0x00007894, 0x5a108000}, +}; + +static const u32 ar9300_2p0_baseband_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005}, + {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, + {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, + {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, + {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, + {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, + {0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044}, + {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, + {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, + {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, + {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, + {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, + {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, + {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, + {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, + {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, + {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, + {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, + {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0}, + {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, + {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, + {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, + {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, + {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, + {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, + {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, + {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, + {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, + {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, + {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, + {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, + {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, + {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, + {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000ae04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, + {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, + {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000be04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, + {0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, +}; + +static const u32 ar9300_2p0_baseband_core[][2] = { + /* Addr allmodes */ + {0x00009800, 0xafe68e30}, + {0x00009804, 0xfd14e000}, + {0x00009808, 0x9c0a9f6b}, + {0x0000980c, 0x04900000}, + {0x00009814, 0x9280c00a}, + {0x00009818, 0x00000000}, + {0x0000981c, 0x00020028}, + {0x00009834, 0x5f3ca3de}, + {0x00009838, 0x0108ecff}, + {0x0000983c, 0x14750600}, + {0x00009880, 0x201fff00}, + {0x00009884, 0x00001042}, + {0x000098a4, 0x00200400}, + {0x000098b0, 0x52440bbe}, + {0x000098d0, 0x004b6a8e}, + {0x000098d4, 0x00000820}, + {0x000098dc, 0x00000000}, + {0x000098f0, 0x00000000}, + {0x000098f4, 0x00000000}, + {0x00009c04, 0xff55ff55}, + {0x00009c08, 0x0320ff55}, + {0x00009c0c, 0x00000000}, + {0x00009c10, 0x00000000}, + {0x00009c14, 0x00046384}, + {0x00009c18, 0x05b6b440}, + {0x00009c1c, 0x00b6b440}, + {0x00009d00, 0xc080a333}, + {0x00009d04, 0x40206c10}, + {0x00009d08, 0x009c4060}, + {0x00009d0c, 0x9883800a}, + {0x00009d10, 0x01834061}, + {0x00009d14, 0x00c0040b}, + {0x00009d18, 0x00000000}, + {0x00009e08, 0x0038233c}, + {0x00009e24, 0x990bb515}, + {0x00009e28, 0x0c6f0000}, + {0x00009e30, 0x06336f77}, + {0x00009e34, 0x6af6532f}, + {0x00009e38, 0x0cc80c00}, + {0x00009e3c, 0xcf946222}, + {0x00009e40, 0x0d261820}, + {0x00009e4c, 0x00001004}, + {0x00009e50, 0x00ff03f1}, + {0x00009e54, 0x00000000}, + {0x00009fc0, 0x803e4788}, + {0x00009fc4, 0x0001efb5}, + {0x00009fcc, 0x40000014}, + {0x00009fd0, 0x01193b93}, + {0x0000a20c, 0x00000000}, + {0x0000a220, 0x00000000}, + {0x0000a224, 0x00000000}, + {0x0000a228, 0x10002310}, + {0x0000a22c, 0x01036a1e}, + {0x0000a234, 0x10000fff}, + {0x0000a23c, 0x00000000}, + {0x0000a244, 0x0c000000}, + {0x0000a2a0, 0x00000001}, + {0x0000a2c0, 0x00000001}, + {0x0000a2c8, 0x00000000}, + {0x0000a2cc, 0x18c43433}, + {0x0000a2d4, 0x00000000}, + {0x0000a2dc, 0x00000000}, + {0x0000a2e0, 0x00000000}, + {0x0000a2e4, 0x00000000}, + {0x0000a2e8, 0x00000000}, + {0x0000a2ec, 0x00000000}, + {0x0000a2f0, 0x00000000}, + {0x0000a2f4, 0x00000000}, + {0x0000a2f8, 0x00000000}, + {0x0000a344, 0x00000000}, + {0x0000a34c, 0x00000000}, + {0x0000a350, 0x0000a000}, + {0x0000a364, 0x00000000}, + {0x0000a370, 0x00000000}, + {0x0000a390, 0x00000001}, + {0x0000a394, 0x00000444}, + {0x0000a398, 0x001f0e0f}, + {0x0000a39c, 0x0075393f}, + {0x0000a3a0, 0xb79f6427}, + {0x0000a3a4, 0x00000000}, + {0x0000a3a8, 0xaaaaaaaa}, + {0x0000a3ac, 0x3c466478}, + {0x0000a3c0, 0x20202020}, + {0x0000a3c4, 0x22222220}, + {0x0000a3c8, 0x20200020}, + {0x0000a3cc, 0x20202020}, + {0x0000a3d0, 0x20202020}, + {0x0000a3d4, 0x20202020}, + {0x0000a3d8, 0x20202020}, + {0x0000a3dc, 0x20202020}, + {0x0000a3e0, 0x20202020}, + {0x0000a3e4, 0x20202020}, + {0x0000a3e8, 0x20202020}, + {0x0000a3ec, 0x20202020}, + {0x0000a3f0, 0x00000000}, + {0x0000a3f4, 0x00000246}, + {0x0000a3f8, 0x0cdbd380}, + {0x0000a3fc, 0x000f0f01}, + {0x0000a400, 0x8fa91f01}, + {0x0000a404, 0x00000000}, + {0x0000a408, 0x0e79e5c6}, + {0x0000a40c, 0x00820820}, + {0x0000a414, 0x1ce739ce}, + {0x0000a418, 0x7d001dce}, + {0x0000a41c, 0x1ce739ce}, + {0x0000a420, 0x000001ce}, + {0x0000a424, 0x1ce739ce}, + {0x0000a428, 0x000001ce}, + {0x0000a42c, 0x1ce739ce}, + {0x0000a430, 0x1ce739ce}, + {0x0000a434, 0x00000000}, + {0x0000a438, 0x00001801}, + {0x0000a43c, 0x00000000}, + {0x0000a440, 0x00000000}, + {0x0000a444, 0x00000000}, + {0x0000a448, 0x07000080}, + {0x0000a44c, 0x00000001}, + {0x0000a450, 0x00010000}, + {0x0000a458, 0x00000000}, + {0x0000a600, 0x00000000}, + {0x0000a604, 0x00000000}, + {0x0000a608, 0x00000000}, + {0x0000a60c, 0x00000000}, + {0x0000a610, 0x00000000}, + {0x0000a614, 0x00000000}, + {0x0000a618, 0x00000000}, + {0x0000a61c, 0x00000000}, + {0x0000a620, 0x00000000}, + {0x0000a624, 0x00000000}, + {0x0000a628, 0x00000000}, + {0x0000a62c, 0x00000000}, + {0x0000a630, 0x00000000}, + {0x0000a634, 0x00000000}, + {0x0000a638, 0x00000000}, + {0x0000a63c, 0x00000000}, + {0x0000a640, 0x00000000}, + {0x0000a644, 0x3ffd9d74}, + {0x0000a648, 0x0048060a}, + {0x0000a64c, 0x00000637}, + {0x0000a670, 0x03020100}, + {0x0000a674, 0x09080504}, + {0x0000a678, 0x0d0c0b0a}, + {0x0000a67c, 0x13121110}, + {0x0000a680, 0x31301514}, + {0x0000a684, 0x35343332}, + {0x0000a688, 0x00000036}, + {0x0000a690, 0x00000838}, + {0x0000a7c0, 0x00000000}, + {0x0000a7c4, 0xfffffffc}, + {0x0000a7c8, 0x00000000}, + {0x0000a7cc, 0x00000000}, + {0x0000a7d0, 0x00000000}, + {0x0000a7d4, 0x00000004}, + {0x0000a7dc, 0x00000001}, + {0x0000a8d0, 0x004b6a8e}, + {0x0000a8d4, 0x00000820}, + {0x0000a8dc, 0x00000000}, + {0x0000a8f0, 0x00000000}, + {0x0000a8f4, 0x00000000}, + {0x0000b2d0, 0x00000080}, + {0x0000b2d4, 0x00000000}, + {0x0000b2dc, 0x00000000}, + {0x0000b2e0, 0x00000000}, + {0x0000b2e4, 0x00000000}, + {0x0000b2e8, 0x00000000}, + {0x0000b2ec, 0x00000000}, + {0x0000b2f0, 0x00000000}, + {0x0000b2f4, 0x00000000}, + {0x0000b2f8, 0x00000000}, + {0x0000b408, 0x0e79e5c0}, + {0x0000b40c, 0x00820820}, + {0x0000b420, 0x00000000}, + {0x0000b8d0, 0x004b6a8e}, + {0x0000b8d4, 0x00000820}, + {0x0000b8dc, 0x00000000}, + {0x0000b8f0, 0x00000000}, + {0x0000b8f4, 0x00000000}, + {0x0000c2d0, 0x00000080}, + {0x0000c2d4, 0x00000000}, + {0x0000c2dc, 0x00000000}, + {0x0000c2e0, 0x00000000}, + {0x0000c2e4, 0x00000000}, + {0x0000c2e8, 0x00000000}, + {0x0000c2ec, 0x00000000}, + {0x0000c2f0, 0x00000000}, + {0x0000c2f4, 0x00000000}, + {0x0000c2f8, 0x00000000}, + {0x0000c408, 0x0e79e5c0}, + {0x0000c40c, 0x00820820}, + {0x0000c420, 0x00000000}, +}; + +static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050da, 0x000050da}, + {0x0000a500, 0x00020220, 0x00020220, 0x00000000, 0x00000000}, + {0x0000a504, 0x06020223, 0x06020223, 0x04000002, 0x04000002}, + {0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10022223, 0x10022223, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x17022620, 0x17022620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1b022622, 0x1b022622, 0x11000400, 0x11000400}, + {0x0000a518, 0x1f022822, 0x1f022822, 0x15000402, 0x15000402}, + {0x0000a51c, 0x24022842, 0x24022842, 0x19000404, 0x19000404}, + {0x0000a520, 0x28042840, 0x28042840, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2c042842, 0x2c042842, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x30042844, 0x30042844, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x34042846, 0x34042846, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x39042869, 0x39042869, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x3d062869, 0x3d062869, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x44062c69, 0x44062c69, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x48063069, 0x48063069, 0x34001640, 0x34001640}, + {0x0000a540, 0x4c0a3065, 0x4c0a3065, 0x38001660, 0x38001660}, + {0x0000a544, 0x500a3069, 0x500a3069, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x530a3469, 0x530a3469, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x590a7464, 0x590a7464, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5e0a7865, 0x5e0a7865, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x630a7e66, 0x630a7e66, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x680a7e89, 0x680a7e89, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6e0a7e8c, 0x6e0a7e8c, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x730e7e8c, 0x730e7e8c, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00820220, 0x00820220, 0x00800000, 0x00800000}, + {0x0000a584, 0x06820223, 0x06820223, 0x04800002, 0x04800002}, + {0x0000a588, 0x0b822220, 0x0b822220, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10822223, 0x10822223, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x17822620, 0x17822620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1b822622, 0x1b822622, 0x11800400, 0x11800400}, + {0x0000a598, 0x1f822822, 0x1f822822, 0x15800402, 0x15800402}, + {0x0000a59c, 0x24822842, 0x24822842, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x28842840, 0x28842840, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2c842842, 0x2c842842, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x30842844, 0x30842844, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x34842846, 0x34842846, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x39842869, 0x39842869, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x3d862869, 0x3d862869, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x44862c69, 0x44862c69, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x48863069, 0x48863069, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x4c8a3065, 0x4c8a3065, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x508a3069, 0x508a3069, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x538a3469, 0x538a3469, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x598a7464, 0x598a7464, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5e8a7865, 0x5e8a7865, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x638a7e66, 0x638a7e66, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x688a7e89, 0x688a7e89, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6e8a7e8c, 0x6e8a7e8c, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x738e7e8c, 0x738e7e8c, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, + {0x00016048, 0xad241a61, 0xad241a61, 0xad241a61, 0xad241a61}, + {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, + {0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, + {0x00016448, 0xad241a61, 0xad241a61, 0xad241a61, 0xad241a61}, + {0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, + {0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, + {0x00016848, 0xad241a61, 0xad241a61, 0xad241a61, 0xad241a61}, + {0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, +}; + +static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050da, 0x000050da}, + {0x0000a500, 0x00020220, 0x00020220, 0x00000000, 0x00000000}, + {0x0000a504, 0x06020223, 0x06020223, 0x04000002, 0x04000002}, + {0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10022223, 0x10022223, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x17022620, 0x17022620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1b022622, 0x1b022622, 0x11000400, 0x11000400}, + {0x0000a518, 0x1f022822, 0x1f022822, 0x15000402, 0x15000402}, + {0x0000a51c, 0x24022842, 0x24022842, 0x19000404, 0x19000404}, + {0x0000a520, 0x28042840, 0x28042840, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2c042842, 0x2c042842, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x30042844, 0x30042844, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x34042846, 0x34042846, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x39042869, 0x39042869, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x3d062869, 0x3d062869, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x44062c69, 0x44062c69, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x48063069, 0x48063069, 0x34001640, 0x34001640}, + {0x0000a540, 0x4c0a3065, 0x4c0a3065, 0x38001660, 0x38001660}, + {0x0000a544, 0x500a3069, 0x500a3069, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x530a3469, 0x530a3469, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x590a7464, 0x590a7464, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5e0a7865, 0x5e0a7865, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x630a7e66, 0x630a7e66, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x680a7e89, 0x680a7e89, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6e0a7e8c, 0x6e0a7e8c, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x730e7e8c, 0x730e7e8c, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00820220, 0x00820220, 0x00800000, 0x00800000}, + {0x0000a584, 0x06820223, 0x06820223, 0x04800002, 0x04800002}, + {0x0000a588, 0x0b822220, 0x0b822220, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10822223, 0x10822223, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x17822620, 0x17822620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1b822622, 0x1b822622, 0x11800400, 0x11800400}, + {0x0000a598, 0x1f822822, 0x1f822822, 0x15800402, 0x15800402}, + {0x0000a59c, 0x24822842, 0x24822842, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x28842840, 0x28842840, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2c842842, 0x2c842842, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x30842844, 0x30842844, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x34842846, 0x34842846, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x39842869, 0x39842869, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x3d862869, 0x3d862869, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x44862c69, 0x44862c69, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x48863069, 0x48863069, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x4c8a3065, 0x4c8a3065, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x508a3069, 0x508a3069, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x538a3469, 0x538a3469, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x598a7464, 0x598a7464, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5e8a7865, 0x5e8a7865, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x638a7e66, 0x638a7e66, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x688a7e89, 0x688a7e89, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6e8a7e8c, 0x6e8a7e8c, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x738e7e8c, 0x738e7e8c, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, + {0x00016048, 0x8c001a61, 0x8c001a61, 0x8c001a61, 0x8c001a61}, + {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, + {0x00016448, 0x8c001a61, 0x8c001a61, 0x8c001a61, 0x8c001a61}, + {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, + {0x00016848, 0x8c001a61, 0x8c001a61, 0x8c001a61, 0x8c001a61}, + {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9300Common_rx_gain_table_2p0[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x01800082}, + {0x0000a014, 0x01820181}, + {0x0000a018, 0x01840183}, + {0x0000a01c, 0x01880185}, + {0x0000a020, 0x018a0189}, + {0x0000a024, 0x02850284}, + {0x0000a028, 0x02890288}, + {0x0000a02c, 0x028b028a}, + {0x0000a030, 0x028d028c}, + {0x0000a034, 0x02910290}, + {0x0000a038, 0x02930292}, + {0x0000a03c, 0x03910390}, + {0x0000a040, 0x03930392}, + {0x0000a044, 0x03950394}, + {0x0000a048, 0x00000396}, + {0x0000a04c, 0x00000000}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x28282828}, + {0x0000a084, 0x21212128}, + {0x0000a088, 0x21212121}, + {0x0000a08c, 0x1c1c1c21}, + {0x0000a090, 0x1c1c1c1c}, + {0x0000a094, 0x17171c1c}, + {0x0000a098, 0x02020212}, + {0x0000a09c, 0x02020202}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x011f0100}, + {0x0000a0c8, 0x011d011e}, + {0x0000a0cc, 0x011b011c}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x021d021e}, + {0x0000a0e0, 0x03010302}, + {0x0000a0e4, 0x031f0300}, + {0x0000a0e8, 0x0402031e}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x05010502}, + {0x0000a0f8, 0x051f0500}, + {0x0000a0fc, 0x0602051e}, + {0x0000a100, 0x06000601}, + {0x0000a104, 0x061e061f}, + {0x0000a108, 0x0703061d}, + {0x0000a10c, 0x07010702}, + {0x0000a110, 0x00000700}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x011f0100}, + {0x0000a148, 0x011d011e}, + {0x0000a14c, 0x011b011c}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x021d021e}, + {0x0000a160, 0x03010302}, + {0x0000a164, 0x031f0300}, + {0x0000a168, 0x0402031e}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x05010502}, + {0x0000a178, 0x051f0500}, + {0x0000a17c, 0x0602051e}, + {0x0000a180, 0x06000601}, + {0x0000a184, 0x061e061f}, + {0x0000a188, 0x0703061d}, + {0x0000a18c, 0x07010702}, + {0x0000a190, 0x00000700}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x32323232}, + {0x0000b084, 0x2f2f3232}, + {0x0000b088, 0x23282a2d}, + {0x0000b08c, 0x1c1e2123}, + {0x0000b090, 0x14171919}, + {0x0000b094, 0x0e0e1214}, + {0x0000b098, 0x03050707}, + {0x0000b09c, 0x00030303}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050da, 0x000050da, 0x000050da, 0x000050da}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, + {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, + {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402}, + {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016048, 0x64001a61, 0x64001a61, 0x64001a61, 0x64001a61}, + {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016448, 0x64001a61, 0x64001a61, 0x64001a61, 0x64001a61}, + {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016848, 0x64001a61, 0x64001a61, 0x64001a61, 0x64001a61}, + {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9300_2p0_mac_core[][2] = { + /* Addr allmodes */ + {0x00000008, 0x00000000}, + {0x00000030, 0x00020085}, + {0x00000034, 0x00000005}, + {0x00000040, 0x00000000}, + {0x00000044, 0x00000000}, + {0x00000048, 0x00000008}, + {0x0000004c, 0x00000010}, + {0x00000050, 0x00000000}, + {0x00001040, 0x002ffc0f}, + {0x00001044, 0x002ffc0f}, + {0x00001048, 0x002ffc0f}, + {0x0000104c, 0x002ffc0f}, + {0x00001050, 0x002ffc0f}, + {0x00001054, 0x002ffc0f}, + {0x00001058, 0x002ffc0f}, + {0x0000105c, 0x002ffc0f}, + {0x00001060, 0x002ffc0f}, + {0x00001064, 0x002ffc0f}, + {0x000010f0, 0x00000100}, + {0x00001270, 0x00000000}, + {0x000012b0, 0x00000000}, + {0x000012f0, 0x00000000}, + {0x0000143c, 0x00000000}, + {0x0000147c, 0x00000000}, + {0x00008000, 0x00000000}, + {0x00008004, 0x00000000}, + {0x00008008, 0x00000000}, + {0x0000800c, 0x00000000}, + {0x00008018, 0x00000000}, + {0x00008020, 0x00000000}, + {0x00008038, 0x00000000}, + {0x0000803c, 0x00000000}, + {0x00008040, 0x00000000}, + {0x00008044, 0x00000000}, + {0x00008048, 0x00000000}, + {0x0000804c, 0xffffffff}, + {0x00008054, 0x00000000}, + {0x00008058, 0x00000000}, + {0x0000805c, 0x000fc78f}, + {0x00008060, 0x0000000f}, + {0x00008064, 0x00000000}, + {0x00008070, 0x00000310}, + {0x00008074, 0x00000020}, + {0x00008078, 0x00000000}, + {0x0000809c, 0x0000000f}, + {0x000080a0, 0x00000000}, + {0x000080a4, 0x02ff0000}, + {0x000080a8, 0x0e070605}, + {0x000080ac, 0x0000000d}, + {0x000080b0, 0x00000000}, + {0x000080b4, 0x00000000}, + {0x000080b8, 0x00000000}, + {0x000080bc, 0x00000000}, + {0x000080c0, 0x2a800000}, + {0x000080c4, 0x06900168}, + {0x000080c8, 0x13881c20}, + {0x000080cc, 0x01f40000}, + {0x000080d0, 0x00252500}, + {0x000080d4, 0x00a00000}, + {0x000080d8, 0x00400000}, + {0x000080dc, 0x00000000}, + {0x000080e0, 0xffffffff}, + {0x000080e4, 0x0000ffff}, + {0x000080e8, 0x3f3f3f3f}, + {0x000080ec, 0x00000000}, + {0x000080f0, 0x00000000}, + {0x000080f4, 0x00000000}, + {0x000080fc, 0x00020000}, + {0x00008100, 0x00000000}, + {0x00008108, 0x00000052}, + {0x0000810c, 0x00000000}, + {0x00008110, 0x00000000}, + {0x00008114, 0x000007ff}, + {0x00008118, 0x000000aa}, + {0x0000811c, 0x00003210}, + {0x00008124, 0x00000000}, + {0x00008128, 0x00000000}, + {0x0000812c, 0x00000000}, + {0x00008130, 0x00000000}, + {0x00008134, 0x00000000}, + {0x00008138, 0x00000000}, + {0x0000813c, 0x0000ffff}, + {0x00008144, 0xffffffff}, + {0x00008168, 0x00000000}, + {0x0000816c, 0x00000000}, + {0x00008170, 0x18486200}, + {0x00008174, 0x33332210}, + {0x00008178, 0x00000000}, + {0x0000817c, 0x00020000}, + {0x000081c0, 0x00000000}, + {0x000081c4, 0x33332210}, + {0x000081c8, 0x00000000}, + {0x000081cc, 0x00000000}, + {0x000081d4, 0x00000000}, + {0x000081ec, 0x00000000}, + {0x000081f0, 0x00000000}, + {0x000081f4, 0x00000000}, + {0x000081f8, 0x00000000}, + {0x000081fc, 0x00000000}, + {0x00008240, 0x00100000}, + {0x00008244, 0x0010f424}, + {0x00008248, 0x00000800}, + {0x0000824c, 0x0001e848}, + {0x00008250, 0x00000000}, + {0x00008254, 0x00000000}, + {0x00008258, 0x00000000}, + {0x0000825c, 0x40000000}, + {0x00008260, 0x00080922}, + {0x00008264, 0x98a00010}, + {0x00008268, 0xffffffff}, + {0x0000826c, 0x0000ffff}, + {0x00008270, 0x00000000}, + {0x00008274, 0x40000000}, + {0x00008278, 0x003e4180}, + {0x0000827c, 0x00000004}, + {0x00008284, 0x0000002c}, + {0x00008288, 0x0000002c}, + {0x0000828c, 0x000000ff}, + {0x00008294, 0x00000000}, + {0x00008298, 0x00000000}, + {0x0000829c, 0x00000000}, + {0x00008300, 0x00000140}, + {0x00008314, 0x00000000}, + {0x0000831c, 0x0000010d}, + {0x00008328, 0x00000000}, + {0x0000832c, 0x00000007}, + {0x00008330, 0x00000302}, + {0x00008334, 0x00000700}, + {0x00008338, 0x00ff0000}, + {0x0000833c, 0x02400000}, + {0x00008340, 0x000107ff}, + {0x00008344, 0xaa48105b}, + {0x00008348, 0x008f0000}, + {0x0000835c, 0x00000000}, + {0x00008360, 0xffffffff}, + {0x00008364, 0xffffffff}, + {0x00008368, 0x00000000}, + {0x00008370, 0x00000000}, + {0x00008374, 0x000000ff}, + {0x00008378, 0x00000000}, + {0x0000837c, 0x00000000}, + {0x00008380, 0xffffffff}, + {0x00008384, 0xffffffff}, + {0x00008390, 0xffffffff}, + {0x00008394, 0xffffffff}, + {0x00008398, 0x00000000}, + {0x0000839c, 0x00000000}, + {0x000083a0, 0x00000000}, + {0x000083a4, 0x0000fa14}, + {0x000083a8, 0x000f0c00}, + {0x000083ac, 0x33332210}, + {0x000083b0, 0x33332210}, + {0x000083b4, 0x33332210}, + {0x000083b8, 0x33332210}, + {0x000083bc, 0x00000000}, + {0x000083c0, 0x00000000}, + {0x000083c4, 0x00000000}, + {0x000083c8, 0x00000000}, + {0x000083cc, 0x00000200}, + {0x000083d0, 0x000301ff}, +}; + +static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x01800082}, + {0x0000a014, 0x01820181}, + {0x0000a018, 0x01840183}, + {0x0000a01c, 0x01880185}, + {0x0000a020, 0x018a0189}, + {0x0000a024, 0x02850284}, + {0x0000a028, 0x02890288}, + {0x0000a02c, 0x03850384}, + {0x0000a030, 0x03890388}, + {0x0000a034, 0x038b038a}, + {0x0000a038, 0x038d038c}, + {0x0000a03c, 0x03910390}, + {0x0000a040, 0x03930392}, + {0x0000a044, 0x03950394}, + {0x0000a048, 0x00000396}, + {0x0000a04c, 0x00000000}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x28282828}, + {0x0000a084, 0x28282828}, + {0x0000a088, 0x28282828}, + {0x0000a08c, 0x28282828}, + {0x0000a090, 0x28282828}, + {0x0000a094, 0x21212128}, + {0x0000a098, 0x171c1c1c}, + {0x0000a09c, 0x02020212}, + {0x0000a0a0, 0x00000202}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x011f0100}, + {0x0000a0c8, 0x011d011e}, + {0x0000a0cc, 0x011b011c}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x021d021e}, + {0x0000a0e0, 0x03010302}, + {0x0000a0e4, 0x031f0300}, + {0x0000a0e8, 0x0402031e}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x05010502}, + {0x0000a0f8, 0x051f0500}, + {0x0000a0fc, 0x0602051e}, + {0x0000a100, 0x06000601}, + {0x0000a104, 0x061e061f}, + {0x0000a108, 0x0703061d}, + {0x0000a10c, 0x07010702}, + {0x0000a110, 0x00000700}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x011f0100}, + {0x0000a148, 0x011d011e}, + {0x0000a14c, 0x011b011c}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x021d021e}, + {0x0000a160, 0x03010302}, + {0x0000a164, 0x031f0300}, + {0x0000a168, 0x0402031e}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x05010502}, + {0x0000a178, 0x051f0500}, + {0x0000a17c, 0x0602051e}, + {0x0000a180, 0x06000601}, + {0x0000a184, 0x061e061f}, + {0x0000a188, 0x0703061d}, + {0x0000a18c, 0x07010702}, + {0x0000a190, 0x00000700}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000296}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x32323232}, + {0x0000b084, 0x2f2f3232}, + {0x0000b088, 0x23282a2d}, + {0x0000b08c, 0x1c1e2123}, + {0x0000b090, 0x14171919}, + {0x0000b094, 0x0e0e1214}, + {0x0000b098, 0x03050707}, + {0x0000b09c, 0x00030303}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9300_2p0_soc_preamble[][2] = { + /* Addr allmodes */ + {0x000040a4, 0x00a0c1c9}, + {0x00007008, 0x00000000}, + {0x00007020, 0x00000000}, + {0x00007034, 0x00000002}, + {0x00007038, 0x000004c2}, +}; + +/* + * PCIE-PHY programming array, to be used prior to entering + * full sleep (holding RTC in reset, PLL is ON in L1 mode) + */ +static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p0[][2] = { + {0x00004040, 0x08212e5e}, + {0x00004040, 0x0008003b}, + {0x00004044, 0x00000000}, +}; + +/* + * PCIE-PHY programming array, to be used when not in + * full sleep (holding RTC in reset) + */ +static const u32 ar9300PciePhy_clkreq_enable_L1_2p0[][2] = { + {0x00004040, 0x08253e5e}, + {0x00004040, 0x0008003b}, + {0x00004044, 0x00000000}, +}; + +/* + * PCIE-PHY programming array, to be used prior to entering + * full sleep (holding RTC in reset) + */ +static const u32 ar9300PciePhy_clkreq_disable_L1_2p0[][2] = { + {0x00004040, 0x08213e5e}, + {0x00004040, 0x0008003b}, + {0x00004044, 0x00000000}, +}; + +#endif /* INITVALS_9003_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8949debeb0fe..4bfb3a847920 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -23,6 +23,7 @@ #include "ar5008_initvals.h" #include "ar9001_initvals.h" #include "ar9002_initvals.h" +#include "ar9003_initvals.h" #define ATH9K_CLOCK_RATE_CCK 22 #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 @@ -813,6 +814,77 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) } } +/* AR9003 2.0 - new INI format (pre, core, post arrays per subsystem) */ +static void ar9003_hw_init_mode_regs(struct ath_hw *ah) +{ + /* mac */ + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], + ar9300_2p0_mac_core, + ARRAY_SIZE(ar9300_2p0_mac_core), 2); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], + ar9300_2p0_mac_postamble, + ARRAY_SIZE(ar9300_2p0_mac_postamble), 5); + + /* bb */ + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], + ar9300_2p0_baseband_core, + ARRAY_SIZE(ar9300_2p0_baseband_core), 2); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], + ar9300_2p0_baseband_postamble, + ARRAY_SIZE(ar9300_2p0_baseband_postamble), 5); + + /* radio */ + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], + ar9300_2p0_radio_core, + ARRAY_SIZE(ar9300_2p0_radio_core), 2); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], + ar9300_2p0_radio_postamble, + ARRAY_SIZE(ar9300_2p0_radio_postamble), 5); + + /* soc */ + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], + ar9300_2p0_soc_preamble, + ARRAY_SIZE(ar9300_2p0_soc_preamble), 2); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], + ar9300_2p0_soc_postamble, + ARRAY_SIZE(ar9300_2p0_soc_postamble), 5); + + /* rx/tx gain */ + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9300Common_rx_gain_table_2p0, + ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), 2); + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_lowest_ob_db_tx_gain_table_2p0, + ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0), + 5); + + /* Load PCIE SERDES settings from INI */ + + /* Awake Setting */ + + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9300PciePhy_pll_on_clkreq_disable_L1_2p0, + ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p0), + 2); + + /* Sleep Setting */ + + INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, + ar9300PciePhy_clkreq_enable_L1_2p0, + ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p0), + 2); + + /* Fast clock modal settings */ + INIT_INI_ARRAY(&ah->iniModesAdditional, + ar9300Modes_fast_clock_2p0, + ARRAY_SIZE(ar9300Modes_fast_clock_2p0), + 3); +} + static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) { if (AR_SREV_9287_11_OR_LATER(ah)) @@ -3581,6 +3653,7 @@ static void ar9003_hw_attach_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + priv_ops->init_mode_regs = ar9003_hw_init_mode_regs; priv_ops->macversion_supported = ar9003_hw_macversion_supported; ar9003_hw_attach_phy_ops(ah); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index d713ff2dfc55..c3928be63b3a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -139,6 +139,13 @@ #define ATH9K_HW_RX_HP_QDEPTH 16 #define ATH9K_HW_RX_LP_QDEPTH 128 +enum ath_ini_subsys { + ATH_INI_PRE = 0, + ATH_INI_CORE, + ATH_INI_POST, + ATH_INI_NUM_SPLIT, +}; + enum wireless_mode { ATH9K_MODE_11A = 0, ATH9K_MODE_11G, @@ -668,6 +675,7 @@ struct ath_hw { struct ar5416IniArray iniBank7; struct ar5416IniArray iniAddac; struct ar5416IniArray iniPcieSerdes; + struct ar5416IniArray iniPcieSerdesLowPower; struct ar5416IniArray iniModesAdditional; struct ar5416IniArray iniModesRxGain; struct ar5416IniArray iniModesTxGain; @@ -680,6 +688,11 @@ struct ath_hw { struct ar5416IniArray iniModes_high_power_tx_gain_9271; struct ar5416IniArray iniModes_normal_power_tx_gain_9271; + struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT]; + struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT]; + struct ar5416IniArray iniRadio[ATH_INI_NUM_SPLIT]; + struct ar5416IniArray iniSOC[ATH_INI_NUM_SPLIT]; + u32 intr_gen_timer_trigger; u32 intr_gen_timer_thresh; struct ath_gen_timer_table hw_gen_timers; -- cgit v1.2.3 From cffb5e49a147cfc6491f561f9b330e1001276185 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:38 -0400 Subject: ath9k_hw: add helpers for processing the AR9003 INI Signed-off-by: Luis R. Rodriguez Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 186 +++++++++++++++++++++++++++- drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2 + drivers/net/wireless/ath/ath9k/reg.h | 13 ++ 3 files changed, 198 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 3e3472e493a4..acbf122a150d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -186,7 +186,40 @@ static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah, static void ar9003_hw_set_channel_regs(struct ath_hw *ah, struct ath9k_channel *chan) { - /* TODO */ + u32 phymode; + u32 enableDacFifo = 0; + + enableDacFifo = + (REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO); + + /* Enable 11n HT, 20 MHz */ + phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_WALSH | + AR_PHY_GC_SHORT_GI_40 | enableDacFifo; + + /* Configure baseband for dynamic 20/40 operation */ + if (IS_CHAN_HT40(chan)) { + phymode |= AR_PHY_GC_DYN2040_EN; + /* Configure control (primary) channel at +-10MHz */ + if ((chan->chanmode == CHANNEL_A_HT40PLUS) || + (chan->chanmode == CHANNEL_G_HT40PLUS)) + phymode |= AR_PHY_GC_DYN2040_PRI_CH; + + } + + /* make sure we preserve INI settings */ + phymode |= REG_READ(ah, AR_PHY_GEN_CTRL); + /* turn off Green Field detection for STA for now */ + phymode &= ~AR_PHY_GC_GF_DETECT_EN; + + REG_WRITE(ah, AR_PHY_GEN_CTRL, phymode); + + /* Configure MAC for 20/40 operation */ + ath9k_hw_set11nmac2040(ah); + + /* global transmit timeout (25 TUs default)*/ + REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); + /* carrier sense timeout */ + REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); } static void ar9003_hw_init_bb(struct ath_hw *ah, @@ -195,11 +228,158 @@ static void ar9003_hw_init_bb(struct ath_hw *ah, /* TODO */ } +void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) +{ + switch (rx) { + case 0x5: + REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, + AR_PHY_SWAP_ALT_CHAIN); + case 0x3: + case 0x1: + case 0x2: + case 0x7: + REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx); + REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx); + break; + default: + break; + } + + REG_WRITE(ah, AR_SELFGEN_MASK, tx); + if (tx == 0x5) { + REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, + AR_PHY_SWAP_ALT_CHAIN); + } +} + +/* + * Override INI values with chip specific configuration. + */ +static void ar9003_hw_override_ini(struct ath_hw *ah) +{ + u32 val; + + /* + * Set the RX_ABORT and RX_DIS and clear it only after + * RXE is set for MAC. This prevents frames with + * corrupted descriptor status. + */ + REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); + + /* + * For AR9280 and above, there is a new feature that allows + * Multicast search based on both MAC Address and Key ID. By default, + * this feature is enabled. But since the driver is not using this + * feature, we switch it off; otherwise multicast search based on + * MAC addr only will fail. + */ + val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE); + REG_WRITE(ah, AR_PCU_MISC_MODE2, + val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE); +} + +static void ar9003_hw_prog_ini(struct ath_hw *ah, + struct ar5416IniArray *iniArr, + int column) +{ + unsigned int i, regWrites = 0; + + /* New INI format: Array may be undefined (pre, core, post arrays) */ + if (!iniArr->ia_array) + return; + + /* + * New INI format: Pre, core, and post arrays for a given subsystem + * may be modal (> 2 columns) or non-modal (2 columns). Determine if + * the array is non-modal and force the column to 1. + */ + if (column >= iniArr->ia_columns) + column = 1; + + for (i = 0; i < iniArr->ia_rows; i++) { + u32 reg = INI_RA(iniArr, i, 0); + u32 val = INI_RA(iniArr, i, column); + + REG_WRITE(ah, reg, val); + + /* + * Determine if this is a shift register value, and insert the + * configured delay if so. + */ + if (reg >= 0x16000 && reg < 0x17000 + && ah->config.analog_shiftreg) + udelay(100); + + DO_DELAY(regWrites); + } +} + static int ar9003_hw_process_ini(struct ath_hw *ah, struct ath9k_channel *chan) { - /* TODO */ - return -1; + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + unsigned int regWrites = 0, i; + struct ieee80211_channel *channel = chan->chan; + u32 modesIndex, freqIndex; + + switch (chan->chanmode) { + case CHANNEL_A: + case CHANNEL_A_HT20: + modesIndex = 1; + freqIndex = 1; + break; + case CHANNEL_A_HT40PLUS: + case CHANNEL_A_HT40MINUS: + modesIndex = 2; + freqIndex = 1; + break; + case CHANNEL_G: + case CHANNEL_G_HT20: + case CHANNEL_B: + modesIndex = 4; + freqIndex = 2; + break; + case CHANNEL_G_HT40PLUS: + case CHANNEL_G_HT40MINUS: + modesIndex = 3; + freqIndex = 2; + break; + + default: + return -EINVAL; + } + + for (i = 0; i < ATH_INI_NUM_SPLIT; i++) { + ar9003_hw_prog_ini(ah, &ah->iniSOC[i], modesIndex); + ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex); + ar9003_hw_prog_ini(ah, &ah->iniBB[i], modesIndex); + ar9003_hw_prog_ini(ah, &ah->iniRadio[i], modesIndex); + } + + REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites); + REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); + + /* + * For 5GHz channels requiring Fast Clock, apply + * different modal values. + */ + if (IS_CHAN_A_5MHZ_SPACED(chan)) + REG_WRITE_ARRAY(&ah->iniModesAdditional, + modesIndex, regWrites); + + ar9003_hw_override_ini(ah); + ar9003_hw_set_channel_regs(ah, chan); + ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); + + /* Set TX power */ + ah->eep_ops->set_txpower(ah, chan, + ath9k_regd_get_ctl(regulatory, chan), + channel->max_antenna_gain * 2, + channel->max_power * 2, + min((u32) MAX_RATE_POWER, + (u32) regulatory->power_limit)); + + return 0; } static void ar9003_hw_set_rfmode(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 2e51e5795a31..70e647b13e0a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -801,4 +801,6 @@ #define AR_PHY_BB_WD_STATUS_CLR 0x00000008 +void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); + #endif /* AR9003_PHY_H */ diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 9d632861aaff..96b2cfee8e33 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1756,4 +1756,17 @@ enum { #define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */ #define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */ +#define AR_AGG_WEP_ENABLE_FIX 0x00000008 /* This allows the use of AR_AGG_WEP_ENABLE */ +#define AR_ADHOC_MCAST_KEYID_ENABLE 0x00000040 /* This bit enables the Multicast search + * based on both MAC Address and Key ID. + * If bit is 0, then Multicast search is + * based on MAC address only. + * For Merlin and above only. + */ +#define AR_AGG_WEP_ENABLE 0x00020000 /* This field enables AGG_WEP feature, + * when it is enable, AGG_WEP would takes + * charge of the encryption interface of + * pcu_txsm. + */ + #endif -- cgit v1.2.3 From c16fcb49b3849b4dceec9e4bbeb013b0713c7b38 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Apr 2010 17:38:39 -0400 Subject: ath9k_hw: Split off ANI control to the PHY ops Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 186 +--------------------------- drivers/net/wireless/ath/ath9k/ar5008_phy.c | 184 +++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_phy.c | 8 ++ drivers/net/wireless/ath/ath9k/hw-ops.h | 6 + drivers/net/wireless/ath/ath9k/hw.h | 2 + 5 files changed, 201 insertions(+), 185 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 031802c8c125..5a2d867a4e92 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -15,7 +15,7 @@ */ #include "hw.h" -#include "ar9002_phy.h" +#include "hw-ops.h" static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, struct ath9k_channel *chan) @@ -38,190 +38,6 @@ static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, return 0; } -static bool ath9k_hw_ani_control(struct ath_hw *ah, - enum ath9k_ani_cmd cmd, int param) -{ - struct ar5416AniState *aniState = ah->curani; - struct ath_common *common = ath9k_hw_common(ah); - - switch (cmd & ah->ani_function) { - case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ - u32 level = param; - - if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { - ath_print(common, ATH_DBG_ANI, - "level out of range (%u > %u)\n", - level, - (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); - return false; - } - - REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, - AR_PHY_DESIRED_SZ_TOT_DES, - ah->totalSizeDesired[level]); - REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, - AR_PHY_AGC_CTL1_COARSE_LOW, - ah->coarse_low[level]); - REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, - AR_PHY_AGC_CTL1_COARSE_HIGH, - ah->coarse_high[level]); - REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, - AR_PHY_FIND_SIG_FIRPWR, - ah->firpwr[level]); - - if (level > aniState->noiseImmunityLevel) - ah->stats.ast_ani_niup++; - else if (level < aniState->noiseImmunityLevel) - ah->stats.ast_ani_nidown++; - aniState->noiseImmunityLevel = level; - break; - } - case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ - const int m1ThreshLow[] = { 127, 50 }; - const int m2ThreshLow[] = { 127, 40 }; - const int m1Thresh[] = { 127, 0x4d }; - const int m2Thresh[] = { 127, 0x40 }; - const int m2CountThr[] = { 31, 16 }; - const int m2CountThrLow[] = { 63, 48 }; - u32 on = param ? 1 : 0; - - REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_M1_THRESH_LOW, - m1ThreshLow[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_M2_THRESH_LOW, - m2ThreshLow[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR, - AR_PHY_SFCORR_M1_THRESH, - m1Thresh[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR, - AR_PHY_SFCORR_M2_THRESH, - m2Thresh[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR, - AR_PHY_SFCORR_M2COUNT_THR, - m2CountThr[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, - m2CountThrLow[on]); - - REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M1_THRESH_LOW, - m1ThreshLow[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M2_THRESH_LOW, - m2ThreshLow[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M1_THRESH, - m1Thresh[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M2_THRESH, - m2Thresh[on]); - - if (on) - REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); - else - REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); - - if (!on != aniState->ofdmWeakSigDetectOff) { - if (on) - ah->stats.ast_ani_ofdmon++; - else - ah->stats.ast_ani_ofdmoff++; - aniState->ofdmWeakSigDetectOff = !on; - } - break; - } - case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ - const int weakSigThrCck[] = { 8, 6 }; - u32 high = param ? 1 : 0; - - REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, - AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, - weakSigThrCck[high]); - if (high != aniState->cckWeakSigThreshold) { - if (high) - ah->stats.ast_ani_cckhigh++; - else - ah->stats.ast_ani_ccklow++; - aniState->cckWeakSigThreshold = high; - } - break; - } - case ATH9K_ANI_FIRSTEP_LEVEL:{ - const int firstep[] = { 0, 4, 8 }; - u32 level = param; - - if (level >= ARRAY_SIZE(firstep)) { - ath_print(common, ATH_DBG_ANI, - "level out of range (%u > %u)\n", - level, - (unsigned) ARRAY_SIZE(firstep)); - return false; - } - REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, - AR_PHY_FIND_SIG_FIRSTEP, - firstep[level]); - if (level > aniState->firstepLevel) - ah->stats.ast_ani_stepup++; - else if (level < aniState->firstepLevel) - ah->stats.ast_ani_stepdown++; - aniState->firstepLevel = level; - break; - } - case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ - const int cycpwrThr1[] = - { 2, 4, 6, 8, 10, 12, 14, 16 }; - u32 level = param; - - if (level >= ARRAY_SIZE(cycpwrThr1)) { - ath_print(common, ATH_DBG_ANI, - "level out of range (%u > %u)\n", - level, - (unsigned) ARRAY_SIZE(cycpwrThr1)); - return false; - } - REG_RMW_FIELD(ah, AR_PHY_TIMING5, - AR_PHY_TIMING5_CYCPWR_THR1, - cycpwrThr1[level]); - if (level > aniState->spurImmunityLevel) - ah->stats.ast_ani_spurup++; - else if (level < aniState->spurImmunityLevel) - ah->stats.ast_ani_spurdown++; - aniState->spurImmunityLevel = level; - break; - } - case ATH9K_ANI_PRESENT: - break; - default: - ath_print(common, ATH_DBG_ANI, - "invalid cmd %u\n", cmd); - return false; - } - - ath_print(common, ATH_DBG_ANI, "ANI parameters:\n"); - ath_print(common, ATH_DBG_ANI, - "noiseImmunityLevel=%d, spurImmunityLevel=%d, " - "ofdmWeakSigDetectOff=%d\n", - aniState->noiseImmunityLevel, - aniState->spurImmunityLevel, - !aniState->ofdmWeakSigDetectOff); - ath_print(common, ATH_DBG_ANI, - "cckWeakSigThreshold=%d, " - "firstepLevel=%d, listenTime=%d\n", - aniState->cckWeakSigThreshold, - aniState->firstepLevel, - aniState->listenTime); - ath_print(common, ATH_DBG_ANI, - "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", - aniState->cycleCount, - aniState->ofdmPhyErrCount, - aniState->cckPhyErrCount); - - return true; -} - static void ath9k_hw_update_mibstats(struct ath_hw *ah, struct ath9k_mib_stats *stats) { diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 9685f4c6fc99..dddca59ea46d 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -1015,6 +1015,189 @@ static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah, return pll; } +static bool ar5008_hw_ani_control(struct ath_hw *ah, + enum ath9k_ani_cmd cmd, int param) +{ + struct ar5416AniState *aniState = ah->curani; + struct ath_common *common = ath9k_hw_common(ah); + + switch (cmd & ah->ani_function) { + case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ + u32 level = param; + + if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { + ath_print(common, ATH_DBG_ANI, + "level out of range (%u > %u)\n", + level, + (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); + return false; + } + + REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_TOT_DES, + ah->totalSizeDesired[level]); + REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, + AR_PHY_AGC_CTL1_COARSE_LOW, + ah->coarse_low[level]); + REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, + AR_PHY_AGC_CTL1_COARSE_HIGH, + ah->coarse_high[level]); + REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRPWR, + ah->firpwr[level]); + + if (level > aniState->noiseImmunityLevel) + ah->stats.ast_ani_niup++; + else if (level < aniState->noiseImmunityLevel) + ah->stats.ast_ani_nidown++; + aniState->noiseImmunityLevel = level; + break; + } + case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ + const int m1ThreshLow[] = { 127, 50 }; + const int m2ThreshLow[] = { 127, 40 }; + const int m1Thresh[] = { 127, 0x4d }; + const int m2Thresh[] = { 127, 0x40 }; + const int m2CountThr[] = { 31, 16 }; + const int m2CountThrLow[] = { 63, 48 }; + u32 on = param ? 1 : 0; + + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M1_THRESH_LOW, + m1ThreshLow[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2_THRESH_LOW, + m2ThreshLow[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M1_THRESH, + m1Thresh[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2_THRESH, + m2Thresh[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2COUNT_THR, + m2CountThr[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, + m2CountThrLow[on]); + + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH_LOW, + m1ThreshLow[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH_LOW, + m2ThreshLow[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH, + m1Thresh[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH, + m2Thresh[on]); + + if (on) + REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + else + REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + + if (!on != aniState->ofdmWeakSigDetectOff) { + if (on) + ah->stats.ast_ani_ofdmon++; + else + ah->stats.ast_ani_ofdmoff++; + aniState->ofdmWeakSigDetectOff = !on; + } + break; + } + case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ + const int weakSigThrCck[] = { 8, 6 }; + u32 high = param ? 1 : 0; + + REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, + AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, + weakSigThrCck[high]); + if (high != aniState->cckWeakSigThreshold) { + if (high) + ah->stats.ast_ani_cckhigh++; + else + ah->stats.ast_ani_ccklow++; + aniState->cckWeakSigThreshold = high; + } + break; + } + case ATH9K_ANI_FIRSTEP_LEVEL:{ + const int firstep[] = { 0, 4, 8 }; + u32 level = param; + + if (level >= ARRAY_SIZE(firstep)) { + ath_print(common, ATH_DBG_ANI, + "level out of range (%u > %u)\n", + level, + (unsigned) ARRAY_SIZE(firstep)); + return false; + } + REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRSTEP, + firstep[level]); + if (level > aniState->firstepLevel) + ah->stats.ast_ani_stepup++; + else if (level < aniState->firstepLevel) + ah->stats.ast_ani_stepdown++; + aniState->firstepLevel = level; + break; + } + case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ + const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; + u32 level = param; + + if (level >= ARRAY_SIZE(cycpwrThr1)) { + ath_print(common, ATH_DBG_ANI, + "level out of range (%u > %u)\n", + level, + (unsigned) ARRAY_SIZE(cycpwrThr1)); + return false; + } + REG_RMW_FIELD(ah, AR_PHY_TIMING5, + AR_PHY_TIMING5_CYCPWR_THR1, + cycpwrThr1[level]); + if (level > aniState->spurImmunityLevel) + ah->stats.ast_ani_spurup++; + else if (level < aniState->spurImmunityLevel) + ah->stats.ast_ani_spurdown++; + aniState->spurImmunityLevel = level; + break; + } + case ATH9K_ANI_PRESENT: + break; + default: + ath_print(common, ATH_DBG_ANI, + "invalid cmd %u\n", cmd); + return false; + } + + ath_print(common, ATH_DBG_ANI, "ANI parameters:\n"); + ath_print(common, ATH_DBG_ANI, + "noiseImmunityLevel=%d, spurImmunityLevel=%d, " + "ofdmWeakSigDetectOff=%d\n", + aniState->noiseImmunityLevel, + aniState->spurImmunityLevel, + !aniState->ofdmWeakSigDetectOff); + ath_print(common, ATH_DBG_ANI, + "cckWeakSigThreshold=%d, " + "firstepLevel=%d, listenTime=%d\n", + aniState->cckWeakSigThreshold, + aniState->firstepLevel, + aniState->listenTime); + ath_print(common, ATH_DBG_ANI, + "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", + aniState->cycleCount, + aniState->ofdmPhyErrCount, + aniState->cckPhyErrCount); + + return true; +} + void ar5008_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); @@ -1036,6 +1219,7 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->enable_rfkill = ar5008_hw_enable_rfkill; priv_ops->restore_chainmask = ar5008_restore_chainmask; priv_ops->set_diversity = ar5008_set_diversity; + priv_ops->ani_control = ar5008_hw_ani_control; if (AR_SREV_9100(ah)) priv_ops->compute_pll_control = ar9100_hw_compute_pll_control; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index acbf122a150d..356e03db9cf1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -420,6 +420,13 @@ static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value) /* TODO */ } +static bool ar9003_hw_ani_control(struct ath_hw *ah, + enum ath9k_ani_cmd cmd, int param) +{ + /* TODO */ + return false; +} + void ar9003_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); @@ -437,4 +444,5 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->rfbus_done = ar9003_hw_rfbus_done; priv_ops->enable_rfkill = ar9003_hw_enable_rfkill; priv_ops->set_diversity = ar9003_hw_set_diversity; + priv_ops->ani_control = ar9003_hw_ani_control; } diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 19259fbad507..08a51a267681 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -146,4 +146,10 @@ static inline void ath9k_hw_set_diversity(struct ath_hw *ah, bool value) return ath9k_hw_private_ops(ah)->set_diversity(ah, value); } +static inline bool ath9k_hw_ani_control(struct ath_hw *ah, + enum ath9k_ani_cmd cmd, int param) +{ + return ath9k_hw_private_ops(ah)->ani_control(ah, cmd, param); +} + #endif /* ATH9K_HW_OPS_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index c3928be63b3a..b0cfc77a66fc 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -508,6 +508,8 @@ struct ath_hw_private_ops { void (*set_diversity)(struct ath_hw *ah, bool value); u32 (*compute_pll_control)(struct ath_hw *ah, struct ath9k_channel *chan); + bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd, + int param); }; /** -- cgit v1.2.3 From af914a9ffd60a841054e9fd248f12630df0698c5 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:40 -0400 Subject: ath9k_hw: add all the AR9003 PHY callbacks Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 300 +++++++++++++++++++++++++++- 1 file changed, 289 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 356e03db9cf1..c938b85c174e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -225,7 +225,30 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah, static void ar9003_hw_init_bb(struct ath_hw *ah, struct ath9k_channel *chan) { - /* TODO */ + u32 synthDelay; + + /* + * Wait for the frequency synth to settle (synth goes on + * via AR_PHY_ACTIVE_EN). Read the phy active delay register. + * Value is in 100ns increments. + */ + synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IS_CHAN_B(chan)) + synthDelay = (4 * synthDelay) / 22; + else + synthDelay /= 10; + + /* Activate the PHY (includes baseband activate + synthesizer on) */ + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + + /* + * There is an issue if the AP starts the calibration before + * the base band timeout completes. This could result in the + * rx_clear false triggering. As a workaround we add delay an + * extra BASE_ACTIVATE_DELAY usecs to ensure this condition + * does not happen. + */ + udelay(synthDelay + BASE_ACTIVATE_DELAY); } void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) @@ -385,46 +408,301 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, static void ar9003_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan) { - /* TODO */ + u32 rfMode = 0; + + if (chan == NULL) + return; + + rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) + ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; + + if (IS_CHAN_A_5MHZ_SPACED(chan)) + rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); + + REG_WRITE(ah, AR_PHY_MODE, rfMode); } static void ar9003_hw_mark_phy_inactive(struct ath_hw *ah) { - /* TODO */ + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); } static void ar9003_hw_set_delta_slope(struct ath_hw *ah, struct ath9k_channel *chan) { - /* TODO */ + u32 coef_scaled, ds_coef_exp, ds_coef_man; + u32 clockMhzScaled = 0x64000000; + struct chan_centers centers; + + /* + * half and quarter rate can divide the scaled clock by 2 or 4 + * scale for selected channel bandwidth + */ + if (IS_CHAN_HALF_RATE(chan)) + clockMhzScaled = clockMhzScaled >> 1; + else if (IS_CHAN_QUARTER_RATE(chan)) + clockMhzScaled = clockMhzScaled >> 2; + + /* + * ALGO -> coef = 1e8/fcarrier*fclock/40; + * scaled coef to provide precision for this floating calculation + */ + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + coef_scaled = clockMhzScaled / centers.synth_center; + + ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, + &ds_coef_exp); + + REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_MAN, ds_coef_man); + REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); + + /* + * For Short GI, + * scaled coeff is 9/10 that of normal coeff + */ + coef_scaled = (9 * coef_scaled) / 10; + + ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, + &ds_coef_exp); + + /* for short gi */ + REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA, + AR_PHY_SGI_DSC_MAN, ds_coef_man); + REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA, + AR_PHY_SGI_DSC_EXP, ds_coef_exp); } static bool ar9003_hw_rfbus_req(struct ath_hw *ah) { - /* TODO */ - return false; + REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); + return ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, + AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT); } +/* + * Wait for the frequency synth to settle (synth goes on via PHY_ACTIVE_EN). + * Read the phy active delay register. Value is in 100ns increments. + */ static void ar9003_hw_rfbus_done(struct ath_hw *ah) { - /* TODO */ + u32 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IS_CHAN_B(ah->curchan)) + synthDelay = (4 * synthDelay) / 22; + else + synthDelay /= 10; + + udelay(synthDelay + BASE_ACTIVATE_DELAY); + + REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); } +/* + * Set the interrupt and GPIO values so the ISR can disable RF + * on a switch signal. Assumes GPIO port and interrupt polarity + * are set prior to call. + */ static void ar9003_hw_enable_rfkill(struct ath_hw *ah) { - /* TODO */ + /* Connect rfsilent_bb_l to baseband */ + REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, + AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); + /* Set input mux for rfsilent_bb_l to GPIO #0 */ + REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, + AR_GPIO_INPUT_MUX2_RFSILENT); + + /* + * Configure the desired GPIO port for input and + * enable baseband rf silence. + */ + ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); + REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); } static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value) { - /* TODO */ + u32 v = REG_READ(ah, AR_PHY_CCK_DETECT); + if (value) + v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; + else + v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; + REG_WRITE(ah, AR_PHY_CCK_DETECT, v); } static bool ar9003_hw_ani_control(struct ath_hw *ah, enum ath9k_ani_cmd cmd, int param) { - /* TODO */ - return false; + struct ar5416AniState *aniState = ah->curani; + struct ath_common *common = ath9k_hw_common(ah); + + switch (cmd & ah->ani_function) { + case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ + u32 level = param; + + if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { + ath_print(common, ATH_DBG_ANI, + "level out of range (%u > %u)\n", + level, + (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); + return false; + } + + REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_TOT_DES, + ah->totalSizeDesired[level]); + REG_RMW_FIELD(ah, AR_PHY_AGC, + AR_PHY_AGC_COARSE_LOW, + ah->coarse_low[level]); + REG_RMW_FIELD(ah, AR_PHY_AGC, + AR_PHY_AGC_COARSE_HIGH, + ah->coarse_high[level]); + REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRPWR, ah->firpwr[level]); + + if (level > aniState->noiseImmunityLevel) + ah->stats.ast_ani_niup++; + else if (level < aniState->noiseImmunityLevel) + ah->stats.ast_ani_nidown++; + aniState->noiseImmunityLevel = level; + break; + } + case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ + const int m1ThreshLow[] = { 127, 50 }; + const int m2ThreshLow[] = { 127, 40 }; + const int m1Thresh[] = { 127, 0x4d }; + const int m2Thresh[] = { 127, 0x40 }; + const int m2CountThr[] = { 31, 16 }; + const int m2CountThrLow[] = { 63, 48 }; + u32 on = param ? 1 : 0; + + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M1_THRESH_LOW, + m1ThreshLow[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2_THRESH_LOW, + m2ThreshLow[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, + m2CountThrLow[on]); + + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]); + + if (on) + REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + else + REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + + if (!on != aniState->ofdmWeakSigDetectOff) { + if (on) + ah->stats.ast_ani_ofdmon++; + else + ah->stats.ast_ani_ofdmoff++; + aniState->ofdmWeakSigDetectOff = !on; + } + break; + } + case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ + const int weakSigThrCck[] = { 8, 6 }; + u32 high = param ? 1 : 0; + + REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, + AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, + weakSigThrCck[high]); + if (high != aniState->cckWeakSigThreshold) { + if (high) + ah->stats.ast_ani_cckhigh++; + else + ah->stats.ast_ani_ccklow++; + aniState->cckWeakSigThreshold = high; + } + break; + } + case ATH9K_ANI_FIRSTEP_LEVEL:{ + const int firstep[] = { 0, 4, 8 }; + u32 level = param; + + if (level >= ARRAY_SIZE(firstep)) { + ath_print(common, ATH_DBG_ANI, + "level out of range (%u > %u)\n", + level, + (unsigned) ARRAY_SIZE(firstep)); + return false; + } + REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRSTEP, + firstep[level]); + if (level > aniState->firstepLevel) + ah->stats.ast_ani_stepup++; + else if (level < aniState->firstepLevel) + ah->stats.ast_ani_stepdown++; + aniState->firstepLevel = level; + break; + } + case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ + const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; + u32 level = param; + + if (level >= ARRAY_SIZE(cycpwrThr1)) { + ath_print(common, ATH_DBG_ANI, + "level out of range (%u > %u)\n", + level, + (unsigned) ARRAY_SIZE(cycpwrThr1)); + return false; + } + REG_RMW_FIELD(ah, AR_PHY_TIMING5, + AR_PHY_TIMING5_CYCPWR_THR1, + cycpwrThr1[level]); + if (level > aniState->spurImmunityLevel) + ah->stats.ast_ani_spurup++; + else if (level < aniState->spurImmunityLevel) + ah->stats.ast_ani_spurdown++; + aniState->spurImmunityLevel = level; + break; + } + case ATH9K_ANI_PRESENT: + break; + default: + ath_print(common, ATH_DBG_ANI, + "invalid cmd %u\n", cmd); + return false; + } + + ath_print(common, ATH_DBG_ANI, "ANI parameters:\n"); + ath_print(common, ATH_DBG_ANI, + "noiseImmunityLevel=%d, spurImmunityLevel=%d, " + "ofdmWeakSigDetectOff=%d\n", + aniState->noiseImmunityLevel, + aniState->spurImmunityLevel, + !aniState->ofdmWeakSigDetectOff); + ath_print(common, ATH_DBG_ANI, + "cckWeakSigThreshold=%d, " + "firstepLevel=%d, listenTime=%d\n", + aniState->cckWeakSigThreshold, + aniState->firstepLevel, + aniState->listenTime); + ath_print(common, ATH_DBG_ANI, + "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", + aniState->cycleCount, + aniState->ofdmPhyErrCount, + aniState->cckPhyErrCount); + + return true; } void ar9003_hw_attach_phy_ops(struct ath_hw *ah) -- cgit v1.2.3 From 162c3be3780dcb241ce0c9d49626c6cfb90f9f61 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:38:41 -0400 Subject: ath9k_hw: Define tx control struct for AR9003 Store appropriate desc length which will be used by the ath9k module while duplicating tx desc. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.h | 28 ++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/hw.c | 3 +++ drivers/net/wireless/ath/ath9k/hw.h | 1 + 3 files changed, 32 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index b22f78c320c5..7374439a836c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h @@ -37,6 +37,34 @@ struct ar9003_rxs { u32 status11; } __packed; +/* Transmit Control Descriptor */ +struct ar9003_txc { + u32 info; /* descriptor information */ + u32 link; /* link pointer */ + u32 data0; /* data pointer to 1st buffer */ + u32 ctl3; /* DMA control 3 */ + u32 data1; /* data pointer to 2nd buffer */ + u32 ctl5; /* DMA control 5 */ + u32 data2; /* data pointer to 3rd buffer */ + u32 ctl7; /* DMA control 7 */ + u32 data3; /* data pointer to 4th buffer */ + u32 ctl9; /* DMA control 9 */ + u32 ctl10; /* DMA control 10 */ + u32 ctl11; /* DMA control 11 */ + u32 ctl12; /* DMA control 12 */ + u32 ctl13; /* DMA control 13 */ + u32 ctl14; /* DMA control 14 */ + u32 ctl15; /* DMA control 15 */ + u32 ctl16; /* DMA control 16 */ + u32 ctl17; /* DMA control 17 */ + u32 ctl18; /* DMA control 18 */ + u32 ctl19; /* DMA control 19 */ + u32 ctl20; /* DMA control 20 */ + u32 ctl21; /* DMA control 21 */ + u32 ctl22; /* DMA control 22 */ + u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */ +} __packed; + void ar9003_hw_attach_mac_ops(struct ath_hw *hw); void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size); void ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp, diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 4bfb3a847920..f45e724c841f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2961,6 +2961,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH; pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH; pCap->rx_status_len = sizeof(struct ar9003_rxs); + pCap->tx_desc_len = sizeof(struct ar9003_txc); + } else { + pCap->tx_desc_len = sizeof(struct ath_desc); } return 0; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index b0cfc77a66fc..ce9d12bd1759 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -206,6 +206,7 @@ struct ath9k_hw_capabilities { u8 rx_hp_qdepth; u8 rx_lp_qdepth; u8 rx_status_len; + u8 tx_desc_len; }; struct ath9k_ops_config { -- cgit v1.2.3 From 3f3a1c8031fd87a7d0195d0a8e8101d04c283fcc Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:38:42 -0400 Subject: ath9k_hw: Move code which populates ds_data to ath9k_hw Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 4 +--- drivers/net/wireless/ath/ath9k/mac.c | 5 ++++- drivers/net/wireless/ath/ath9k/mac.h | 3 ++- drivers/net/wireless/ath/ath9k/xmit.c | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 22375a754718..268b598746f6 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -93,8 +93,6 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); } - ds->ds_data = bf->bf_buf_addr; - sband = &sc->sbands[common->hw->conf.channel->band]; rate = sband->bitrates[rateidx].hw_value; if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) @@ -109,7 +107,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, /* NB: beacon's BufLen must be a multiple of 4 bytes */ ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4), - true, true, ds); + true, true, ds, bf->bf_buf_addr); memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); series[0].Tries = 1; diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index ae9d54c9c79a..0c9c378616c6 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -220,10 +220,13 @@ EXPORT_SYMBOL(ath9k_hw_stoptxdma); void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, u32 segLen, bool firstSeg, - bool lastSeg, const struct ath_desc *ds0) + bool lastSeg, const struct ath_desc *ds0, + dma_addr_t buf_addr) { struct ar5416_desc *ads = AR5416DESC(ds); + ads->ds_data = buf_addr; + if (firstSeg) { ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore); } else if (lastSeg) { diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 126a4030be1d..f2f4ad253696 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -693,7 +693,8 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, u32 segLen, bool firstSeg, - bool lastSeg, const struct ath_desc *ds0); + bool lastSeg, const struct ath_desc *ds0, + dma_addr_t buf_addr); void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, struct ath_tx_status *ts); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 02df4cbf179f..7219e2927705 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1660,7 +1660,6 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, ds = bf->bf_desc; ds->ds_link = 0; - ds->ds_data = bf->bf_buf_addr; ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER, bf->bf_keyix, bf->bf_keytype, bf->bf_flags); @@ -1669,7 +1668,8 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, skb->len, /* segment length */ true, /* first segment */ true, /* last segment */ - ds); /* first descriptor */ + ds, /* first descriptor */ + bf->bf_buf_addr); spin_lock_bh(&txctl->txq->axq_lock); -- cgit v1.2.3 From 87d5efbbd6b6df6111404f9c12ad1b9a957498c5 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:38:43 -0400 Subject: ath9k_hw: Add abstraction to set/get link pointer Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 12 ++++++++++++ drivers/net/wireless/ath/ath9k/hw-ops.h | 11 +++++++++++ drivers/net/wireless/ath/ath9k/hw.h | 2 ++ drivers/net/wireless/ath/ath9k/mac.c | 13 +++++++++++++ drivers/net/wireless/ath/ath9k/xmit.c | 7 ++++--- 5 files changed, 42 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 20890060ee2c..f28adb23ac83 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -20,11 +20,23 @@ static void ar9003_hw_rx_enable(struct ath_hw *hw) REG_WRITE(hw, AR_CR, 0); } +static void ar9003_hw_set_desc_link(void *ds, u32 ds_link) +{ + ((struct ar9003_txc *) ds)->link = ds_link; +} + +static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link) +{ + *ds_link = &((struct ar9003_txc *) ds)->link; +} + void ar9003_hw_attach_mac_ops(struct ath_hw *hw) { struct ath_hw_ops *ops = ath9k_hw_ops(hw); ops->rx_enable = ar9003_hw_rx_enable; + ops->set_desc_link = ar9003_hw_set_desc_link; + ops->get_desc_link = ar9003_hw_get_desc_link; } void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 08a51a267681..a7701079a88a 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -33,6 +33,17 @@ static inline void ath9k_hw_rxena(struct ath_hw *ah) ath9k_hw_ops(ah)->rx_enable(ah); } +static inline void ath9k_hw_set_desc_link(struct ath_hw *ah, void *ds, + u32 link) +{ + ath9k_hw_ops(ah)->set_desc_link(ds, link); +} + +static inline void ath9k_hw_get_desc_link(struct ath_hw *ah, void *ds, + u32 **link) +{ + ath9k_hw_ops(ah)->get_desc_link(ds, link); +} /* Private hardware call ops */ /* PHY ops */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ce9d12bd1759..c02f46e4a9b8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -526,6 +526,8 @@ struct ath_hw_ops { int restore, int power_off); void (*rx_enable)(struct ath_hw *ah); + void (*set_desc_link)(void *ds, u32 link); + void (*get_desc_link)(void *ds, u32 **link); }; struct ath_hw { diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 0c9c378616c6..a8dab23622f1 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -21,12 +21,25 @@ static void ar9002_hw_rx_enable(struct ath_hw *ah) REG_WRITE(ah, AR_CR, AR_CR_RXE); } +static void ar9002_hw_set_desc_link(void *ds, u32 ds_link) +{ + ((struct ath_desc *) ds)->ds_link = ds_link; +} + +static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link) +{ + *ds_link = &((struct ath_desc *)ds)->ds_link; +} + void ar9002_hw_attach_mac_ops(struct ath_hw *ah) { struct ath_hw_ops *ops = ath9k_hw_ops(ah); ops->rx_enable = ar9002_hw_rx_enable; + ops->set_desc_link = ar9002_hw_set_desc_link; + ops->get_desc_link = ar9002_hw_get_desc_link; } + static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, struct ath9k_tx_queue_info *qi) { diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 7219e2927705..4f12de99492d 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -665,7 +665,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, bpad = PADBYTES(al_delta) + (ndelim << 2); bf->bf_next = NULL; - bf->bf_desc->ds_link = 0; + ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0); /* link buffers of this frame to the aggregate */ ath_tx_addto_baw(sc, tid, bf); @@ -673,7 +673,8 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, list_move_tail(&bf->list, bf_q); if (bf_prev) { bf_prev->bf_next = bf; - bf_prev->bf_desc->ds_link = bf->bf_daddr; + ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc, + bf->bf_daddr); } bf_prev = bf; @@ -1659,7 +1660,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, list_add_tail(&bf->list, &bf_head); ds = bf->bf_desc; - ds->ds_link = 0; + ath9k_hw_set_desc_link(ah, ds, 0); ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER, bf->bf_keyix, bf->bf_keytype, bf->bf_flags); -- cgit v1.2.3 From 5c3a338fcfd25de1f8434f9e504aa7e2a425d3ce Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:38:44 -0400 Subject: ath9k: Use abstraction to get link pointer Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 4f12de99492d..16f7a3d2d5ea 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1242,7 +1242,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, txq->axq_qnum, txq->axq_link, ito64(bf->bf_daddr), bf->bf_desc); } - txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link); + ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc, &txq->axq_link); ath9k_hw_txstart(ah, txq->axq_qnum); } -- cgit v1.2.3 From d826c83277a2a661cd0d37d051d5a4931b8463ff Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:38:45 -0400 Subject: ath9k: Use memcpy in ath_clone_txbuf() Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 16f7a3d2d5ea..4bc52f4a0ad3 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -279,7 +279,7 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) tbf->aphy = bf->aphy; tbf->bf_mpdu = bf->bf_mpdu; tbf->bf_buf_addr = bf->bf_buf_addr; - *(tbf->bf_desc) = *(bf->bf_desc); + memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len); tbf->bf_state = bf->bf_state; tbf->bf_dmacontext = bf->bf_dmacontext; -- cgit v1.2.3 From 6d913f7db3ff5cc5c9b673d8db8e4a8b9f86d85b Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:38:46 -0400 Subject: ath9k: Remove ATH9K_TX_SW_ABORTED and introduce a bool for this purpose Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/common.h | 1 + drivers/net/wireless/ath/ath9k/mac.h | 1 - drivers/net/wireless/ath/ath9k/xmit.c | 9 ++++----- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 1a87283a0941..5fd7fe10d7ea 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -82,6 +82,7 @@ struct ath_buf { dma_addr_t bf_buf_addr; /* physical addr of data buffer */ bool bf_stale; bool bf_isnullfunc; + bool bf_tx_aborted; u16 bf_flags; struct ath_buf_state bf_state; dma_addr_t bf_dmacontext; diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index f2f4ad253696..99f81ebb35bf 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -86,7 +86,6 @@ #define ATH9K_TX_DESC_CFG_ERR 0x04 #define ATH9K_TX_DATA_UNDERRUN 0x08 #define ATH9K_TX_DELIM_UNDERRUN 0x10 -#define ATH9K_TX_SW_ABORTED 0x40 #define ATH9K_TX_SW_FILTERED 0x80 /* 64 bytes */ diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 4bc52f4a0ad3..6ab20992ba30 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -359,7 +359,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, acked_cnt++; } else { if (!(tid->state & AGGR_CLEANUP) && - ts->ts_flags != ATH9K_TX_SW_ABORTED) { + !bf_last->bf_tx_aborted) { if (bf->bf_retries < ATH_MAX_SW_RETRIES) { ath_tx_set_retry(sc, txq, bf); txpending = 1; @@ -1036,9 +1036,6 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) struct ath_tx_status ts; memset(&ts, 0, sizeof(ts)); - if (!retry_tx) - ts.ts_flags = ATH9K_TX_SW_ABORTED; - INIT_LIST_HEAD(&bf_head); for (;;) { @@ -1063,6 +1060,8 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) } lastbf = bf->bf_lastbf; + if (!retry_tx) + lastbf->bf_tx_aborted = true; /* remove ath_buf's of the same mpdu from txq */ list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); @@ -1897,7 +1896,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, int nbad = 0; int isaggr = 0; - if (ts->ts_flags == ATH9K_TX_SW_ABORTED) + if (bf->bf_tx_aborted) return 0; isaggr = bf_isaggr(bf); -- cgit v1.2.3 From c38d4d2eb988717f7a8be24faeada648b5dac52a Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:38:47 -0400 Subject: ath9k: Make bf_desc of ath_buf opaque Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 5fd7fe10d7ea..e08f7e5a26e0 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -77,7 +77,7 @@ struct ath_buf { an aggregate) */ struct ath_buf *bf_next; /* next subframe in the aggregate */ struct sk_buff *bf_mpdu; /* enclosing frame structure */ - struct ath_desc *bf_desc; /* virtual addr of desc */ + void *bf_desc; /* virtual addr of desc */ dma_addr_t bf_daddr; /* physical addr of desc */ dma_addr_t bf_buf_addr; /* physical addr of data buffer */ bool bf_stale; -- cgit v1.2.3 From b5c80475abaad015699384ca64ef8229fdd88758 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Apr 2010 17:38:48 -0400 Subject: ath9k: Add Rx EDMA support Signed-off-by: Felix Fietkau Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 3 + drivers/net/wireless/ath/ath9k/ath9k.h | 10 +- drivers/net/wireless/ath/ath9k/hw.h | 2 + drivers/net/wireless/ath/ath9k/main.c | 40 ++- drivers/net/wireless/ath/ath9k/recv.c | 517 ++++++++++++++++++++++------ 5 files changed, 459 insertions(+), 113 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index f28adb23ac83..b229597e54cd 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -72,6 +72,9 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0) return -EINPROGRESS; + if (!rxs) + return 0; + rxs->rs_status = 0; rxs->rs_flags = 0; diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index bdcd257ca7a4..a11d830d76a9 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -223,6 +223,12 @@ struct ath_tx { struct ath_descdma txdma; }; +struct ath_rx_edma { + struct sk_buff_head rx_fifo; + struct sk_buff_head rx_buffers; + u32 rx_fifo_hwsize; +}; + struct ath_rx { u8 defant; u8 rxotherant; @@ -232,6 +238,8 @@ struct ath_rx { spinlock_t rxbuflock; struct list_head rxbuf; struct ath_descdma rxdma; + struct ath_buf *rx_bufptr; + struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; }; int ath_startrecv(struct ath_softc *sc); @@ -240,7 +248,7 @@ void ath_flushrecv(struct ath_softc *sc); u32 ath_calcrxfilter(struct ath_softc *sc); int ath_rx_init(struct ath_softc *sc, int nbufs); void ath_rx_cleanup(struct ath_softc *sc); -int ath_rx_tasklet(struct ath_softc *sc, int flush); +int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp); struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); int ath_tx_setup(struct ath_softc *sc, int haltype); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index c02f46e4a9b8..1eceda22ae5f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -246,6 +246,8 @@ struct ath9k_ops_config { enum ath9k_int { ATH9K_INT_RX = 0x00000001, ATH9K_INT_RXDESC = 0x00000002, + ATH9K_INT_RXHP = 0x00000001, + ATH9K_INT_RXLP = 0x00000002, ATH9K_INT_RXNOFRM = 0x00000008, ATH9K_INT_RXEOL = 0x00000010, ATH9K_INT_RXORN = 0x00000020, diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 494456cd1daa..92f6fdc30076 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -401,6 +401,7 @@ void ath9k_tasklet(unsigned long data) struct ath_common *common = ath9k_hw_common(ah); u32 status = sc->intrstatus; + u32 rxmask; ath9k_ps_wakeup(sc); @@ -410,9 +411,21 @@ void ath9k_tasklet(unsigned long data) return; } - if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { + if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) + rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL | + ATH9K_INT_RXORN); + else + rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN); + + if (status & rxmask) { spin_lock_bh(&sc->rx.rxflushlock); - ath_rx_tasklet(sc, 0); + + /* Check for high priority Rx first */ + if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && + (status & ATH9K_INT_RXHP)) + ath_rx_tasklet(sc, 0, true); + + ath_rx_tasklet(sc, 0, false); spin_unlock_bh(&sc->rx.rxflushlock); } @@ -445,6 +458,8 @@ irqreturn_t ath_isr(int irq, void *dev) ATH9K_INT_RXORN | \ ATH9K_INT_RXEOL | \ ATH9K_INT_RX | \ + ATH9K_INT_RXLP | \ + ATH9K_INT_RXHP | \ ATH9K_INT_TX | \ ATH9K_INT_BMISS | \ ATH9K_INT_CST | \ @@ -496,7 +511,8 @@ irqreturn_t ath_isr(int irq, void *dev) * If a FATAL or RXORN interrupt is received, we have to reset the * chip immediately. */ - if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN)) + if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) && + !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))) goto chip_reset; if (status & ATH9K_INT_SWBA) @@ -505,6 +521,13 @@ irqreturn_t ath_isr(int irq, void *dev) if (status & ATH9K_INT_TXURN) ath9k_hw_updatetxtriglevel(ah, true); + if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { + if (status & ATH9K_INT_RXEOL) { + ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN); + ath9k_hw_set_interrupts(ah, ah->imask); + } + } + if (status & ATH9K_INT_MIB) { /* * Disable interrupts until we service the MIB @@ -1162,9 +1185,14 @@ static int ath9k_start(struct ieee80211_hw *hw) } /* Setup our intr mask. */ - ah->imask = ATH9K_INT_RX | ATH9K_INT_TX - | ATH9K_INT_RXEOL | ATH9K_INT_RXORN - | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; + ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | + ATH9K_INT_RXORN | ATH9K_INT_FATAL | + ATH9K_INT_GLOBAL; + + if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) + ah->imask |= ATH9K_INT_RXHP | ATH9K_INT_RXLP; + else + ah->imask |= ATH9K_INT_RX; if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT) ah->imask |= ATH9K_INT_GTT; diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 94560e2fe376..ffb599c49185 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -16,6 +16,8 @@ #include "ath9k.h" +#define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) + static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc, struct ieee80211_hdr *hdr) { @@ -115,56 +117,246 @@ static void ath_opmode_init(struct ath_softc *sc) ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); } -int ath_rx_init(struct ath_softc *sc, int nbufs) +static bool ath_rx_edma_buf_link(struct ath_softc *sc, + enum ath9k_rx_qtype qtype) { - struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_hw *ah = sc->sc_ah; + struct ath_rx_edma *rx_edma; struct sk_buff *skb; struct ath_buf *bf; - int error = 0; - spin_lock_init(&sc->rx.rxflushlock); - sc->sc_flags &= ~SC_OP_RXFLUSH; - spin_lock_init(&sc->rx.rxbuflock); + rx_edma = &sc->rx.rx_edma[qtype]; + if (skb_queue_len(&rx_edma->rx_fifo) >= rx_edma->rx_fifo_hwsize) + return false; - common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN, - min(common->cachelsz, (u16)64)); + bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); + list_del_init(&bf->list); - ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", - common->cachelsz, common->rx_bufsize); + skb = bf->bf_mpdu; + + ATH_RXBUF_RESET(bf); + memset(skb->data, 0, ah->caps.rx_status_len); + dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, + ah->caps.rx_status_len, DMA_TO_DEVICE); - /* Initialize rx descriptors */ + SKB_CB_ATHBUF(skb) = bf; + ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype); + skb_queue_tail(&rx_edma->rx_fifo, skb); - error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, - "rx", nbufs, 1); - if (error != 0) { - ath_print(common, ATH_DBG_FATAL, - "failed to allocate rx descriptors: %d\n", error); - goto err; + return true; +} + +static void ath_rx_addbuffer_edma(struct ath_softc *sc, + enum ath9k_rx_qtype qtype, int size) +{ + struct ath_rx_edma *rx_edma; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + u32 nbuf = 0; + + rx_edma = &sc->rx.rx_edma[qtype]; + if (list_empty(&sc->rx.rxbuf)) { + ath_print(common, ATH_DBG_QUEUE, "No free rx buf available\n"); + return; } + while (!list_empty(&sc->rx.rxbuf)) { + nbuf++; + + if (!ath_rx_edma_buf_link(sc, qtype)) + break; + + if (nbuf >= size) + break; + } +} + +static void ath_rx_remove_buffer(struct ath_softc *sc, + enum ath9k_rx_qtype qtype) +{ + struct ath_buf *bf; + struct ath_rx_edma *rx_edma; + struct sk_buff *skb; + + rx_edma = &sc->rx.rx_edma[qtype]; + + while ((skb = skb_dequeue(&rx_edma->rx_fifo)) != NULL) { + bf = SKB_CB_ATHBUF(skb); + BUG_ON(!bf); + list_add_tail(&bf->list, &sc->rx.rxbuf); + } +} + +static void ath_rx_edma_cleanup(struct ath_softc *sc) +{ + struct ath_buf *bf; + + ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); + ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); + list_for_each_entry(bf, &sc->rx.rxbuf, list) { + if (bf->bf_mpdu) + dev_kfree_skb_any(bf->bf_mpdu); + } + + INIT_LIST_HEAD(&sc->rx.rxbuf); + + kfree(sc->rx.rx_bufptr); + sc->rx.rx_bufptr = NULL; +} + +static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size) +{ + skb_queue_head_init(&rx_edma->rx_fifo); + skb_queue_head_init(&rx_edma->rx_buffers); + rx_edma->rx_fifo_hwsize = size; +} + +static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) +{ + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_hw *ah = sc->sc_ah; + struct sk_buff *skb; + struct ath_buf *bf; + int error = 0, i; + u32 size; + + + common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN + + ah->caps.rx_status_len, + min(common->cachelsz, (u16)64)); + + ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize - + ah->caps.rx_status_len); + + ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_LP], + ah->caps.rx_lp_qdepth); + ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_HP], + ah->caps.rx_hp_qdepth); + + size = sizeof(struct ath_buf) * nbufs; + bf = kzalloc(size, GFP_KERNEL); + if (!bf) + return -ENOMEM; + + INIT_LIST_HEAD(&sc->rx.rxbuf); + sc->rx.rx_bufptr = bf; + + for (i = 0; i < nbufs; i++, bf++) { skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_KERNEL); - if (skb == NULL) { + if (!skb) { error = -ENOMEM; - goto err; + goto rx_init_fail; } + memset(skb->data, 0, common->rx_bufsize); bf->bf_mpdu = skb; + bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, common->rx_bufsize, - DMA_FROM_DEVICE); + DMA_BIDIRECTIONAL); if (unlikely(dma_mapping_error(sc->dev, - bf->bf_buf_addr))) { - dev_kfree_skb_any(skb); - bf->bf_mpdu = NULL; + bf->bf_buf_addr))) { + dev_kfree_skb_any(skb); + bf->bf_mpdu = NULL; + ath_print(common, ATH_DBG_FATAL, + "dma_mapping_error() on RX init\n"); + error = -ENOMEM; + goto rx_init_fail; + } + + list_add_tail(&bf->list, &sc->rx.rxbuf); + } + + return 0; + +rx_init_fail: + ath_rx_edma_cleanup(sc); + return error; +} + +static void ath_edma_start_recv(struct ath_softc *sc) +{ + spin_lock_bh(&sc->rx.rxbuflock); + + ath9k_hw_rxena(sc->sc_ah); + + ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP, + sc->rx.rx_edma[ATH9K_RX_QUEUE_HP].rx_fifo_hwsize); + + ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP, + sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize); + + spin_unlock_bh(&sc->rx.rxbuflock); + + ath_opmode_init(sc); + + ath9k_hw_startpcureceive(sc->sc_ah); +} + +static void ath_edma_stop_recv(struct ath_softc *sc) +{ + spin_lock_bh(&sc->rx.rxbuflock); + ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); + ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); + spin_unlock_bh(&sc->rx.rxbuflock); +} + +int ath_rx_init(struct ath_softc *sc, int nbufs) +{ + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct sk_buff *skb; + struct ath_buf *bf; + int error = 0; + + spin_lock_init(&sc->rx.rxflushlock); + sc->sc_flags &= ~SC_OP_RXFLUSH; + spin_lock_init(&sc->rx.rxbuflock); + + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { + return ath_rx_edma_init(sc, nbufs); + } else { + common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN, + min(common->cachelsz, (u16)64)); + + ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", + common->cachelsz, common->rx_bufsize); + + /* Initialize rx descriptors */ + + error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, + "rx", nbufs, 1); + if (error != 0) { ath_print(common, ATH_DBG_FATAL, - "dma_mapping_error() on RX init\n"); - error = -ENOMEM; + "failed to allocate rx descriptors: %d\n", + error); goto err; } - bf->bf_dmacontext = bf->bf_buf_addr; + + list_for_each_entry(bf, &sc->rx.rxbuf, list) { + skb = ath_rxbuf_alloc(common, common->rx_bufsize, + GFP_KERNEL); + if (skb == NULL) { + error = -ENOMEM; + goto err; + } + + bf->bf_mpdu = skb; + bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, + common->rx_bufsize, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(sc->dev, + bf->bf_buf_addr))) { + dev_kfree_skb_any(skb); + bf->bf_mpdu = NULL; + ath_print(common, ATH_DBG_FATAL, + "dma_mapping_error() on RX init\n"); + error = -ENOMEM; + goto err; + } + bf->bf_dmacontext = bf->bf_buf_addr; + } + sc->rx.rxlink = NULL; } - sc->rx.rxlink = NULL; err: if (error) @@ -180,17 +372,23 @@ void ath_rx_cleanup(struct ath_softc *sc) struct sk_buff *skb; struct ath_buf *bf; - list_for_each_entry(bf, &sc->rx.rxbuf, list) { - skb = bf->bf_mpdu; - if (skb) { - dma_unmap_single(sc->dev, bf->bf_buf_addr, - common->rx_bufsize, DMA_FROM_DEVICE); - dev_kfree_skb(skb); + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { + ath_rx_edma_cleanup(sc); + return; + } else { + list_for_each_entry(bf, &sc->rx.rxbuf, list) { + skb = bf->bf_mpdu; + if (skb) { + dma_unmap_single(sc->dev, bf->bf_buf_addr, + common->rx_bufsize, + DMA_FROM_DEVICE); + dev_kfree_skb(skb); + } } - } - if (sc->rx.rxdma.dd_desc_len != 0) - ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf); + if (sc->rx.rxdma.dd_desc_len != 0) + ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf); + } } /* @@ -273,6 +471,11 @@ int ath_startrecv(struct ath_softc *sc) struct ath_hw *ah = sc->sc_ah; struct ath_buf *bf, *tbf; + if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { + ath_edma_start_recv(sc); + return 0; + } + spin_lock_bh(&sc->rx.rxbuflock); if (list_empty(&sc->rx.rxbuf)) goto start_recv; @@ -306,7 +509,11 @@ bool ath_stoprecv(struct ath_softc *sc) ath9k_hw_stoppcurecv(ah); ath9k_hw_setrxfilter(ah, 0); stopped = ath9k_hw_stopdmarecv(ah); - sc->rx.rxlink = NULL; + + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) + ath_edma_stop_recv(sc); + else + sc->rx.rxlink = NULL; return stopped; } @@ -315,7 +522,9 @@ void ath_flushrecv(struct ath_softc *sc) { spin_lock_bh(&sc->rx.rxflushlock); sc->sc_flags |= SC_OP_RXFLUSH; - ath_rx_tasklet(sc, 1); + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) + ath_rx_tasklet(sc, 1, true); + ath_rx_tasklet(sc, 1, false); sc->sc_flags &= ~SC_OP_RXFLUSH; spin_unlock_bh(&sc->rx.rxflushlock); } @@ -469,14 +678,147 @@ static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw, ieee80211_rx(hw, skb); } -int ath_rx_tasklet(struct ath_softc *sc, int flush) +static bool ath_edma_get_buffers(struct ath_softc *sc, + enum ath9k_rx_qtype qtype) { -#define PA2DESC(_sc, _pa) \ - ((struct ath_desc *)((caddr_t)(_sc)->rx.rxdma.dd_desc + \ - ((_pa) - (_sc)->rx.rxdma.dd_desc_paddr))) + struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype]; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct sk_buff *skb; + struct ath_buf *bf; + int ret; + + skb = skb_peek(&rx_edma->rx_fifo); + if (!skb) + return false; + + bf = SKB_CB_ATHBUF(skb); + BUG_ON(!bf); + + dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, + common->rx_bufsize, DMA_FROM_DEVICE); + + ret = ath9k_hw_process_rxdesc_edma(ah, NULL, skb->data); + if (ret == -EINPROGRESS) + return false; + + __skb_unlink(skb, &rx_edma->rx_fifo); + if (ret == -EINVAL) { + /* corrupt descriptor, skip this one and the following one */ + list_add_tail(&bf->list, &sc->rx.rxbuf); + ath_rx_edma_buf_link(sc, qtype); + skb = skb_peek(&rx_edma->rx_fifo); + if (!skb) + return true; + + bf = SKB_CB_ATHBUF(skb); + BUG_ON(!bf); + + __skb_unlink(skb, &rx_edma->rx_fifo); + list_add_tail(&bf->list, &sc->rx.rxbuf); + ath_rx_edma_buf_link(sc, qtype); + } + skb_queue_tail(&rx_edma->rx_buffers, skb); + + return true; +} +static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc, + struct ath_rx_status *rs, + enum ath9k_rx_qtype qtype) +{ + struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype]; + struct sk_buff *skb; struct ath_buf *bf; + + while (ath_edma_get_buffers(sc, qtype)); + skb = __skb_dequeue(&rx_edma->rx_buffers); + if (!skb) + return NULL; + + bf = SKB_CB_ATHBUF(skb); + ath9k_hw_process_rxdesc_edma(sc->sc_ah, rs, skb->data); + return bf; +} + +static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, + struct ath_rx_status *rs) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); struct ath_desc *ds; + struct ath_buf *bf; + int ret; + + if (list_empty(&sc->rx.rxbuf)) { + sc->rx.rxlink = NULL; + return NULL; + } + + bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); + ds = bf->bf_desc; + + /* + * Must provide the virtual address of the current + * descriptor, the physical address, and the virtual + * address of the next descriptor in the h/w chain. + * This allows the HAL to look ahead to see if the + * hardware is done with a descriptor by checking the + * done bit in the following descriptor and the address + * of the current descriptor the DMA engine is working + * on. All this is necessary because of our use of + * a self-linked list to avoid rx overruns. + */ + ret = ath9k_hw_rxprocdesc(ah, ds, rs, 0); + if (ret == -EINPROGRESS) { + struct ath_rx_status trs; + struct ath_buf *tbf; + struct ath_desc *tds; + + memset(&trs, 0, sizeof(trs)); + if (list_is_last(&bf->list, &sc->rx.rxbuf)) { + sc->rx.rxlink = NULL; + return NULL; + } + + tbf = list_entry(bf->list.next, struct ath_buf, list); + + /* + * On some hardware the descriptor status words could + * get corrupted, including the done bit. Because of + * this, check if the next descriptor's done bit is + * set or not. + * + * If the next descriptor's done bit is set, the current + * descriptor has been corrupted. Force s/w to discard + * this descriptor and continue... + */ + + tds = tbf->bf_desc; + ret = ath9k_hw_rxprocdesc(ah, tds, &trs, 0); + if (ret == -EINPROGRESS) + return NULL; + } + + if (!bf->bf_mpdu) + return bf; + + /* + * Synchronize the DMA transfer with CPU before + * 1. accessing the frame + * 2. requeueing the same buffer to h/w + */ + dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, + common->rx_bufsize, + DMA_FROM_DEVICE); + + return bf; +} + + +int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) +{ + struct ath_buf *bf; struct sk_buff *skb = NULL, *requeue_skb; struct ieee80211_rx_status *rxs; struct ath_hw *ah = sc->sc_ah; @@ -491,7 +833,16 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) int retval; bool decrypt_error = false; struct ath_rx_status rs; + enum ath9k_rx_qtype qtype; + bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); + int dma_type; + if (edma) + dma_type = DMA_FROM_DEVICE; + else + dma_type = DMA_BIDIRECTIONAL; + + qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; spin_lock_bh(&sc->rx.rxbuflock); do { @@ -499,71 +850,19 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) break; - if (list_empty(&sc->rx.rxbuf)) { - sc->rx.rxlink = NULL; - break; - } - - bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); - ds = bf->bf_desc; - - /* - * Must provide the virtual address of the current - * descriptor, the physical address, and the virtual - * address of the next descriptor in the h/w chain. - * This allows the HAL to look ahead to see if the - * hardware is done with a descriptor by checking the - * done bit in the following descriptor and the address - * of the current descriptor the DMA engine is working - * on. All this is necessary because of our use of - * a self-linked list to avoid rx overruns. - */ memset(&rs, 0, sizeof(rs)); - retval = ath9k_hw_rxprocdesc(ah, ds, &rs, 0); - if (retval == -EINPROGRESS) { - struct ath_rx_status trs; - struct ath_buf *tbf; - struct ath_desc *tds; - - memset(&trs, 0, sizeof(trs)); - if (list_is_last(&bf->list, &sc->rx.rxbuf)) { - sc->rx.rxlink = NULL; - break; - } + if (edma) + bf = ath_edma_get_next_rx_buf(sc, &rs, qtype); + else + bf = ath_get_next_rx_buf(sc, &rs); - tbf = list_entry(bf->list.next, struct ath_buf, list); - - /* - * On some hardware the descriptor status words could - * get corrupted, including the done bit. Because of - * this, check if the next descriptor's done bit is - * set or not. - * - * If the next descriptor's done bit is set, the current - * descriptor has been corrupted. Force s/w to discard - * this descriptor and continue... - */ - - tds = tbf->bf_desc; - retval = ath9k_hw_rxprocdesc(ah, tds, &trs, 0); - if (retval == -EINPROGRESS) { - break; - } - } + if (!bf) + break; skb = bf->bf_mpdu; if (!skb) continue; - /* - * Synchronize the DMA transfer with CPU before - * 1. accessing the frame - * 2. requeueing the same buffer to h/w - */ - dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr, - common->rx_bufsize, - DMA_FROM_DEVICE); - hdr = (struct ieee80211_hdr *) skb->data; rxs = IEEE80211_SKB_RXCB(skb); @@ -597,9 +896,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) /* Unmap the frame */ dma_unmap_single(sc->dev, bf->bf_buf_addr, common->rx_bufsize, - DMA_FROM_DEVICE); + dma_type); - skb_put(skb, rs.rs_datalen); + skb_put(skb, rs.rs_datalen + ah->caps.rx_status_len); + if (ah->caps.rx_status_len) + skb_pull(skb, ah->caps.rx_status_len); ath9k_cmn_rx_skb_postprocess(common, skb, &rs, rxs, decrypt_error); @@ -608,7 +909,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) bf->bf_mpdu = requeue_skb; bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data, common->rx_bufsize, - DMA_FROM_DEVICE); + dma_type); if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { dev_kfree_skb_any(requeue_skb); @@ -639,12 +940,16 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) ath_rx_send_to_mac80211(hw, sc, skb, rxs); requeue: - list_move_tail(&bf->list, &sc->rx.rxbuf); - ath_rx_buf_link(sc, bf); + if (edma) { + list_add_tail(&bf->list, &sc->rx.rxbuf); + ath_rx_edma_buf_link(sc, qtype); + } else { + list_move_tail(&bf->list, &sc->rx.rxbuf); + ath_rx_buf_link(sc, bf); + } } while (1); spin_unlock_bh(&sc->rx.rxbuflock); return 0; -#undef PA2DESC } -- cgit v1.2.3 From 641d99217f507024720d21f0a76a8075824fcc46 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Apr 2010 17:38:49 -0400 Subject: ath9k_hw: Split out the function for reading the noise floor Signed-off-by: Felix Fietkau Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar5008_phy.c | 50 +++++++++++++ drivers/net/wireless/ath/ath9k/ar9002_phy.c | 53 ++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_phy.c | 110 ++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/calib.c | 90 +---------------------- drivers/net/wireless/ath/ath9k/hw-ops.h | 6 ++ drivers/net/wireless/ath/ath9k/hw.c | 3 + drivers/net/wireless/ath/ath9k/hw.h | 12 +++ 7 files changed, 235 insertions(+), 89 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index dddca59ea46d..bd3792c78af1 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -1198,6 +1198,55 @@ static bool ar5008_hw_ani_control(struct ath_hw *ah, return true; } +static void ar5008_hw_do_getnf(struct ath_hw *ah, + int16_t nfarray[NUM_NF_READINGS]) +{ + struct ath_common *common = ath9k_hw_common(ah); + int16_t nf; + + nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 0] is %d\n", nf); + nfarray[0] = nf; + + nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 1] is %d\n", nf); + nfarray[1] = nf; + + nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 2] is %d\n", nf); + nfarray[2] = nf; + + nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 0] is %d\n", nf); + nfarray[3] = nf; + + nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 1] is %d\n", nf); + nfarray[4] = nf; + + nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 2] is %d\n", nf); + nfarray[5] = nf; +} + void ar5008_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); @@ -1220,6 +1269,7 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->restore_chainmask = ar5008_restore_chainmask; priv_ops->set_diversity = ar5008_set_diversity; priv_ops->ani_control = ar5008_hw_ani_control; + priv_ops->do_getnf = ar5008_hw_do_getnf; if (AR_SREV_9100(ah)) priv_ops->compute_pll_control = ar9100_hw_compute_pll_control; diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 1f8ac0ae471a..a0a2f58db29c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -467,6 +467,58 @@ static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah, return pll; } +static void ar9002_hw_do_getnf(struct ath_hw *ah, + int16_t nfarray[NUM_NF_READINGS]) +{ + struct ath_common *common = ath9k_hw_common(ah); + int16_t nf; + + nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); + + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 0] is %d\n", nf); + + if (AR_SREV_9271(ah) && (nf >= -114)) + nf = -116; + + nfarray[0] = nf; + + if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) { + nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), + AR9280_PHY_CH1_MINCCA_PWR); + + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 1] is %d\n", nf); + nfarray[1] = nf; + } + + nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 0] is %d\n", nf); + + if (AR_SREV_9271(ah) && (nf >= -114)) + nf = -116; + + nfarray[3] = nf; + + if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) { + nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), + AR9280_PHY_CH1_EXT_MINCCA_PWR); + + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 1] is %d\n", nf); + nfarray[4] = nf; + } +} + void ar9002_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); @@ -478,4 +530,5 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate; priv_ops->olc_init = ar9002_olc_init; priv_ops->compute_pll_control = ar9002_hw_compute_pll_control; + priv_ops->do_getnf = ar9002_hw_do_getnf; } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index c938b85c174e..67b3b6518436 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -705,6 +705,115 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, return true; } +static void ar9003_hw_nf_sanitize_2g(struct ath_hw *ah, s16 *nf) +{ + struct ath_common *common = ath9k_hw_common(ah); + + if (*nf > ah->nf_2g_max) { + ath_print(common, ATH_DBG_CALIBRATE, + "2 GHz NF (%d) > MAX (%d), " + "correcting to MAX", + *nf, ah->nf_2g_max); + *nf = ah->nf_2g_max; + } else if (*nf < ah->nf_2g_min) { + ath_print(common, ATH_DBG_CALIBRATE, + "2 GHz NF (%d) < MIN (%d), " + "correcting to MIN", + *nf, ah->nf_2g_min); + *nf = ah->nf_2g_min; + } +} + +static void ar9003_hw_nf_sanitize_5g(struct ath_hw *ah, s16 *nf) +{ + struct ath_common *common = ath9k_hw_common(ah); + + if (*nf > ah->nf_5g_max) { + ath_print(common, ATH_DBG_CALIBRATE, + "5 GHz NF (%d) > MAX (%d), " + "correcting to MAX", + *nf, ah->nf_5g_max); + *nf = ah->nf_5g_max; + } else if (*nf < ah->nf_5g_min) { + ath_print(common, ATH_DBG_CALIBRATE, + "5 GHz NF (%d) < MIN (%d), " + "correcting to MIN", + *nf, ah->nf_5g_min); + *nf = ah->nf_5g_min; + } +} + +static void ar9003_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) +{ + if (IS_CHAN_2GHZ(ah->curchan)) + ar9003_hw_nf_sanitize_2g(ah, nf); + else + ar9003_hw_nf_sanitize_5g(ah, nf); +} + +static void ar9003_hw_do_getnf(struct ath_hw *ah, + int16_t nfarray[NUM_NF_READINGS]) +{ + struct ath_common *common = ath9k_hw_common(ah); + int16_t nf; + + nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ar9003_hw_nf_sanitize(ah, &nf); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 0] is %d\n", nf); + nfarray[0] = nf; + + nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ar9003_hw_nf_sanitize(ah, &nf); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 1] is %d\n", nf); + nfarray[1] = nf; + + nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ar9003_hw_nf_sanitize(ah, &nf); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 2] is %d\n", nf); + nfarray[2] = nf; + + nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ar9003_hw_nf_sanitize(ah, &nf); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 0] is %d\n", nf); + nfarray[3] = nf; + + nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ar9003_hw_nf_sanitize(ah, &nf); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 1] is %d\n", nf); + nfarray[4] = nf; + + nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + ar9003_hw_nf_sanitize(ah, &nf); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 2] is %d\n", nf); + nfarray[5] = nf; +} + +void ar9003_hw_set_nf_limits(struct ath_hw *ah) +{ + ah->nf_2g_max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ; + ah->nf_2g_min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ; + ah->nf_5g_max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ; + ah->nf_5g_min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ; +} + void ar9003_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); @@ -723,4 +832,5 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->enable_rfkill = ar9003_hw_enable_rfkill; priv_ops->set_diversity = ar9003_hw_set_diversity; priv_ops->ani_control = ar9003_hw_ani_control; + priv_ops->do_getnf = ar9003_hw_do_getnf; } diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index eba85adb7cd3..eed2c76f56c6 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -15,6 +15,7 @@ */ #include "hw.h" +#include "hw-ops.h" #include "ar9002_phy.h" /* We can tune this as we go by monitoring really low values */ @@ -88,95 +89,6 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, return; } -static void ath9k_hw_do_getnf(struct ath_hw *ah, - int16_t nfarray[NUM_NF_READINGS]) -{ - struct ath_common *common = ath9k_hw_common(ah); - int16_t nf; - - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); - - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - ath_print(common, ATH_DBG_CALIBRATE, - "NF calibrated [ctl] [chain 0] is %d\n", nf); - - if (AR_SREV_9271(ah) && (nf >= -114)) - nf = -116; - - nfarray[0] = nf; - - if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) { - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), - AR9280_PHY_CH1_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), - AR_PHY_CH1_MINCCA_PWR); - - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - ath_print(common, ATH_DBG_CALIBRATE, - "NF calibrated [ctl] [chain 1] is %d\n", nf); - nfarray[1] = nf; - - if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { - nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), - AR_PHY_CH2_MINCCA_PWR); - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - ath_print(common, ATH_DBG_CALIBRATE, - "NF calibrated [ctl] [chain 2] is %d\n", nf); - nfarray[2] = nf; - } - } - - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), - AR9280_PHY_EXT_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), - AR_PHY_EXT_MINCCA_PWR); - - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - ath_print(common, ATH_DBG_CALIBRATE, - "NF calibrated [ext] [chain 0] is %d\n", nf); - - if (AR_SREV_9271(ah) && (nf >= -114)) - nf = -116; - - nfarray[3] = nf; - - if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) { - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), - AR9280_PHY_CH1_EXT_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), - AR_PHY_CH1_EXT_MINCCA_PWR); - - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - ath_print(common, ATH_DBG_CALIBRATE, - "NF calibrated [ext] [chain 1] is %d\n", nf); - nfarray[4] = nf; - - if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { - nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), - AR_PHY_CH2_EXT_MINCCA_PWR); - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - ath_print(common, ATH_DBG_CALIBRATE, - "NF calibrated [ext] [chain 2] is %d\n", nf); - nfarray[5] = nf; - } - } -} - static bool getNoiseFloorThresh(struct ath_hw *ah, enum ieee80211_band band, int16_t *nft) diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index a7701079a88a..e2b8ad4df904 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -163,4 +163,10 @@ static inline bool ath9k_hw_ani_control(struct ath_hw *ah, return ath9k_hw_private_ops(ah)->ani_control(ah, cmd, param); } +static inline void ath9k_hw_do_getnf(struct ath_hw *ah, + int16_t nfarray[NUM_NF_READINGS]) +{ + return ath9k_hw_private_ops(ah)->do_getnf(ah, nfarray); +} + #endif /* ATH9K_HW_OPS_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index f45e724c841f..6ee719e36798 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1071,6 +1071,9 @@ static int __ath9k_hw_init(struct ath_hw *ah) else ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); + if (AR_SREV_9300_20_OR_LATER(ah)) + ar9003_hw_set_nf_limits(ah); + ath9k_init_nfcal_hist_buffer(ah); common->state = ATH_HW_INITIALIZED; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 1eceda22ae5f..7889ecbfeeec 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -513,6 +513,7 @@ struct ath_hw_private_ops { struct ath9k_channel *chan); bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd, int param); + void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]); }; /** @@ -553,6 +554,10 @@ struct ath_hw { bool is_pciexpress; bool need_an_top2_fixup; u16 tx_trig_level; + s16 nf_2g_max; + s16 nf_2g_min; + s16 nf_5g_max; + s16 nf_5g_min; u16 rfsilent; u32 rfkill_gpio; u32 rfkill_polarity; @@ -818,6 +823,13 @@ void ath9k_hw_htc_resetinit(struct ath_hw *ah); void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, u32 *coef_mantissa, u32 *coef_exponent); +/* + * Code specifric to AR9003, we stuff these here to avoid callbacks + * for older families + */ +void ar9003_hw_set_nf_limits(struct ath_hw *ah); + +/* Hardware family op attach helpers */ void ar5008_hw_attach_phy_ops(struct ath_hw *ah); void ar9002_hw_attach_phy_ops(struct ath_hw *ah); void ar9003_hw_attach_phy_ops(struct ath_hw *ah); -- cgit v1.2.3 From 939ad86de538d23533d2f9dd43f80725789d43ba Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Thu, 15 Apr 2010 17:38:50 -0400 Subject: ath9k_hw: the eep_map is used only for AR9280 PCI card ini fixup We can reorganize the code in such a way that eep_map can be removed, which makes the code more clearer. Signed-off-by: Senthil Balasubramanian Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom.c | 3 --- drivers/net/wireless/ath/ath9k/eeprom.h | 7 ------- drivers/net/wireless/ath/ath9k/hw.c | 2 +- drivers/net/wireless/ath/ath9k/hw.h | 1 - 4 files changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index dacaae934148..1a48f43f653e 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -257,13 +257,10 @@ int ath9k_hw_eeprom_init(struct ath_hw *ah) int status; if (AR_SREV_9287(ah)) { - ah->eep_map = EEP_MAP_AR9287; ah->eep_ops = &eep_AR9287_ops; } else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) { - ah->eep_map = EEP_MAP_4KBITS; ah->eep_ops = &eep_4k_ops; } else { - ah->eep_map = EEP_MAP_DEFAULT; ah->eep_ops = &eep_def_ops; } diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 2f2993b50e2f..e087e2de6067 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -656,13 +656,6 @@ struct ath9k_country_entry { u8 iso[3]; }; -enum ath9k_eep_map { - EEP_MAP_DEFAULT = 0x0, - EEP_MAP_4KBITS, - EEP_MAP_AR9287, - EEP_MAP_MAX -}; - struct eeprom_ops { int (*check_eeprom)(struct ath_hw *hw); u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param); diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 6ee719e36798..e914d8f68fd8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -946,7 +946,7 @@ static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); ah->need_an_top2_fixup = (ah->hw_version.devid == AR9280_DEVID_PCI) && - (ah->eep_map != EEP_MAP_4KBITS) && + !AR_SREV_9285(ah) && !AR_SREV_9271(ah) && ((pBase->version & 0xff) > 0x0a) && (pBase->pwdclkind == 0); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7889ecbfeeec..48fb5ce8294b 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -548,7 +548,6 @@ struct ath_hw { struct ar9287_eeprom map9287; } eeprom; const struct eeprom_ops *eep_ops; - enum ath9k_eep_map eep_map; bool sw_mgmt_crypto; bool is_pciexpress; -- cgit v1.2.3 From 4d001d18f2e738f3b53bfd1cd493987e3e61421a Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:51 -0400 Subject: ath9k_hw: add a helper for Power Amplifier calibration for AR9002 The code can be simplified and shared between two locations if we bring this into a helper. During reset we do not account for the skip count. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index eed2c76f56c6..26bc3819bdde 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -949,6 +949,21 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset) } +static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) +{ + if (AR_SREV_9271(ah)) { + if (is_reset || !ah->pacal_info.skipcount) + ath9k_hw_9271_pa_cal(ah, is_reset); + else + ah->pacal_info.skipcount--; + } else if (AR_SREV_9285_11_OR_LATER(ah)) { + if (is_reset || !ah->pacal_info.skipcount) + ath9k_hw_9285_pa_cal(ah, is_reset); + else + ah->pacal_info.skipcount--; + } +} + bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, u8 rxchainmask, bool longcal) { @@ -973,17 +988,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, /* Do NF cal only at longer intervals */ if (longcal) { /* Do periodic PAOffset Cal */ - if (AR_SREV_9271(ah)) { - if (!ah->pacal_info.skipcount) - ath9k_hw_9271_pa_cal(ah, false); - else - ah->pacal_info.skipcount--; - } else if (AR_SREV_9285_11_OR_LATER(ah)) { - if (!ah->pacal_info.skipcount) - ath9k_hw_9285_pa_cal(ah, false); - else - ah->pacal_info.skipcount--; - } + ar9002_hw_pa_cal(ah, false); if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER) ath9k_olc_temp_compensation(ah); @@ -1142,10 +1147,7 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) } /* Do PA Calibration */ - if (AR_SREV_9271(ah)) - ath9k_hw_9271_pa_cal(ah, true); - else if (AR_SREV_9285_11_OR_LATER(ah)) - ath9k_hw_9285_pa_cal(ah, true); + ar9002_hw_pa_cal(ah, true); /* Do NF Calibration after DC offset and other calibrations */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, -- cgit v1.2.3 From e83a1134de299e6453c6d8bc99cf3af3972bb84a Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:52 -0400 Subject: ath9k_hw: add a helper for the OLC tem compensation for AR9002 Open Loop Control temperature compensation changes between our hardware so use a helper for it. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 26bc3819bdde..156ae347c617 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -964,6 +964,12 @@ static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) } } +static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah) +{ + if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER) + ath9k_olc_temp_compensation(ah); +} + bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, u8 rxchainmask, bool longcal) { @@ -989,9 +995,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, if (longcal) { /* Do periodic PAOffset Cal */ ar9002_hw_pa_cal(ah, false); - - if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER) - ath9k_olc_temp_compensation(ah); + ar9002_hw_olc_temp_compensation(ah); /* Get the value from the previous NF cal and update history buffer */ ath9k_hw_getnf(ah, chan); -- cgit v1.2.3 From becdbc542f3f3395138b45d7ae445886fa0feef7 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:53 -0400 Subject: ath9k_hw: rename PA calib for AR9287 Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 156ae347c617..e2c427b9ec62 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -671,7 +671,7 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) } EXPORT_SYMBOL(ath9k_hw_getchan_noise); -static void ath9k_olc_temp_compensation_9287(struct ath_hw *ah) +static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah) { u32 rddata; int32_t delta, currPDADC, slope; @@ -706,7 +706,7 @@ static void ath9k_olc_temp_compensation(struct ath_hw *ah) int delta, currPDADC, regval; if (OLC_FOR_AR9287_10_LATER) { - ath9k_olc_temp_compensation_9287(ah); + ar9287_hw_olc_temp_compensation(ah); } else { rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); -- cgit v1.2.3 From 80b99932fd43ce3477fb2d952f12657963a2562d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:54 -0400 Subject: ath9k_hw: shift code for AR9280 OLC temp comp We're bailing out on the alternative code path so remove the else branch. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 35 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index e2c427b9ec62..5d61169de07b 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -711,25 +711,24 @@ static void ath9k_olc_temp_compensation(struct ath_hw *ah) rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); - if (ah->initPDADC == 0 || currPDADC == 0) { + if (ah->initPDADC == 0 || currPDADC == 0) return; - } else { - if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) - delta = (currPDADC - ah->initPDADC + 4) / 8; - else - delta = (currPDADC - ah->initPDADC + 5) / 10; - - if (delta != ah->PDADCdelta) { - ah->PDADCdelta = delta; - for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { - regval = ah->originalGain[i] - delta; - if (regval < 0) - regval = 0; - - REG_RMW_FIELD(ah, - AR_PHY_TX_GAIN_TBL1 + i * 4, - AR_PHY_TX_GAIN, regval); - } + + if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) + delta = (currPDADC - ah->initPDADC + 4) / 8; + else + delta = (currPDADC - ah->initPDADC + 5) / 10; + + if (delta != ah->PDADCdelta) { + ah->PDADCdelta = delta; + for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { + regval = ah->originalGain[i] - delta; + if (regval < 0) + regval = 0; + + REG_RMW_FIELD(ah, + AR_PHY_TX_GAIN_TBL1 + i * 4, + AR_PHY_TX_GAIN, regval); } } } -- cgit v1.2.3 From 2b5facfe7669b36a04845928abd1fcc153990026 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:55 -0400 Subject: ath9k_hw: move the AR9280 OLC temp comp to its own helper Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 52 ++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 24 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 5d61169de07b..dae200c5fe0d 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -700,40 +700,44 @@ static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah) } } -static void ath9k_olc_temp_compensation(struct ath_hw *ah) +static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah) { u32 rddata, i; int delta, currPDADC, regval; - if (OLC_FOR_AR9287_10_LATER) { - ar9287_hw_olc_temp_compensation(ah); - } else { - rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); - currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); + rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); + currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); - if (ah->initPDADC == 0 || currPDADC == 0) - return; + if (ah->initPDADC == 0 || currPDADC == 0) + return; - if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) - delta = (currPDADC - ah->initPDADC + 4) / 8; - else - delta = (currPDADC - ah->initPDADC + 5) / 10; - - if (delta != ah->PDADCdelta) { - ah->PDADCdelta = delta; - for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { - regval = ah->originalGain[i] - delta; - if (regval < 0) - regval = 0; - - REG_RMW_FIELD(ah, - AR_PHY_TX_GAIN_TBL1 + i * 4, - AR_PHY_TX_GAIN, regval); - } + if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) + delta = (currPDADC - ah->initPDADC + 4) / 8; + else + delta = (currPDADC - ah->initPDADC + 5) / 10; + + if (delta != ah->PDADCdelta) { + ah->PDADCdelta = delta; + for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { + regval = ah->originalGain[i] - delta; + if (regval < 0) + regval = 0; + + REG_RMW_FIELD(ah, + AR_PHY_TX_GAIN_TBL1 + i * 4, + AR_PHY_TX_GAIN, regval); } } } +static void ath9k_olc_temp_compensation(struct ath_hw *ah) +{ + if (OLC_FOR_AR9287_10_LATER) + ar9287_hw_olc_temp_compensation(ah); + else + ar9280_hw_olc_temp_compensation(ah); +} + static void ath9k_hw_9271_pa_cal(struct ath_hw *ah, bool is_reset) { u32 regVal; -- cgit v1.2.3 From af6757e95efca3d5965a7d3d087190bef99ac45f Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:56 -0400 Subject: ath9k_hw: simplify OLC temp compensation for AR9002 We can do the family revision check on the top level caller. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index dae200c5fe0d..b44b3056c2fe 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -730,14 +730,6 @@ static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah) } } -static void ath9k_olc_temp_compensation(struct ath_hw *ah) -{ - if (OLC_FOR_AR9287_10_LATER) - ar9287_hw_olc_temp_compensation(ah); - else - ar9280_hw_olc_temp_compensation(ah); -} - static void ath9k_hw_9271_pa_cal(struct ath_hw *ah, bool is_reset) { u32 regVal; @@ -969,8 +961,10 @@ static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah) { - if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER) - ath9k_olc_temp_compensation(ah); + if (OLC_FOR_AR9287_10_LATER) + ar9287_hw_olc_temp_compensation(ah); + else if (OLC_FOR_AR9280_20_LATER) + ar9280_hw_olc_temp_compensation(ah); } bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, -- cgit v1.2.3 From 37c3e8b9d7f2d689b0aca89a8ac4aa12476df633 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:57 -0400 Subject: ath9k_hw: rename the PA calib routines to match their families Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index b44b3056c2fe..4018074632c8 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -730,7 +730,7 @@ static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah) } } -static void ath9k_hw_9271_pa_cal(struct ath_hw *ah, bool is_reset) +static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) { u32 regVal; unsigned int i; @@ -831,7 +831,7 @@ static void ath9k_hw_9271_pa_cal(struct ath_hw *ah, bool is_reset) REG_WRITE(ah, regList[i][0], regList[i][1]); } -static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset) +static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) { struct ath_common *common = ath9k_hw_common(ah); u32 regVal; @@ -948,12 +948,12 @@ static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) { if (AR_SREV_9271(ah)) { if (is_reset || !ah->pacal_info.skipcount) - ath9k_hw_9271_pa_cal(ah, is_reset); + ar9271_hw_pa_cal(ah, is_reset); else ah->pacal_info.skipcount--; } else if (AR_SREV_9285_11_OR_LATER(ah)) { if (is_reset || !ah->pacal_info.skipcount) - ath9k_hw_9285_pa_cal(ah, is_reset); + ar9285_hw_pa_cal(ah, is_reset); else ah->pacal_info.skipcount--; } -- cgit v1.2.3 From b43d59fb3e2977945df061e7c405679f31acb26e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:58 -0400 Subject: ath9k_hw: rename getNoiseFloorThresh() to ath9k_hw_loadnf() Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 4018074632c8..aa724c263404 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -89,9 +89,9 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, return; } -static bool getNoiseFloorThresh(struct ath_hw *ah, - enum ieee80211_band band, - int16_t *nft) +static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, + enum ieee80211_band band, + int16_t *nft) { switch (band) { case IEEE80211_BAND_5GHZ: @@ -612,7 +612,7 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah, } else { ath9k_hw_do_getnf(ah, nfarray); nf = nfarray[0]; - if (getNoiseFloorThresh(ah, c->band, &nfThresh) + if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh) && nf > nfThresh) { ath_print(common, ATH_DBG_CALIBRATE, "noise floor failed detected; " -- cgit v1.2.3 From 0df13da4555320f6dc9b901fd5f22cf54065c708 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:59 -0400 Subject: ath9k_hw: move the cal AR9100 calibration settings The calibration settings should go into the respective hardware family AR9002 calibration settings callback, ar9002_hw_init_cal_settings(). Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index e914d8f68fd8..67c2becad662 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -602,6 +602,12 @@ static bool ar9003_hw_macversion_supported(u32 macversion) static void ar9002_hw_init_cal_settings(struct ath_hw *ah) { + if (AR_SREV_9100(ah)) { + ah->iq_caldata.calData = &iq_cal_multi_sample; + ah->supp_cals = IQ_MISMATCH_CAL; + return; + } + if (AR_SREV_9160_10_OR_LATER(ah)) { if (AR_SREV_9280_10_OR_LATER(ah)) { ah->iq_caldata.calData = &iq_cal_single_sample; @@ -1015,13 +1021,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) return -EOPNOTSUPP; } - if (AR_SREV_9100(ah)) { - ah->iq_caldata.calData = &iq_cal_multi_sample; - ah->supp_cals = IQ_MISMATCH_CAL; - ah->is_pciexpress = false; - } - - if (AR_SREV_9271(ah)) + if (AR_SREV_9271(ah) || AR_SREV_9100(ah)) ah->is_pciexpress = false; ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); -- cgit v1.2.3 From 795f5e2ca672727a96bacf97075976cfe1249fcf Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:00 -0400 Subject: ath9k_hw: split calib code by hardware families Calibration code touches phy registers and since these change the calibration code needs to be abstracted. Noise floor calibration is the only thing remaining but since the remaining calls only touch the AR_PHY_AGC_CONTROL register we'll just define that register conditionally, that will be done separately. The goal is to remove the dependency of ar9002_phy.h on calib.c This also adds stubs to be filled for AR9003 calibration code. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Makefile | 4 +- drivers/net/wireless/ath/ath9k/ar9002_calib.c | 993 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_calib.c | 66 ++ drivers/net/wireless/ath/ath9k/calib.c | 928 +----------------------- drivers/net/wireless/ath/ath9k/calib.h | 15 +- drivers/net/wireless/ath/ath9k/hw-ops.h | 28 +- drivers/net/wireless/ath/ath9k/hw.c | 34 +- drivers/net/wireless/ath/ath9k/hw.h | 21 +- 8 files changed, 1118 insertions(+), 971 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/ar9002_calib.c create mode 100644 drivers/net/wireless/ath/ath9k/ar9003_calib.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 96af3d96de5c..d2417ed8ec4c 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -17,11 +17,13 @@ ath9k_hw-y:= hw.o \ ar9003_phy.o \ ar9002_phy.o \ ar5008_phy.o \ + ar9002_calib.o \ + ar9003_calib.o \ + calib.o \ eeprom.o \ eeprom_def.o \ eeprom_4k.o \ eeprom_9287.o \ - calib.o \ ani.o \ btcoex.o \ mac.o \ diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c new file mode 100644 index 000000000000..cd234aafaa4a --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -0,0 +1,993 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" +#include "hw-ops.h" +#include "ar9002_phy.h" + +#define AR9285_CLCAL_REDO_THRESH 1 + +static void ar9002_hw_setup_calibration(struct ath_hw *ah, + struct ath9k_cal_list *currCal) +{ + struct ath_common *common = ath9k_hw_common(ah); + + REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), + AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, + currCal->calData->calCountMax); + + switch (currCal->calData->calType) { + case IQ_MISMATCH_CAL: + REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); + ath_print(common, ATH_DBG_CALIBRATE, + "starting IQ Mismatch Calibration\n"); + break; + case ADC_GAIN_CAL: + REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); + ath_print(common, ATH_DBG_CALIBRATE, + "starting ADC Gain Calibration\n"); + break; + case ADC_DC_CAL: + REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); + ath_print(common, ATH_DBG_CALIBRATE, + "starting ADC DC Calibration\n"); + break; + case ADC_DC_INIT_CAL: + REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); + ath_print(common, ATH_DBG_CALIBRATE, + "starting Init ADC DC Calibration\n"); + break; + } + + REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), + AR_PHY_TIMING_CTRL4_DO_CAL); +} + +static bool ar9002_hw_per_calibration(struct ath_hw *ah, + struct ath9k_channel *ichan, + u8 rxchainmask, + struct ath9k_cal_list *currCal) +{ + bool iscaldone = false; + + if (currCal->calState == CAL_RUNNING) { + if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & + AR_PHY_TIMING_CTRL4_DO_CAL)) { + + currCal->calData->calCollect(ah); + ah->cal_samples++; + + if (ah->cal_samples >= + currCal->calData->calNumSamples) { + int i, numChains = 0; + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + if (rxchainmask & (1 << i)) + numChains++; + } + + currCal->calData->calPostProc(ah, numChains); + ichan->CalValid |= currCal->calData->calType; + currCal->calState = CAL_DONE; + iscaldone = true; + } else { + ar9002_hw_setup_calibration(ah, currCal); + } + } + } else if (!(ichan->CalValid & currCal->calData->calType)) { + ath9k_hw_reset_calibration(ah, currCal); + } + + return iscaldone; +} + +/* Assumes you are talking about the currently configured channel */ +static bool ar9002_hw_iscal_supported(struct ath_hw *ah, + enum ath9k_cal_types calType) +{ + struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; + + switch (calType & ah->supp_cals) { + case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ + return true; + case ADC_GAIN_CAL: + case ADC_DC_CAL: + if (!(conf->channel->band == IEEE80211_BAND_2GHZ && + conf_is_ht20(conf))) + return true; + break; + } + return false; +} + +static void ar9002_hw_iqcal_collect(struct ath_hw *ah) +{ + int i; + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + ah->totalPowerMeasI[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + ah->totalPowerMeasQ[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + ah->totalIqCorrMeas[i] += + (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", + ah->cal_samples, i, ah->totalPowerMeasI[i], + ah->totalPowerMeasQ[i], + ah->totalIqCorrMeas[i]); + } +} + +static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah) +{ + int i; + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + ah->totalAdcIOddPhase[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + ah->totalAdcIEvenPhase[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + ah->totalAdcQOddPhase[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + ah->totalAdcQEvenPhase[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); + + ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " + "oddq=0x%08x; evenq=0x%08x;\n", + ah->cal_samples, i, + ah->totalAdcIOddPhase[i], + ah->totalAdcIEvenPhase[i], + ah->totalAdcQOddPhase[i], + ah->totalAdcQEvenPhase[i]); + } +} + +static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah) +{ + int i; + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + ah->totalAdcDcOffsetIOddPhase[i] += + (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + ah->totalAdcDcOffsetIEvenPhase[i] += + (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + ah->totalAdcDcOffsetQOddPhase[i] += + (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + ah->totalAdcDcOffsetQEvenPhase[i] += + (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); + + ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " + "oddq=0x%08x; evenq=0x%08x;\n", + ah->cal_samples, i, + ah->totalAdcDcOffsetIOddPhase[i], + ah->totalAdcDcOffsetIEvenPhase[i], + ah->totalAdcDcOffsetQOddPhase[i], + ah->totalAdcDcOffsetQEvenPhase[i]); + } +} + +static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) +{ + struct ath_common *common = ath9k_hw_common(ah); + u32 powerMeasQ, powerMeasI, iqCorrMeas; + u32 qCoffDenom, iCoffDenom; + int32_t qCoff, iCoff; + int iqCorrNeg, i; + + for (i = 0; i < numChains; i++) { + powerMeasI = ah->totalPowerMeasI[i]; + powerMeasQ = ah->totalPowerMeasQ[i]; + iqCorrMeas = ah->totalIqCorrMeas[i]; + + ath_print(common, ATH_DBG_CALIBRATE, + "Starting IQ Cal and Correction for Chain %d\n", + i); + + ath_print(common, ATH_DBG_CALIBRATE, + "Orignal: Chn %diq_corr_meas = 0x%08x\n", + i, ah->totalIqCorrMeas[i]); + + iqCorrNeg = 0; + + if (iqCorrMeas > 0x80000000) { + iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; + iqCorrNeg = 1; + } + + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); + ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", + iqCorrNeg); + + iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; + qCoffDenom = powerMeasQ / 64; + + if ((powerMeasQ != 0) && (iCoffDenom != 0) && + (qCoffDenom != 0)) { + iCoff = iqCorrMeas / iCoffDenom; + qCoff = powerMeasI / qCoffDenom - 64; + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d iCoff = 0x%08x\n", i, iCoff); + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d qCoff = 0x%08x\n", i, qCoff); + + iCoff = iCoff & 0x3f; + ath_print(common, ATH_DBG_CALIBRATE, + "New: Chn %d iCoff = 0x%08x\n", i, iCoff); + if (iqCorrNeg == 0x0) + iCoff = 0x40 - iCoff; + + if (qCoff > 15) + qCoff = 15; + else if (qCoff <= -16) + qCoff = 16; + + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", + i, iCoff, qCoff); + + REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, + iCoff); + REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), + AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, + qCoff); + ath_print(common, ATH_DBG_CALIBRATE, + "IQ Cal and Correction done for Chain %d\n", + i); + } + } + + REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), + AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); +} + +static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) +{ + struct ath_common *common = ath9k_hw_common(ah); + u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset; + u32 qGainMismatch, iGainMismatch, val, i; + + for (i = 0; i < numChains; i++) { + iOddMeasOffset = ah->totalAdcIOddPhase[i]; + iEvenMeasOffset = ah->totalAdcIEvenPhase[i]; + qOddMeasOffset = ah->totalAdcQOddPhase[i]; + qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; + + ath_print(common, ATH_DBG_CALIBRATE, + "Starting ADC Gain Cal for Chain %d\n", i); + + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_odd_i = 0x%08x\n", i, + iOddMeasOffset); + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_even_i = 0x%08x\n", i, + iEvenMeasOffset); + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_odd_q = 0x%08x\n", i, + qOddMeasOffset); + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_even_q = 0x%08x\n", i, + qEvenMeasOffset); + + if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { + iGainMismatch = + ((iEvenMeasOffset * 32) / + iOddMeasOffset) & 0x3f; + qGainMismatch = + ((qOddMeasOffset * 32) / + qEvenMeasOffset) & 0x3f; + + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d gain_mismatch_i = 0x%08x\n", i, + iGainMismatch); + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d gain_mismatch_q = 0x%08x\n", i, + qGainMismatch); + + val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); + val &= 0xfffff000; + val |= (qGainMismatch) | (iGainMismatch << 6); + REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); + + ath_print(common, ATH_DBG_CALIBRATE, + "ADC Gain Cal done for Chain %d\n", i); + } + } + + REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), + REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | + AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); +} + +static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) +{ + struct ath_common *common = ath9k_hw_common(ah); + u32 iOddMeasOffset, iEvenMeasOffset, val, i; + int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; + const struct ath9k_percal_data *calData = + ah->cal_list_curr->calData; + u32 numSamples = + (1 << (calData->calCountMax + 5)) * calData->calNumSamples; + + for (i = 0; i < numChains; i++) { + iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i]; + iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i]; + qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; + qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; + + ath_print(common, ATH_DBG_CALIBRATE, + "Starting ADC DC Offset Cal for Chain %d\n", i); + + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_odd_i = %d\n", i, + iOddMeasOffset); + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_even_i = %d\n", i, + iEvenMeasOffset); + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_odd_q = %d\n", i, + qOddMeasOffset); + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_even_q = %d\n", i, + qEvenMeasOffset); + + iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / + numSamples) & 0x1ff; + qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / + numSamples) & 0x1ff; + + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, + iDcMismatch); + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, + qDcMismatch); + + val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); + val &= 0xc0000fff; + val |= (qDcMismatch << 12) | (iDcMismatch << 21); + REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); + + ath_print(common, ATH_DBG_CALIBRATE, + "ADC DC Offset Cal done for Chain %d\n", i); + } + + REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), + REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | + AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); +} + +static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah) +{ + u32 rddata; + int32_t delta, currPDADC, slope; + + rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); + currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); + + if (ah->initPDADC == 0 || currPDADC == 0) { + /* + * Zero value indicates that no frames have been transmitted + * yet, can't do temperature compensation until frames are + * transmitted. + */ + return; + } else { + slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); + + if (slope == 0) { /* to avoid divide by zero case */ + delta = 0; + } else { + delta = ((currPDADC - ah->initPDADC)*4) / slope; + } + REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, + AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); + REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, + AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); + } +} + +static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah) +{ + u32 rddata, i; + int delta, currPDADC, regval; + + rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); + currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); + + if (ah->initPDADC == 0 || currPDADC == 0) + return; + + if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) + delta = (currPDADC - ah->initPDADC + 4) / 8; + else + delta = (currPDADC - ah->initPDADC + 5) / 10; + + if (delta != ah->PDADCdelta) { + ah->PDADCdelta = delta; + for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { + regval = ah->originalGain[i] - delta; + if (regval < 0) + regval = 0; + + REG_RMW_FIELD(ah, + AR_PHY_TX_GAIN_TBL1 + i * 4, + AR_PHY_TX_GAIN, regval); + } + } +} + +static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) +{ + u32 regVal; + unsigned int i; + u32 regList[][2] = { + { 0x786c, 0 }, + { 0x7854, 0 }, + { 0x7820, 0 }, + { 0x7824, 0 }, + { 0x7868, 0 }, + { 0x783c, 0 }, + { 0x7838, 0 } , + { 0x7828, 0 } , + }; + + for (i = 0; i < ARRAY_SIZE(regList); i++) + regList[i][1] = REG_READ(ah, regList[i][0]); + + regVal = REG_READ(ah, 0x7834); + regVal &= (~(0x1)); + REG_WRITE(ah, 0x7834, regVal); + regVal = REG_READ(ah, 0x9808); + regVal |= (0x1 << 27); + REG_WRITE(ah, 0x9808, regVal); + + /* 786c,b23,1, pwddac=1 */ + REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); + /* 7854, b5,1, pdrxtxbb=1 */ + REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); + /* 7854, b7,1, pdv2i=1 */ + REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); + /* 7854, b8,1, pddacinterface=1 */ + REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); + /* 7824,b12,0, offcal=0 */ + REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); + /* 7838, b1,0, pwddb=0 */ + REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); + /* 7820,b11,0, enpacal=0 */ + REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); + /* 7820,b25,1, pdpadrv1=0 */ + REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); + /* 7820,b24,0, pdpadrv2=0 */ + REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); + /* 7820,b23,0, pdpaout=0 */ + REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); + /* 783c,b14-16,7, padrvgn2tab_0=7 */ + REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); + /* + * 7838,b29-31,0, padrvgn1tab_0=0 + * does not matter since we turn it off + */ + REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); + + REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); + + /* Set: + * localmode=1,bmode=1,bmoderxtx=1,synthon=1, + * txon=1,paon=1,oscon=1,synthon_force=1 + */ + REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); + udelay(30); + REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0); + + /* find off_6_1; */ + for (i = 6; i > 0; i--) { + regVal = REG_READ(ah, 0x7834); + regVal |= (1 << (20 + i)); + REG_WRITE(ah, 0x7834, regVal); + udelay(1); + /* regVal = REG_READ(ah, 0x7834); */ + regVal &= (~(0x1 << (20 + i))); + regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9) + << (20 + i)); + REG_WRITE(ah, 0x7834, regVal); + } + + regVal = (regVal >> 20) & 0x7f; + + /* Update PA cal info */ + if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) { + if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) + ah->pacal_info.max_skipcount = + 2 * ah->pacal_info.max_skipcount; + ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; + } else { + ah->pacal_info.max_skipcount = 1; + ah->pacal_info.skipcount = 0; + ah->pacal_info.prev_offset = regVal; + } + + regVal = REG_READ(ah, 0x7834); + regVal |= 0x1; + REG_WRITE(ah, 0x7834, regVal); + regVal = REG_READ(ah, 0x9808); + regVal &= (~(0x1 << 27)); + REG_WRITE(ah, 0x9808, regVal); + + for (i = 0; i < ARRAY_SIZE(regList); i++) + REG_WRITE(ah, regList[i][0], regList[i][1]); +} + +static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) +{ + struct ath_common *common = ath9k_hw_common(ah); + u32 regVal; + int i, offset, offs_6_1, offs_0; + u32 ccomp_org, reg_field; + u32 regList[][2] = { + { 0x786c, 0 }, + { 0x7854, 0 }, + { 0x7820, 0 }, + { 0x7824, 0 }, + { 0x7868, 0 }, + { 0x783c, 0 }, + { 0x7838, 0 }, + }; + + ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); + + /* PA CAL is not needed for high power solution */ + if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == + AR5416_EEP_TXGAIN_HIGH_POWER) + return; + + if (AR_SREV_9285_11(ah)) { + REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); + udelay(10); + } + + for (i = 0; i < ARRAY_SIZE(regList); i++) + regList[i][1] = REG_READ(ah, regList[i][0]); + + regVal = REG_READ(ah, 0x7834); + regVal &= (~(0x1)); + REG_WRITE(ah, 0x7834, regVal); + regVal = REG_READ(ah, 0x9808); + regVal |= (0x1 << 27); + REG_WRITE(ah, 0x9808, regVal); + + REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); + REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); + REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); + REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); + REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); + REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); + REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); + REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); + REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); + REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); + REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); + REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); + ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); + REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf); + + REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); + udelay(30); + REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); + REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); + + for (i = 6; i > 0; i--) { + regVal = REG_READ(ah, 0x7834); + regVal |= (1 << (19 + i)); + REG_WRITE(ah, 0x7834, regVal); + udelay(1); + regVal = REG_READ(ah, 0x7834); + regVal &= (~(0x1 << (19 + i))); + reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); + regVal |= (reg_field << (19 + i)); + REG_WRITE(ah, 0x7834, regVal); + } + + REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); + udelay(1); + reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); + REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); + offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); + offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); + + offset = (offs_6_1<<1) | offs_0; + offset = offset - 0; + offs_6_1 = offset>>1; + offs_0 = offset & 1; + + if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) { + if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) + ah->pacal_info.max_skipcount = + 2 * ah->pacal_info.max_skipcount; + ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; + } else { + ah->pacal_info.max_skipcount = 1; + ah->pacal_info.skipcount = 0; + ah->pacal_info.prev_offset = offset; + } + + REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); + REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); + + regVal = REG_READ(ah, 0x7834); + regVal |= 0x1; + REG_WRITE(ah, 0x7834, regVal); + regVal = REG_READ(ah, 0x9808); + regVal &= (~(0x1 << 27)); + REG_WRITE(ah, 0x9808, regVal); + + for (i = 0; i < ARRAY_SIZE(regList); i++) + REG_WRITE(ah, regList[i][0], regList[i][1]); + + REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); + + if (AR_SREV_9285_11(ah)) + REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); + +} + +static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) +{ + if (AR_SREV_9271(ah)) { + if (is_reset || !ah->pacal_info.skipcount) + ar9271_hw_pa_cal(ah, is_reset); + else + ah->pacal_info.skipcount--; + } else if (AR_SREV_9285_11_OR_LATER(ah)) { + if (is_reset || !ah->pacal_info.skipcount) + ar9285_hw_pa_cal(ah, is_reset); + else + ah->pacal_info.skipcount--; + } +} + +static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah) +{ + if (OLC_FOR_AR9287_10_LATER) + ar9287_hw_olc_temp_compensation(ah); + else if (OLC_FOR_AR9280_20_LATER) + ar9280_hw_olc_temp_compensation(ah); +} + +static bool ar9002_hw_calibrate(struct ath_hw *ah, + struct ath9k_channel *chan, + u8 rxchainmask, + bool longcal) +{ + bool iscaldone = true; + struct ath9k_cal_list *currCal = ah->cal_list_curr; + + if (currCal && + (currCal->calState == CAL_RUNNING || + currCal->calState == CAL_WAITING)) { + iscaldone = ar9002_hw_per_calibration(ah, chan, + rxchainmask, currCal); + if (iscaldone) { + ah->cal_list_curr = currCal = currCal->calNext; + + if (currCal->calState == CAL_WAITING) { + iscaldone = false; + ath9k_hw_reset_calibration(ah, currCal); + } + } + } + + /* Do NF cal only at longer intervals */ + if (longcal) { + /* Do periodic PAOffset Cal */ + ar9002_hw_pa_cal(ah, false); + ar9002_hw_olc_temp_compensation(ah); + + /* + * Get the value from the previous NF cal and update + * history buffer. + */ + ath9k_hw_getnf(ah, chan); + + /* + * Load the NF from history buffer of the current channel. + * NF is slow time-variant, so it is OK to use a historical + * value. + */ + ath9k_hw_loadnf(ah, ah->curchan); + + ath9k_hw_start_nfcal(ah); + } + + return iscaldone; +} + +/* Carrier leakage Calibration fix */ +static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) +{ + struct ath_common *common = ath9k_hw_common(ah); + + REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + if (IS_CHAN_HT20(chan)) { + REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); + REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_FLTR_CAL); + REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); + if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { + ath_print(common, ATH_DBG_CALIBRATE, "offset " + "calibration failed to complete in " + "1ms; noisy ??\n"); + return false; + } + REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); + REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); + REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + } + REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); + if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, + 0, AH_WAIT_TIMEOUT)) { + ath_print(common, ATH_DBG_CALIBRATE, "offset calibration " + "failed to complete in 1ms; noisy ??\n"); + return false; + } + + REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + + return true; +} + +static bool ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan) +{ + int i; + u_int32_t txgain_max; + u_int32_t clc_gain, gain_mask = 0, clc_num = 0; + u_int32_t reg_clc_I0, reg_clc_Q0; + u_int32_t i0_num = 0; + u_int32_t q0_num = 0; + u_int32_t total_num = 0; + u_int32_t reg_rf2g5_org; + bool retv = true; + + if (!(ar9285_hw_cl_cal(ah, chan))) + return false; + + txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7), + AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX); + + for (i = 0; i < (txgain_max+1); i++) { + clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) & + AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S; + if (!(gain_mask & (1 << clc_gain))) { + gain_mask |= (1 << clc_gain); + clc_num++; + } + } + + for (i = 0; i < clc_num; i++) { + reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) + & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S; + reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) + & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S; + if (reg_clc_I0 == 0) + i0_num++; + + if (reg_clc_Q0 == 0) + q0_num++; + } + total_num = i0_num + q0_num; + if (total_num > AR9285_CLCAL_REDO_THRESH) { + reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5); + if (AR_SREV_9285E_20(ah)) { + REG_WRITE(ah, AR9285_RF2G5, + (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | + AR9285_RF2G5_IC50TX_XE_SET); + } else { + REG_WRITE(ah, AR9285_RF2G5, + (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | + AR9285_RF2G5_IC50TX_SET); + } + retv = ar9285_hw_cl_cal(ah, chan); + REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org); + } + return retv; +} + +static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) +{ + struct ath_common *common = ath9k_hw_common(ah); + + if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) { + if (!ar9285_hw_clc(ah, chan)) + return false; + } else { + if (AR_SREV_9280_10_OR_LATER(ah)) { + if (!AR_SREV_9287_10_OR_LATER(ah)) + REG_CLR_BIT(ah, AR_PHY_ADC_CTL, + AR_PHY_ADC_CTL_OFF_PWDADC); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_FLTR_CAL); + } + + /* Calibrate the AGC */ + REG_WRITE(ah, AR_PHY_AGC_CONTROL, + REG_READ(ah, AR_PHY_AGC_CONTROL) | + AR_PHY_AGC_CONTROL_CAL); + + /* Poll for offset calibration complete */ + if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_CAL, + 0, AH_WAIT_TIMEOUT)) { + ath_print(common, ATH_DBG_CALIBRATE, + "offset calibration failed to " + "complete in 1ms; noisy environment?\n"); + return false; + } + + if (AR_SREV_9280_10_OR_LATER(ah)) { + if (!AR_SREV_9287_10_OR_LATER(ah)) + REG_SET_BIT(ah, AR_PHY_ADC_CTL, + AR_PHY_ADC_CTL_OFF_PWDADC); + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_FLTR_CAL); + } + } + + /* Do PA Calibration */ + ar9002_hw_pa_cal(ah, true); + + /* Do NF Calibration after DC offset and other calibrations */ + REG_WRITE(ah, AR_PHY_AGC_CONTROL, + REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); + + ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; + + /* Enable IQ, ADC Gain and ADC DC offset CALs */ + if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { + if (ar9002_hw_iscal_supported(ah, ADC_GAIN_CAL)) { + INIT_CAL(&ah->adcgain_caldata); + INSERT_CAL(ah, &ah->adcgain_caldata); + ath_print(common, ATH_DBG_CALIBRATE, + "enabling ADC Gain Calibration.\n"); + } + if (ar9002_hw_iscal_supported(ah, ADC_DC_CAL)) { + INIT_CAL(&ah->adcdc_caldata); + INSERT_CAL(ah, &ah->adcdc_caldata); + ath_print(common, ATH_DBG_CALIBRATE, + "enabling ADC DC Calibration.\n"); + } + if (ar9002_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { + INIT_CAL(&ah->iq_caldata); + INSERT_CAL(ah, &ah->iq_caldata); + ath_print(common, ATH_DBG_CALIBRATE, + "enabling IQ Calibration.\n"); + } + + ah->cal_list_curr = ah->cal_list; + + if (ah->cal_list_curr) + ath9k_hw_reset_calibration(ah, ah->cal_list_curr); + } + + chan->CalValid = 0; + + return true; +} + +static const struct ath9k_percal_data iq_cal_multi_sample = { + IQ_MISMATCH_CAL, + MAX_CAL_SAMPLES, + PER_MIN_LOG_COUNT, + ar9002_hw_iqcal_collect, + ar9002_hw_iqcalibrate +}; +static const struct ath9k_percal_data iq_cal_single_sample = { + IQ_MISMATCH_CAL, + MIN_CAL_SAMPLES, + PER_MAX_LOG_COUNT, + ar9002_hw_iqcal_collect, + ar9002_hw_iqcalibrate +}; +static const struct ath9k_percal_data adc_gain_cal_multi_sample = { + ADC_GAIN_CAL, + MAX_CAL_SAMPLES, + PER_MIN_LOG_COUNT, + ar9002_hw_adc_gaincal_collect, + ar9002_hw_adc_gaincal_calibrate +}; +static const struct ath9k_percal_data adc_gain_cal_single_sample = { + ADC_GAIN_CAL, + MIN_CAL_SAMPLES, + PER_MAX_LOG_COUNT, + ar9002_hw_adc_gaincal_collect, + ar9002_hw_adc_gaincal_calibrate +}; +static const struct ath9k_percal_data adc_dc_cal_multi_sample = { + ADC_DC_CAL, + MAX_CAL_SAMPLES, + PER_MIN_LOG_COUNT, + ar9002_hw_adc_dccal_collect, + ar9002_hw_adc_dccal_calibrate +}; +static const struct ath9k_percal_data adc_dc_cal_single_sample = { + ADC_DC_CAL, + MIN_CAL_SAMPLES, + PER_MAX_LOG_COUNT, + ar9002_hw_adc_dccal_collect, + ar9002_hw_adc_dccal_calibrate +}; +static const struct ath9k_percal_data adc_init_dc_cal = { + ADC_DC_INIT_CAL, + MIN_CAL_SAMPLES, + INIT_LOG_COUNT, + ar9002_hw_adc_dccal_collect, + ar9002_hw_adc_dccal_calibrate +}; + +static void ar9002_hw_init_cal_settings(struct ath_hw *ah) +{ + if (AR_SREV_9100(ah)) { + ah->iq_caldata.calData = &iq_cal_multi_sample; + ah->supp_cals = IQ_MISMATCH_CAL; + return; + } + + if (AR_SREV_9160_10_OR_LATER(ah)) { + if (AR_SREV_9280_10_OR_LATER(ah)) { + ah->iq_caldata.calData = &iq_cal_single_sample; + ah->adcgain_caldata.calData = + &adc_gain_cal_single_sample; + ah->adcdc_caldata.calData = + &adc_dc_cal_single_sample; + ah->adcdc_calinitdata.calData = + &adc_init_dc_cal; + } else { + ah->iq_caldata.calData = &iq_cal_multi_sample; + ah->adcgain_caldata.calData = + &adc_gain_cal_multi_sample; + ah->adcdc_caldata.calData = + &adc_dc_cal_multi_sample; + ah->adcdc_calinitdata.calData = + &adc_init_dc_cal; + } + ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; + } +} + +void ar9002_hw_attach_calib_ops(struct ath_hw *ah) +{ + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + struct ath_hw_ops *ops = ath9k_hw_ops(ah); + + priv_ops->init_cal_settings = ar9002_hw_init_cal_settings; + priv_ops->init_cal = ar9002_hw_init_cal; + priv_ops->setup_calibration = ar9002_hw_setup_calibration; + priv_ops->iscal_supported = ar9002_hw_iscal_supported; + + ops->calibrate = ar9002_hw_calibrate; +} diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c new file mode 100644 index 000000000000..6a7267764ac9 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" +#include "hw-ops.h" +#include "ar9003_phy.h" + +static void ar9003_hw_setup_calibration(struct ath_hw *ah, + struct ath9k_cal_list *currCal) +{ + /* TODO */ +} + +static bool ar9003_hw_calibrate(struct ath_hw *ah, + struct ath9k_channel *chan, + u8 rxchainmask, + bool longcal) +{ + /* TODO */ + return false; +} + +static bool ar9003_hw_init_cal(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + /* TODO */ + return false; +} + +static void ar9003_hw_init_cal_settings(struct ath_hw *ah) +{ + /* TODO */ +} + +static bool ar9003_hw_iscal_supported(struct ath_hw *ah, + enum ath9k_cal_types calType) +{ + /* TODO */ + return false; +} + +void ar9003_hw_attach_calib_ops(struct ath_hw *ah) +{ + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + struct ath_hw_ops *ops = ath9k_hw_ops(ah); + + priv_ops->init_cal_settings = ar9003_hw_init_cal_settings; + priv_ops->init_cal = ar9003_hw_init_cal; + priv_ops->setup_calibration = ar9003_hw_setup_calibration; + priv_ops->iscal_supported = ar9003_hw_iscal_supported; + + ops->calibrate = ar9003_hw_calibrate; +} diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index aa724c263404..085e1264fbe0 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -18,9 +18,10 @@ #include "hw-ops.h" #include "ar9002_phy.h" +/* Common calibration code */ + /* We can tune this as we go by monitoring really low values */ #define ATH9K_NF_TOO_LOW -60 -#define AR9285_CLCAL_REDO_THRESH 1 /* AR5416 may return very high value (like -31 dBm), in those cases the nf * is incorrect and we should use the static NF value. Later we can try to @@ -108,44 +109,8 @@ static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, return true; } -static void ath9k_hw_setup_calibration(struct ath_hw *ah, - struct ath9k_cal_list *currCal) -{ - struct ath_common *common = ath9k_hw_common(ah); - - REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), - AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, - currCal->calData->calCountMax); - - switch (currCal->calData->calType) { - case IQ_MISMATCH_CAL: - REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); - ath_print(common, ATH_DBG_CALIBRATE, - "starting IQ Mismatch Calibration\n"); - break; - case ADC_GAIN_CAL: - REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); - ath_print(common, ATH_DBG_CALIBRATE, - "starting ADC Gain Calibration\n"); - break; - case ADC_DC_CAL: - REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); - ath_print(common, ATH_DBG_CALIBRATE, - "starting ADC DC Calibration\n"); - break; - case ADC_DC_INIT_CAL: - REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); - ath_print(common, ATH_DBG_CALIBRATE, - "starting Init ADC DC Calibration\n"); - break; - } - - REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), - AR_PHY_TIMING_CTRL4_DO_CAL); -} - -static void ath9k_hw_reset_calibration(struct ath_hw *ah, - struct ath9k_cal_list *currCal) +void ath9k_hw_reset_calibration(struct ath_hw *ah, + struct ath9k_cal_list *currCal) { int i; @@ -163,324 +128,6 @@ static void ath9k_hw_reset_calibration(struct ath_hw *ah, ah->cal_samples = 0; } -static bool ath9k_hw_per_calibration(struct ath_hw *ah, - struct ath9k_channel *ichan, - u8 rxchainmask, - struct ath9k_cal_list *currCal) -{ - bool iscaldone = false; - - if (currCal->calState == CAL_RUNNING) { - if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & - AR_PHY_TIMING_CTRL4_DO_CAL)) { - - currCal->calData->calCollect(ah); - ah->cal_samples++; - - if (ah->cal_samples >= currCal->calData->calNumSamples) { - int i, numChains = 0; - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - if (rxchainmask & (1 << i)) - numChains++; - } - - currCal->calData->calPostProc(ah, numChains); - ichan->CalValid |= currCal->calData->calType; - currCal->calState = CAL_DONE; - iscaldone = true; - } else { - ath9k_hw_setup_calibration(ah, currCal); - } - } - } else if (!(ichan->CalValid & currCal->calData->calType)) { - ath9k_hw_reset_calibration(ah, currCal); - } - - return iscaldone; -} - -/* Assumes you are talking about the currently configured channel */ -static bool ath9k_hw_iscal_supported(struct ath_hw *ah, - enum ath9k_cal_types calType) -{ - struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; - - switch (calType & ah->supp_cals) { - case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ - return true; - case ADC_GAIN_CAL: - case ADC_DC_CAL: - if (!(conf->channel->band == IEEE80211_BAND_2GHZ && - conf_is_ht20(conf))) - return true; - break; - } - return false; -} - -static void ath9k_hw_iqcal_collect(struct ath_hw *ah) -{ - int i; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ah->totalPowerMeasI[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); - ah->totalPowerMeasQ[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); - ah->totalIqCorrMeas[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, - "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", - ah->cal_samples, i, ah->totalPowerMeasI[i], - ah->totalPowerMeasQ[i], - ah->totalIqCorrMeas[i]); - } -} - -static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah) -{ - int i; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ah->totalAdcIOddPhase[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); - ah->totalAdcIEvenPhase[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); - ah->totalAdcQOddPhase[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - ah->totalAdcQEvenPhase[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); - - ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, - "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " - "oddq=0x%08x; evenq=0x%08x;\n", - ah->cal_samples, i, - ah->totalAdcIOddPhase[i], - ah->totalAdcIEvenPhase[i], - ah->totalAdcQOddPhase[i], - ah->totalAdcQEvenPhase[i]); - } -} - -static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah) -{ - int i; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ah->totalAdcDcOffsetIOddPhase[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); - ah->totalAdcDcOffsetIEvenPhase[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); - ah->totalAdcDcOffsetQOddPhase[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - ah->totalAdcDcOffsetQEvenPhase[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); - - ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, - "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " - "oddq=0x%08x; evenq=0x%08x;\n", - ah->cal_samples, i, - ah->totalAdcDcOffsetIOddPhase[i], - ah->totalAdcDcOffsetIEvenPhase[i], - ah->totalAdcDcOffsetQOddPhase[i], - ah->totalAdcDcOffsetQEvenPhase[i]); - } -} - -static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) -{ - struct ath_common *common = ath9k_hw_common(ah); - u32 powerMeasQ, powerMeasI, iqCorrMeas; - u32 qCoffDenom, iCoffDenom; - int32_t qCoff, iCoff; - int iqCorrNeg, i; - - for (i = 0; i < numChains; i++) { - powerMeasI = ah->totalPowerMeasI[i]; - powerMeasQ = ah->totalPowerMeasQ[i]; - iqCorrMeas = ah->totalIqCorrMeas[i]; - - ath_print(common, ATH_DBG_CALIBRATE, - "Starting IQ Cal and Correction for Chain %d\n", - i); - - ath_print(common, ATH_DBG_CALIBRATE, - "Orignal: Chn %diq_corr_meas = 0x%08x\n", - i, ah->totalIqCorrMeas[i]); - - iqCorrNeg = 0; - - if (iqCorrMeas > 0x80000000) { - iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; - iqCorrNeg = 1; - } - - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); - ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", - iqCorrNeg); - - iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; - qCoffDenom = powerMeasQ / 64; - - if ((powerMeasQ != 0) && (iCoffDenom != 0) && - (qCoffDenom != 0)) { - iCoff = iqCorrMeas / iCoffDenom; - qCoff = powerMeasI / qCoffDenom - 64; - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d iCoff = 0x%08x\n", i, iCoff); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d qCoff = 0x%08x\n", i, qCoff); - - iCoff = iCoff & 0x3f; - ath_print(common, ATH_DBG_CALIBRATE, - "New: Chn %d iCoff = 0x%08x\n", i, iCoff); - if (iqCorrNeg == 0x0) - iCoff = 0x40 - iCoff; - - if (qCoff > 15) - qCoff = 15; - else if (qCoff <= -16) - qCoff = 16; - - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", - i, iCoff, qCoff); - - REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), - AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, - iCoff); - REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), - AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, - qCoff); - ath_print(common, ATH_DBG_CALIBRATE, - "IQ Cal and Correction done for Chain %d\n", - i); - } - } - - REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), - AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); -} - -static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) -{ - struct ath_common *common = ath9k_hw_common(ah); - u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset; - u32 qGainMismatch, iGainMismatch, val, i; - - for (i = 0; i < numChains; i++) { - iOddMeasOffset = ah->totalAdcIOddPhase[i]; - iEvenMeasOffset = ah->totalAdcIEvenPhase[i]; - qOddMeasOffset = ah->totalAdcQOddPhase[i]; - qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; - - ath_print(common, ATH_DBG_CALIBRATE, - "Starting ADC Gain Cal for Chain %d\n", i); - - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_i = 0x%08x\n", i, - iOddMeasOffset); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_i = 0x%08x\n", i, - iEvenMeasOffset); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_q = 0x%08x\n", i, - qOddMeasOffset); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_q = 0x%08x\n", i, - qEvenMeasOffset); - - if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { - iGainMismatch = - ((iEvenMeasOffset * 32) / - iOddMeasOffset) & 0x3f; - qGainMismatch = - ((qOddMeasOffset * 32) / - qEvenMeasOffset) & 0x3f; - - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d gain_mismatch_i = 0x%08x\n", i, - iGainMismatch); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d gain_mismatch_q = 0x%08x\n", i, - qGainMismatch); - - val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); - val &= 0xfffff000; - val |= (qGainMismatch) | (iGainMismatch << 6); - REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); - - ath_print(common, ATH_DBG_CALIBRATE, - "ADC Gain Cal done for Chain %d\n", i); - } - } - - REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), - REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | - AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); -} - -static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) -{ - struct ath_common *common = ath9k_hw_common(ah); - u32 iOddMeasOffset, iEvenMeasOffset, val, i; - int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; - const struct ath9k_percal_data *calData = - ah->cal_list_curr->calData; - u32 numSamples = - (1 << (calData->calCountMax + 5)) * calData->calNumSamples; - - for (i = 0; i < numChains; i++) { - iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i]; - iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i]; - qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; - qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; - - ath_print(common, ATH_DBG_CALIBRATE, - "Starting ADC DC Offset Cal for Chain %d\n", i); - - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_i = %d\n", i, - iOddMeasOffset); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_i = %d\n", i, - iEvenMeasOffset); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_q = %d\n", i, - qOddMeasOffset); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_q = %d\n", i, - qEvenMeasOffset); - - iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / - numSamples) & 0x1ff; - qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / - numSamples) & 0x1ff; - - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, - iDcMismatch); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, - qDcMismatch); - - val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); - val &= 0xc0000fff; - val |= (qDcMismatch << 12) | (iDcMismatch << 21); - REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); - - ath_print(common, ATH_DBG_CALIBRATE, - "ADC DC Offset Cal done for Chain %d\n", i); - } - - REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), - REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | - AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); -} - /* This is done for the currently configured channel */ bool ath9k_hw_reset_calvalid(struct ath_hw *ah) { @@ -670,570 +317,3 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) return nf; } EXPORT_SYMBOL(ath9k_hw_getchan_noise); - -static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah) -{ - u32 rddata; - int32_t delta, currPDADC, slope; - - rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); - currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); - - if (ah->initPDADC == 0 || currPDADC == 0) { - /* - * Zero value indicates that no frames have been transmitted yet, - * can't do temperature compensation until frames are transmitted. - */ - return; - } else { - slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); - - if (slope == 0) { /* to avoid divide by zero case */ - delta = 0; - } else { - delta = ((currPDADC - ah->initPDADC)*4) / slope; - } - REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, - AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); - REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, - AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); - } -} - -static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah) -{ - u32 rddata, i; - int delta, currPDADC, regval; - - rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); - currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); - - if (ah->initPDADC == 0 || currPDADC == 0) - return; - - if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) - delta = (currPDADC - ah->initPDADC + 4) / 8; - else - delta = (currPDADC - ah->initPDADC + 5) / 10; - - if (delta != ah->PDADCdelta) { - ah->PDADCdelta = delta; - for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { - regval = ah->originalGain[i] - delta; - if (regval < 0) - regval = 0; - - REG_RMW_FIELD(ah, - AR_PHY_TX_GAIN_TBL1 + i * 4, - AR_PHY_TX_GAIN, regval); - } - } -} - -static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) -{ - u32 regVal; - unsigned int i; - u32 regList [][2] = { - { 0x786c, 0 }, - { 0x7854, 0 }, - { 0x7820, 0 }, - { 0x7824, 0 }, - { 0x7868, 0 }, - { 0x783c, 0 }, - { 0x7838, 0 } , - { 0x7828, 0 } , - }; - - for (i = 0; i < ARRAY_SIZE(regList); i++) - regList[i][1] = REG_READ(ah, regList[i][0]); - - regVal = REG_READ(ah, 0x7834); - regVal &= (~(0x1)); - REG_WRITE(ah, 0x7834, regVal); - regVal = REG_READ(ah, 0x9808); - regVal |= (0x1 << 27); - REG_WRITE(ah, 0x9808, regVal); - - /* 786c,b23,1, pwddac=1 */ - REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); - /* 7854, b5,1, pdrxtxbb=1 */ - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); - /* 7854, b7,1, pdv2i=1 */ - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); - /* 7854, b8,1, pddacinterface=1 */ - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); - /* 7824,b12,0, offcal=0 */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); - /* 7838, b1,0, pwddb=0 */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); - /* 7820,b11,0, enpacal=0 */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); - /* 7820,b25,1, pdpadrv1=0 */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); - /* 7820,b24,0, pdpadrv2=0 */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G1,AR9285_AN_RF2G1_PDPADRV2,0); - /* 7820,b23,0, pdpaout=0 */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); - /* 783c,b14-16,7, padrvgn2tab_0=7 */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G8,AR9285_AN_RF2G8_PADRVGN2TAB0, 7); - /* - * 7838,b29-31,0, padrvgn1tab_0=0 - * does not matter since we turn it off - */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G7,AR9285_AN_RF2G7_PADRVGN2TAB0, 0); - - REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); - - /* Set: - * localmode=1,bmode=1,bmoderxtx=1,synthon=1, - * txon=1,paon=1,oscon=1,synthon_force=1 - */ - REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); - udelay(30); - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0); - - /* find off_6_1; */ - for (i = 6; i > 0; i--) { - regVal = REG_READ(ah, 0x7834); - regVal |= (1 << (20 + i)); - REG_WRITE(ah, 0x7834, regVal); - udelay(1); - //regVal = REG_READ(ah, 0x7834); - regVal &= (~(0x1 << (20 + i))); - regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9) - << (20 + i)); - REG_WRITE(ah, 0x7834, regVal); - } - - regVal = (regVal >>20) & 0x7f; - - /* Update PA cal info */ - if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) { - if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) - ah->pacal_info.max_skipcount = - 2 * ah->pacal_info.max_skipcount; - ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; - } else { - ah->pacal_info.max_skipcount = 1; - ah->pacal_info.skipcount = 0; - ah->pacal_info.prev_offset = regVal; - } - - regVal = REG_READ(ah, 0x7834); - regVal |= 0x1; - REG_WRITE(ah, 0x7834, regVal); - regVal = REG_READ(ah, 0x9808); - regVal &= (~(0x1 << 27)); - REG_WRITE(ah, 0x9808, regVal); - - for (i = 0; i < ARRAY_SIZE(regList); i++) - REG_WRITE(ah, regList[i][0], regList[i][1]); -} - -static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) -{ - struct ath_common *common = ath9k_hw_common(ah); - u32 regVal; - int i, offset, offs_6_1, offs_0; - u32 ccomp_org, reg_field; - u32 regList[][2] = { - { 0x786c, 0 }, - { 0x7854, 0 }, - { 0x7820, 0 }, - { 0x7824, 0 }, - { 0x7868, 0 }, - { 0x783c, 0 }, - { 0x7838, 0 }, - }; - - ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); - - /* PA CAL is not needed for high power solution */ - if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == - AR5416_EEP_TXGAIN_HIGH_POWER) - return; - - if (AR_SREV_9285_11(ah)) { - REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); - udelay(10); - } - - for (i = 0; i < ARRAY_SIZE(regList); i++) - regList[i][1] = REG_READ(ah, regList[i][0]); - - regVal = REG_READ(ah, 0x7834); - regVal &= (~(0x1)); - REG_WRITE(ah, 0x7834, regVal); - regVal = REG_READ(ah, 0x9808); - regVal |= (0x1 << 27); - REG_WRITE(ah, 0x9808, regVal); - - REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); - REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); - REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); - ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf); - - REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); - udelay(30); - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); - - for (i = 6; i > 0; i--) { - regVal = REG_READ(ah, 0x7834); - regVal |= (1 << (19 + i)); - REG_WRITE(ah, 0x7834, regVal); - udelay(1); - regVal = REG_READ(ah, 0x7834); - regVal &= (~(0x1 << (19 + i))); - reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); - regVal |= (reg_field << (19 + i)); - REG_WRITE(ah, 0x7834, regVal); - } - - REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); - udelay(1); - reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); - REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); - offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); - offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); - - offset = (offs_6_1<<1) | offs_0; - offset = offset - 0; - offs_6_1 = offset>>1; - offs_0 = offset & 1; - - if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) { - if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) - ah->pacal_info.max_skipcount = - 2 * ah->pacal_info.max_skipcount; - ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; - } else { - ah->pacal_info.max_skipcount = 1; - ah->pacal_info.skipcount = 0; - ah->pacal_info.prev_offset = offset; - } - - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); - REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); - - regVal = REG_READ(ah, 0x7834); - regVal |= 0x1; - REG_WRITE(ah, 0x7834, regVal); - regVal = REG_READ(ah, 0x9808); - regVal &= (~(0x1 << 27)); - REG_WRITE(ah, 0x9808, regVal); - - for (i = 0; i < ARRAY_SIZE(regList); i++) - REG_WRITE(ah, regList[i][0], regList[i][1]); - - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); - - if (AR_SREV_9285_11(ah)) - REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); - -} - -static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) -{ - if (AR_SREV_9271(ah)) { - if (is_reset || !ah->pacal_info.skipcount) - ar9271_hw_pa_cal(ah, is_reset); - else - ah->pacal_info.skipcount--; - } else if (AR_SREV_9285_11_OR_LATER(ah)) { - if (is_reset || !ah->pacal_info.skipcount) - ar9285_hw_pa_cal(ah, is_reset); - else - ah->pacal_info.skipcount--; - } -} - -static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah) -{ - if (OLC_FOR_AR9287_10_LATER) - ar9287_hw_olc_temp_compensation(ah); - else if (OLC_FOR_AR9280_20_LATER) - ar9280_hw_olc_temp_compensation(ah); -} - -bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, - u8 rxchainmask, bool longcal) -{ - bool iscaldone = true; - struct ath9k_cal_list *currCal = ah->cal_list_curr; - - if (currCal && - (currCal->calState == CAL_RUNNING || - currCal->calState == CAL_WAITING)) { - iscaldone = ath9k_hw_per_calibration(ah, chan, - rxchainmask, currCal); - if (iscaldone) { - ah->cal_list_curr = currCal = currCal->calNext; - - if (currCal->calState == CAL_WAITING) { - iscaldone = false; - ath9k_hw_reset_calibration(ah, currCal); - } - } - } - - /* Do NF cal only at longer intervals */ - if (longcal) { - /* Do periodic PAOffset Cal */ - ar9002_hw_pa_cal(ah, false); - ar9002_hw_olc_temp_compensation(ah); - - /* Get the value from the previous NF cal and update history buffer */ - ath9k_hw_getnf(ah, chan); - - /* - * Load the NF from history buffer of the current channel. - * NF is slow time-variant, so it is OK to use a historical value. - */ - ath9k_hw_loadnf(ah, ah->curchan); - - ath9k_hw_start_nfcal(ah); - } - - return iscaldone; -} -EXPORT_SYMBOL(ath9k_hw_calibrate); - -/* Carrier leakage Calibration fix */ -static bool ar9285_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) -{ - struct ath_common *common = ath9k_hw_common(ah); - - REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - if (IS_CHAN_HT20(chan)) { - REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); - REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_FLTR_CAL); - REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); - if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { - ath_print(common, ATH_DBG_CALIBRATE, "offset " - "calibration failed to complete in " - "1ms; noisy ??\n"); - return false; - } - REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); - REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); - REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - } - REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); - REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); - if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, - 0, AH_WAIT_TIMEOUT)) { - ath_print(common, ATH_DBG_CALIBRATE, "offset calibration " - "failed to complete in 1ms; noisy ??\n"); - return false; - } - - REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); - REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); - - return true; -} - -static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) -{ - int i; - u_int32_t txgain_max; - u_int32_t clc_gain, gain_mask = 0, clc_num = 0; - u_int32_t reg_clc_I0, reg_clc_Q0; - u_int32_t i0_num = 0; - u_int32_t q0_num = 0; - u_int32_t total_num = 0; - u_int32_t reg_rf2g5_org; - bool retv = true; - - if (!(ar9285_cl_cal(ah, chan))) - return false; - - txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7), - AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX); - - for (i = 0; i < (txgain_max+1); i++) { - clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) & - AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S; - if (!(gain_mask & (1 << clc_gain))) { - gain_mask |= (1 << clc_gain); - clc_num++; - } - } - - for (i = 0; i < clc_num; i++) { - reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) - & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S; - reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) - & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S; - if (reg_clc_I0 == 0) - i0_num++; - - if (reg_clc_Q0 == 0) - q0_num++; - } - total_num = i0_num + q0_num; - if (total_num > AR9285_CLCAL_REDO_THRESH) { - reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5); - if (AR_SREV_9285E_20(ah)) { - REG_WRITE(ah, AR9285_RF2G5, - (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | - AR9285_RF2G5_IC50TX_XE_SET); - } else { - REG_WRITE(ah, AR9285_RF2G5, - (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | - AR9285_RF2G5_IC50TX_SET); - } - retv = ar9285_cl_cal(ah, chan); - REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org); - } - return retv; -} - -bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) -{ - struct ath_common *common = ath9k_hw_common(ah); - - if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) { - if (!ar9285_clc(ah, chan)) - return false; - } else { - if (AR_SREV_9280_10_OR_LATER(ah)) { - if (!AR_SREV_9287_10_OR_LATER(ah)) - REG_CLR_BIT(ah, AR_PHY_ADC_CTL, - AR_PHY_ADC_CTL_OFF_PWDADC); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_FLTR_CAL); - } - - /* Calibrate the AGC */ - REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | - AR_PHY_AGC_CONTROL_CAL); - - /* Poll for offset calibration complete */ - if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, - 0, AH_WAIT_TIMEOUT)) { - ath_print(common, ATH_DBG_CALIBRATE, - "offset calibration failed to " - "complete in 1ms; noisy environment?\n"); - return false; - } - - if (AR_SREV_9280_10_OR_LATER(ah)) { - if (!AR_SREV_9287_10_OR_LATER(ah)) - REG_SET_BIT(ah, AR_PHY_ADC_CTL, - AR_PHY_ADC_CTL_OFF_PWDADC); - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_FLTR_CAL); - } - } - - /* Do PA Calibration */ - ar9002_hw_pa_cal(ah, true); - - /* Do NF Calibration after DC offset and other calibrations */ - REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); - - ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; - - /* Enable IQ, ADC Gain and ADC DC offset CALs */ - if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { - if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { - INIT_CAL(&ah->adcgain_caldata); - INSERT_CAL(ah, &ah->adcgain_caldata); - ath_print(common, ATH_DBG_CALIBRATE, - "enabling ADC Gain Calibration.\n"); - } - if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { - INIT_CAL(&ah->adcdc_caldata); - INSERT_CAL(ah, &ah->adcdc_caldata); - ath_print(common, ATH_DBG_CALIBRATE, - "enabling ADC DC Calibration.\n"); - } - if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { - INIT_CAL(&ah->iq_caldata); - INSERT_CAL(ah, &ah->iq_caldata); - ath_print(common, ATH_DBG_CALIBRATE, - "enabling IQ Calibration.\n"); - } - - ah->cal_list_curr = ah->cal_list; - - if (ah->cal_list_curr) - ath9k_hw_reset_calibration(ah, ah->cal_list_curr); - } - - chan->CalValid = 0; - - return true; -} - -const struct ath9k_percal_data iq_cal_multi_sample = { - IQ_MISMATCH_CAL, - MAX_CAL_SAMPLES, - PER_MIN_LOG_COUNT, - ath9k_hw_iqcal_collect, - ath9k_hw_iqcalibrate -}; -const struct ath9k_percal_data iq_cal_single_sample = { - IQ_MISMATCH_CAL, - MIN_CAL_SAMPLES, - PER_MAX_LOG_COUNT, - ath9k_hw_iqcal_collect, - ath9k_hw_iqcalibrate -}; -const struct ath9k_percal_data adc_gain_cal_multi_sample = { - ADC_GAIN_CAL, - MAX_CAL_SAMPLES, - PER_MIN_LOG_COUNT, - ath9k_hw_adc_gaincal_collect, - ath9k_hw_adc_gaincal_calibrate -}; -const struct ath9k_percal_data adc_gain_cal_single_sample = { - ADC_GAIN_CAL, - MIN_CAL_SAMPLES, - PER_MAX_LOG_COUNT, - ath9k_hw_adc_gaincal_collect, - ath9k_hw_adc_gaincal_calibrate -}; -const struct ath9k_percal_data adc_dc_cal_multi_sample = { - ADC_DC_CAL, - MAX_CAL_SAMPLES, - PER_MIN_LOG_COUNT, - ath9k_hw_adc_dccal_collect, - ath9k_hw_adc_dccal_calibrate -}; -const struct ath9k_percal_data adc_dc_cal_single_sample = { - ADC_DC_CAL, - MIN_CAL_SAMPLES, - PER_MAX_LOG_COUNT, - ath9k_hw_adc_dccal_collect, - ath9k_hw_adc_dccal_calibrate -}; -const struct ath9k_percal_data adc_init_dc_cal = { - ADC_DC_INIT_CAL, - MIN_CAL_SAMPLES, - INIT_LOG_COUNT, - ath9k_hw_adc_dccal_collect, - ath9k_hw_adc_dccal_calibrate -}; diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index b2c873e97485..9f6c21d50f17 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -19,14 +19,6 @@ #include "hw.h" -extern const struct ath9k_percal_data iq_cal_multi_sample; -extern const struct ath9k_percal_data iq_cal_single_sample; -extern const struct ath9k_percal_data adc_gain_cal_multi_sample; -extern const struct ath9k_percal_data adc_gain_cal_single_sample; -extern const struct ath9k_percal_data adc_dc_cal_multi_sample; -extern const struct ath9k_percal_data adc_dc_cal_single_sample; -extern const struct ath9k_percal_data adc_init_dc_cal; - #define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85 #define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112 #define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118 @@ -127,9 +119,8 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah); s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); -bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, - u8 rxchainmask, bool longcal); -bool ath9k_hw_init_cal(struct ath_hw *ah, - struct ath9k_channel *chan); +void ath9k_hw_reset_calibration(struct ath_hw *ah, + struct ath9k_cal_list *currCal); + #endif /* CALIB_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index e2b8ad4df904..3848c0d3f99e 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -44,6 +44,14 @@ static inline void ath9k_hw_get_desc_link(struct ath_hw *ah, void *ds, { ath9k_hw_ops(ah)->get_desc_link(ds, link); } +static inline bool ath9k_hw_calibrate(struct ath_hw *ah, + struct ath9k_channel *chan, + u8 rxchainmask, + bool longcal) +{ + return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal); +} + /* Private hardware call ops */ /* PHY ops */ @@ -166,7 +174,25 @@ static inline bool ath9k_hw_ani_control(struct ath_hw *ah, static inline void ath9k_hw_do_getnf(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]) { - return ath9k_hw_private_ops(ah)->do_getnf(ah, nfarray); + ath9k_hw_private_ops(ah)->do_getnf(ah, nfarray); +} + +static inline bool ath9k_hw_init_cal(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + return ath9k_hw_private_ops(ah)->init_cal(ah, chan); +} + +static inline void ath9k_hw_setup_calibration(struct ath_hw *ah, + struct ath9k_cal_list *currCal) +{ + ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal); +} + +static inline bool ath9k_hw_iscal_supported(struct ath_hw *ah, + enum ath9k_cal_types calType) +{ + return ath9k_hw_private_ops(ah)->iscal_supported(ah, calType); } #endif /* ATH9K_HW_OPS_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 67c2becad662..e6d4c4c8a3df 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -600,36 +600,6 @@ static bool ar9003_hw_macversion_supported(u32 macversion) return false; } -static void ar9002_hw_init_cal_settings(struct ath_hw *ah) -{ - if (AR_SREV_9100(ah)) { - ah->iq_caldata.calData = &iq_cal_multi_sample; - ah->supp_cals = IQ_MISMATCH_CAL; - return; - } - - if (AR_SREV_9160_10_OR_LATER(ah)) { - if (AR_SREV_9280_10_OR_LATER(ah)) { - ah->iq_caldata.calData = &iq_cal_single_sample; - ah->adcgain_caldata.calData = - &adc_gain_cal_single_sample; - ah->adcdc_caldata.calData = - &adc_dc_cal_single_sample; - ah->adcdc_calinitdata.calData = - &adc_init_dc_cal; - } else { - ah->iq_caldata.calData = &iq_cal_multi_sample; - ah->adcgain_caldata.calData = - &adc_gain_cal_multi_sample; - ah->adcdc_caldata.calData = - &adc_dc_cal_multi_sample; - ah->adcdc_calinitdata.calData = - &adc_init_dc_cal; - } - ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; - } -} - static void ar9002_hw_init_mode_regs(struct ath_hw *ah) { if (AR_SREV_9271(ah)) { @@ -3641,7 +3611,6 @@ static void ar9002_hw_attach_ops(struct ath_hw *ah) struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); struct ath_hw_ops *ops = ath9k_hw_ops(ah); - priv_ops->init_cal_settings = ar9002_hw_init_cal_settings; priv_ops->init_mode_regs = ar9002_hw_init_mode_regs; priv_ops->macversion_supported = ar9002_hw_macversion_supported; @@ -3651,6 +3620,7 @@ static void ar9002_hw_attach_ops(struct ath_hw *ah) if (AR_SREV_9280_10_OR_LATER(ah)) ar9002_hw_attach_phy_ops(ah); + ar9002_hw_attach_calib_ops(ah); ar9002_hw_attach_mac_ops(ah); } @@ -3663,6 +3633,6 @@ static void ar9003_hw_attach_ops(struct ath_hw *ah) priv_ops->macversion_supported = ar9003_hw_macversion_supported; ar9003_hw_attach_phy_ops(ah); - + ar9003_hw_attach_calib_ops(ah); ar9003_hw_attach_mac_ops(ah); } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 48fb5ce8294b..7ef93c8df923 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -469,7 +469,9 @@ struct ath_gen_timer_table { * This structure contains private callbacks designed to only be used internally * by the hardware core. * - * @init_cal_settings: Initializes calibration settings + * @init_cal_settings: setup types of calibrations supported + * @init_cal: starts actual calibration + * * @init_mode_regs: Initializes mode registers * @macversion_supported: If this specific mac revision is supported * @@ -480,11 +482,20 @@ struct ath_gen_timer_table { * @set_rf_regs: * @compute_pll_control: compute the PLL control value to use for * AR_RTC_PLL_CONTROL for a given channel + * @setup_calibration: set up calibration + * @iscal_supported: used to query if a type of calibration is supported */ struct ath_hw_private_ops { + /* Calibration ops */ void (*init_cal_settings)(struct ath_hw *ah); + bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan); + void (*init_mode_regs)(struct ath_hw *ah); bool (*macversion_supported)(u32 macversion); + void (*setup_calibration)(struct ath_hw *ah, + struct ath9k_cal_list *currCal); + bool (*iscal_supported)(struct ath_hw *ah, + enum ath9k_cal_types calType); /* PHY ops */ int (*rf_set_freq)(struct ath_hw *ah, @@ -523,6 +534,7 @@ struct ath_hw_private_ops { * hardware code and also by the lower level driver. * * @config_pci_powersave: + * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC */ struct ath_hw_ops { void (*config_pci_powersave)(struct ath_hw *ah, @@ -531,6 +543,10 @@ struct ath_hw_ops { void (*rx_enable)(struct ath_hw *ah); void (*set_desc_link)(void *ds, u32 link); void (*get_desc_link)(void *ds, u32 **link); + bool (*calibrate)(struct ath_hw *ah, + struct ath9k_channel *chan, + u8 rxchainmask, + bool longcal); }; struct ath_hw { @@ -833,6 +849,9 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah); void ar9002_hw_attach_phy_ops(struct ath_hw *ah); void ar9003_hw_attach_phy_ops(struct ath_hw *ah); +void ar9002_hw_attach_calib_ops(struct ath_hw *ah); +void ar9003_hw_attach_calib_ops(struct ath_hw *ah); + #define ATH_PCIE_CAP_LINK_CTRL 0x70 #define ATH_PCIE_CAP_LINK_L0S 1 #define ATH_PCIE_CAP_LINK_L1 2 -- cgit v1.2.3 From 590b7d2f10f4552e5b7570c84dc565d3cb7825c9 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:01 -0400 Subject: ath9k_hw: add the AR9003 ar9003_hw_init_cal callback Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 145 +++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 6a7267764ac9..00e4cb8d5f04 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -40,9 +40,152 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, return false; } +static void ar9003_hw_iqcal_collect(struct ath_hw *ah) +{ + int i; + + /* Accumulate IQ cal measures for active chains */ + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + ah->totalPowerMeasI[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + ah->totalPowerMeasQ[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + ah->totalIqCorrMeas[i] += + (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", + ah->cal_samples, i, ah->totalPowerMeasI[i], + ah->totalPowerMeasQ[i], + ah->totalIqCorrMeas[i]); + } +} + +static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) +{ + struct ath_common *common = ath9k_hw_common(ah); + u32 powerMeasQ, powerMeasI, iqCorrMeas; + u32 qCoffDenom, iCoffDenom; + int32_t qCoff, iCoff; + int iqCorrNeg, i; + const u_int32_t offset_array[3] = { + AR_PHY_RX_IQCAL_CORR_B0, + AR_PHY_RX_IQCAL_CORR_B1, + AR_PHY_RX_IQCAL_CORR_B2, + }; + + for (i = 0; i < numChains; i++) { + powerMeasI = ah->totalPowerMeasI[i]; + powerMeasQ = ah->totalPowerMeasQ[i]; + iqCorrMeas = ah->totalIqCorrMeas[i]; + + ath_print(common, ATH_DBG_CALIBRATE, + "Starting IQ Cal and Correction for Chain %d\n", + i); + + ath_print(common, ATH_DBG_CALIBRATE, + "Orignal: Chn %diq_corr_meas = 0x%08x\n", + i, ah->totalIqCorrMeas[i]); + + iqCorrNeg = 0; + + if (iqCorrMeas > 0x80000000) { + iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; + iqCorrNeg = 1; + } + + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); + ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", + iqCorrNeg); + + iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256; + qCoffDenom = powerMeasQ / 64; + + if ((iCoffDenom != 0) && (qCoffDenom != 0)) { + iCoff = iqCorrMeas / iCoffDenom; + qCoff = powerMeasI / qCoffDenom - 64; + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d iCoff = 0x%08x\n", i, iCoff); + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d qCoff = 0x%08x\n", i, qCoff); + + /* Force bounds on iCoff */ + if (iCoff >= 63) + iCoff = 63; + else if (iCoff <= -63) + iCoff = -63; + + /* Negate iCoff if iqCorrNeg == 0 */ + if (iqCorrNeg == 0x0) + iCoff = -iCoff; + + /* Force bounds on qCoff */ + if (qCoff >= 63) + qCoff = 63; + else if (qCoff <= -63) + qCoff = -63; + + iCoff = iCoff & 0x7f; + qCoff = qCoff & 0x7f; + + ath_print(common, ATH_DBG_CALIBRATE, + "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", + i, iCoff, qCoff); + ath_print(common, ATH_DBG_CALIBRATE, + "Register offset (0x%04x) " + "before update = 0x%x\n", + offset_array[i], + REG_READ(ah, offset_array[i])); + + REG_RMW_FIELD(ah, offset_array[i], + AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, + iCoff); + REG_RMW_FIELD(ah, offset_array[i], + AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, + qCoff); + ath_print(common, ATH_DBG_CALIBRATE, + "Register offset (0x%04x) QI COFF " + "(bitfields 0x%08x) after update = 0x%x\n", + offset_array[i], + AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, + REG_READ(ah, offset_array[i])); + ath_print(common, ATH_DBG_CALIBRATE, + "Register offset (0x%04x) QQ COFF " + "(bitfields 0x%08x) after update = 0x%x\n", + offset_array[i], + AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, + REG_READ(ah, offset_array[i])); + + ath_print(common, ATH_DBG_CALIBRATE, + "IQ Cal and Correction done for Chain %d\n", + i); + } + } + + REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0, + AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE); + ath_print(common, ATH_DBG_CALIBRATE, + "IQ Cal and Correction (offset 0x%04x) enabled " + "(bit position 0x%08x). New Value 0x%08x\n", + (unsigned) (AR_PHY_RX_IQCAL_CORR_B0), + AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE, + REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0)); +} + +static const struct ath9k_percal_data iq_cal_single_sample = { + IQ_MISMATCH_CAL, + MIN_CAL_SAMPLES, + PER_MAX_LOG_COUNT, + ar9003_hw_iqcal_collect, + ar9003_hw_iqcalibrate +}; + static void ar9003_hw_init_cal_settings(struct ath_hw *ah) { - /* TODO */ + ah->iq_caldata.calData = &iq_cal_single_sample; + ah->supp_cals = IQ_MISMATCH_CAL; } static bool ar9003_hw_iscal_supported(struct ath_hw *ah, -- cgit v1.2.3 From 204729fd182bd56180323d9293c31038dde32995 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:02 -0400 Subject: ath9k_hw: add the config_pci_powersave AR9003 callback Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index e6d4c4c8a3df..0db3475487cb 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2594,6 +2594,37 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) } EXPORT_SYMBOL(ath9k_hw_set_interrupts); +/* + * Helper for ASPM support. + * + * Disable PLL when in L0s as well as receiver clock when in L1. + * This power saving option must be enabled through the SerDes. + * + * Programming the SerDes must go through the same 288 bit serial shift + * register as the other analog registers. Hence the 9 writes. + */ +static void ar9003_hw_configpcipowersave(struct ath_hw *ah, + int restore, + int power_off) +{ + if (ah->is_pciexpress != true) + return; + + /* Do not touch SerDes registers */ + if (ah->config.pcie_powersave_enable == 2) + return; + + /* Nothing to do on restore for 11N */ + if (!restore) { + /* set bit 19 to allow forcing of pcie core into L1 state */ + REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + + /* Several PCIe massages to ensure proper behaviour */ + if (ah->config.pcie_waen) + REG_WRITE(ah, AR_WA, ah->config.pcie_waen); + } +} + /*******************/ /* Beacon Handling */ /*******************/ @@ -3628,10 +3659,13 @@ static void ar9002_hw_attach_ops(struct ath_hw *ah) static void ar9003_hw_attach_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + struct ath_hw_ops *ops = ath9k_hw_ops(ah); priv_ops->init_mode_regs = ar9003_hw_init_mode_regs; priv_ops->macversion_supported = ar9003_hw_macversion_supported; + ops->config_pci_powersave = ar9003_hw_configpcipowersave; + ar9003_hw_attach_phy_ops(ah); ar9003_hw_attach_calib_ops(ah); ar9003_hw_attach_mac_ops(ah); -- cgit v1.2.3 From b3950e6a52b1d0279787ef44ba1efac2f3414260 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:03 -0400 Subject: ath9k_hw: split the generic hardware code by hardware family Move out the generic hardware family code out into their own files, we have one for AR5008, AR9001, and AR9002 family (ar9002_hw.c) and another file for the new AR9003 hardware family (ar9003_hw.c). Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Makefile | 5 +- drivers/net/wireless/ath/ath9k/ar9002_hw.c | 383 ++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_hw.c | 149 +++++++++ drivers/net/wireless/ath/ath9k/hw.c | 498 +---------------------------- drivers/net/wireless/ath/ath9k/hw.h | 5 +- 5 files changed, 541 insertions(+), 499 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/ar9002_hw.c create mode 100644 drivers/net/wireless/ath/ath9k/ar9003_hw.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index d2417ed8ec4c..ee8f7e87e9ce 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -13,7 +13,10 @@ ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o obj-$(CONFIG_ATH9K) += ath9k.o -ath9k_hw-y:= hw.o \ +ath9k_hw-y:= \ + ar9002_hw.o \ + ar9003_hw.o \ + hw.o \ ar9003_phy.o \ ar9002_phy.o \ ar5008_phy.o \ diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c new file mode 100644 index 000000000000..aa52fd7b630c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" +#include "ar5008_initvals.h" +#include "ar9001_initvals.h" +#include "ar9002_initvals.h" + +/* General hardware code for the A5008/AR9001/AR9002 hadware families */ + +static bool ar9002_hw_macversion_supported(u32 macversion) +{ + switch (macversion) { + case AR_SREV_VERSION_5416_PCI: + case AR_SREV_VERSION_5416_PCIE: + case AR_SREV_VERSION_9160: + case AR_SREV_VERSION_9100: + case AR_SREV_VERSION_9280: + case AR_SREV_VERSION_9285: + case AR_SREV_VERSION_9287: + case AR_SREV_VERSION_9271: + return true; + default: + break; + } + return false; +} + +static void ar9002_hw_init_mode_regs(struct ath_hw *ah) +{ + if (AR_SREV_9271(ah)) { + INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271, + ARRAY_SIZE(ar9271Modes_9271), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271, + ARRAY_SIZE(ar9271Common_9271), 2); + INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271, + ar9271Common_normal_cck_fir_coeff_9271, + ARRAY_SIZE(ar9271Common_normal_cck_fir_coeff_9271), 2); + INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271, + ar9271Common_japan_2484_cck_fir_coeff_9271, + ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2); + INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only, + ar9271Modes_9271_1_0_only, + ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6); + INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg, + ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6); + INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271, + ar9271Modes_high_power_tx_gain_9271, + ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6); + INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, + ar9271Modes_normal_power_tx_gain_9271, + ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6); + return; + } + + if (AR_SREV_9287_11_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1, + ARRAY_SIZE(ar9287Modes_9287_1_1), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1, + ARRAY_SIZE(ar9287Common_9287_1_1), 2); + if (ah->config.pcie_clock_req) + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9287PciePhy_clkreq_off_L1_9287_1_1, + ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2); + else + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9287PciePhy_clkreq_always_on_L1_9287_1_1, + ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1), + 2); + } else if (AR_SREV_9287_10_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_0, + ARRAY_SIZE(ar9287Modes_9287_1_0), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_0, + ARRAY_SIZE(ar9287Common_9287_1_0), 2); + + if (ah->config.pcie_clock_req) + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9287PciePhy_clkreq_off_L1_9287_1_0, + ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_0), 2); + else + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9287PciePhy_clkreq_always_on_L1_9287_1_0, + ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_0), + 2); + } else if (AR_SREV_9285_12_OR_LATER(ah)) { + + + INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, + ARRAY_SIZE(ar9285Modes_9285_1_2), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2, + ARRAY_SIZE(ar9285Common_9285_1_2), 2); + + if (ah->config.pcie_clock_req) { + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9285PciePhy_clkreq_off_L1_9285_1_2, + ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2); + } else { + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9285PciePhy_clkreq_always_on_L1_9285_1_2, + ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2), + 2); + } + } else if (AR_SREV_9285_10_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285, + ARRAY_SIZE(ar9285Modes_9285), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285, + ARRAY_SIZE(ar9285Common_9285), 2); + + if (ah->config.pcie_clock_req) { + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9285PciePhy_clkreq_off_L1_9285, + ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2); + } else { + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9285PciePhy_clkreq_always_on_L1_9285, + ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2); + } + } else if (AR_SREV_9280_20_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2, + ARRAY_SIZE(ar9280Modes_9280_2), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2, + ARRAY_SIZE(ar9280Common_9280_2), 2); + + if (ah->config.pcie_clock_req) { + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9280PciePhy_clkreq_off_L1_9280, + ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280), 2); + } else { + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9280PciePhy_clkreq_always_on_L1_9280, + ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2); + } + INIT_INI_ARRAY(&ah->iniModesAdditional, + ar9280Modes_fast_clock_9280_2, + ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3); + } else if (AR_SREV_9280_10_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280, + ARRAY_SIZE(ar9280Modes_9280), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280, + ARRAY_SIZE(ar9280Common_9280), 2); + } else if (AR_SREV_9160_10_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160, + ARRAY_SIZE(ar5416Modes_9160), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160, + ARRAY_SIZE(ar5416Common_9160), 2); + INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160, + ARRAY_SIZE(ar5416Bank0_9160), 2); + INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160, + ARRAY_SIZE(ar5416BB_RfGain_9160), 3); + INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160, + ARRAY_SIZE(ar5416Bank1_9160), 2); + INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160, + ARRAY_SIZE(ar5416Bank2_9160), 2); + INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160, + ARRAY_SIZE(ar5416Bank3_9160), 3); + INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160, + ARRAY_SIZE(ar5416Bank6_9160), 3); + INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160, + ARRAY_SIZE(ar5416Bank6TPC_9160), 3); + INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160, + ARRAY_SIZE(ar5416Bank7_9160), 2); + if (AR_SREV_9160_11(ah)) { + INIT_INI_ARRAY(&ah->iniAddac, + ar5416Addac_91601_1, + ARRAY_SIZE(ar5416Addac_91601_1), 2); + } else { + INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160, + ARRAY_SIZE(ar5416Addac_9160), 2); + } + } else if (AR_SREV_9100_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100, + ARRAY_SIZE(ar5416Modes_9100), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100, + ARRAY_SIZE(ar5416Common_9100), 2); + INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100, + ARRAY_SIZE(ar5416Bank0_9100), 2); + INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100, + ARRAY_SIZE(ar5416BB_RfGain_9100), 3); + INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100, + ARRAY_SIZE(ar5416Bank1_9100), 2); + INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100, + ARRAY_SIZE(ar5416Bank2_9100), 2); + INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100, + ARRAY_SIZE(ar5416Bank3_9100), 3); + INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100, + ARRAY_SIZE(ar5416Bank6_9100), 3); + INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100, + ARRAY_SIZE(ar5416Bank6TPC_9100), 3); + INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100, + ARRAY_SIZE(ar5416Bank7_9100), 2); + INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100, + ARRAY_SIZE(ar5416Addac_9100), 2); + } else { + INIT_INI_ARRAY(&ah->iniModes, ar5416Modes, + ARRAY_SIZE(ar5416Modes), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar5416Common, + ARRAY_SIZE(ar5416Common), 2); + INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0, + ARRAY_SIZE(ar5416Bank0), 2); + INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain, + ARRAY_SIZE(ar5416BB_RfGain), 3); + INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1, + ARRAY_SIZE(ar5416Bank1), 2); + INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2, + ARRAY_SIZE(ar5416Bank2), 2); + INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3, + ARRAY_SIZE(ar5416Bank3), 3); + INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6, + ARRAY_SIZE(ar5416Bank6), 3); + INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC, + ARRAY_SIZE(ar5416Bank6TPC), 3); + INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7, + ARRAY_SIZE(ar5416Bank7), 2); + INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac, + ARRAY_SIZE(ar5416Addac), 2); + } +} + +/* + * Helper for ASPM support. + * + * Disable PLL when in L0s as well as receiver clock when in L1. + * This power saving option must be enabled through the SerDes. + * + * Programming the SerDes must go through the same 288 bit serial shift + * register as the other analog registers. Hence the 9 writes. + */ +static void ar9002_hw_configpcipowersave(struct ath_hw *ah, + int restore, + int power_off) +{ + u8 i; + u32 val; + + if (ah->is_pciexpress != true) + return; + + /* Do not touch SerDes registers */ + if (ah->config.pcie_powersave_enable == 2) + return; + + /* Nothing to do on restore for 11N */ + if (!restore) { + if (AR_SREV_9280_20_OR_LATER(ah)) { + /* + * AR9280 2.0 or later chips use SerDes values from the + * initvals.h initialized depending on chipset during + * __ath9k_hw_init() + */ + for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { + REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), + INI_RA(&ah->iniPcieSerdes, i, 1)); + } + } else if (AR_SREV_9280(ah) && + (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) { + REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00); + REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); + + /* RX shut off when elecidle is asserted */ + REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019); + REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820); + REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560); + + /* Shut off CLKREQ active in L1 */ + if (ah->config.pcie_clock_req) + REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc); + else + REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd); + + REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); + REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); + REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); + + /* Load the new settings */ + REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); + + } else { + REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); + REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); + + /* RX shut off when elecidle is asserted */ + REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); + REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); + REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); + + /* + * Ignore ah->ah_config.pcie_clock_req setting for + * pre-AR9280 11n + */ + REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); + + REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); + REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); + REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); + + /* Load the new settings */ + REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); + } + + udelay(1000); + + /* set bit 19 to allow forcing of pcie core into L1 state */ + REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + + /* Several PCIe massages to ensure proper behaviour */ + if (ah->config.pcie_waen) { + val = ah->config.pcie_waen; + if (!power_off) + val &= (~AR_WA_D3_L1_DISABLE); + } else { + if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || + AR_SREV_9287(ah)) { + val = AR9285_WA_DEFAULT; + if (!power_off) + val &= (~AR_WA_D3_L1_DISABLE); + } else if (AR_SREV_9280(ah)) { + /* + * On AR9280 chips bit 22 of 0x4004 needs to be + * set otherwise card may disappear. + */ + val = AR9280_WA_DEFAULT; + if (!power_off) + val &= (~AR_WA_D3_L1_DISABLE); + } else + val = AR_WA_DEFAULT; + } + + REG_WRITE(ah, AR_WA, val); + } + + if (power_off) { + /* + * Set PCIe workaround bits + * bit 14 in WA register (disable L1) should only + * be set when device enters D3 and be cleared + * when device comes back to D0. + */ + if (ah->config.pcie_waen) { + if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) + REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); + } else { + if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) || + AR_SREV_9287(ah)) && + (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) || + (AR_SREV_9280(ah) && + (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) { + REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); + } + } + } +} + +/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */ +void ar9002_hw_attach_ops(struct ath_hw *ah) +{ + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + struct ath_hw_ops *ops = ath9k_hw_ops(ah); + + priv_ops->init_mode_regs = ar9002_hw_init_mode_regs; + priv_ops->macversion_supported = ar9002_hw_macversion_supported; + + ops->config_pci_powersave = ar9002_hw_configpcipowersave; + + ar5008_hw_attach_phy_ops(ah); + if (AR_SREV_9280_10_OR_LATER(ah)) + ar9002_hw_attach_phy_ops(ah); + + ar9002_hw_attach_calib_ops(ah); + ar9002_hw_attach_mac_ops(ah); +} diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c new file mode 100644 index 000000000000..6111bdb7779b --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" +#include "ar9003_initvals.h" + +/* General hardware code for the AR9003 hadware family */ + +static bool ar9003_hw_macversion_supported(u32 macversion) +{ + switch (macversion) { + case AR_SREV_VERSION_9300: + return true; + default: + break; + } + return false; +} + +/* AR9003 2.0 - new INI format (pre, core, post arrays per subsystem) */ +static void ar9003_hw_init_mode_regs(struct ath_hw *ah) +{ + /* mac */ + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], + ar9300_2p0_mac_core, + ARRAY_SIZE(ar9300_2p0_mac_core), 2); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], + ar9300_2p0_mac_postamble, + ARRAY_SIZE(ar9300_2p0_mac_postamble), 5); + + /* bb */ + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], + ar9300_2p0_baseband_core, + ARRAY_SIZE(ar9300_2p0_baseband_core), 2); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], + ar9300_2p0_baseband_postamble, + ARRAY_SIZE(ar9300_2p0_baseband_postamble), 5); + + /* radio */ + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], + ar9300_2p0_radio_core, + ARRAY_SIZE(ar9300_2p0_radio_core), 2); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], + ar9300_2p0_radio_postamble, + ARRAY_SIZE(ar9300_2p0_radio_postamble), 5); + + /* soc */ + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], + ar9300_2p0_soc_preamble, + ARRAY_SIZE(ar9300_2p0_soc_preamble), 2); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], + ar9300_2p0_soc_postamble, + ARRAY_SIZE(ar9300_2p0_soc_postamble), 5); + + /* rx/tx gain */ + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9300Common_rx_gain_table_2p0, + ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), 2); + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_lowest_ob_db_tx_gain_table_2p0, + ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0), + 5); + + /* Load PCIE SERDES settings from INI */ + + /* Awake Setting */ + + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9300PciePhy_pll_on_clkreq_disable_L1_2p0, + ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p0), + 2); + + /* Sleep Setting */ + + INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, + ar9300PciePhy_clkreq_enable_L1_2p0, + ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p0), + 2); + + /* Fast clock modal settings */ + INIT_INI_ARRAY(&ah->iniModesAdditional, + ar9300Modes_fast_clock_2p0, + ARRAY_SIZE(ar9300Modes_fast_clock_2p0), + 3); +} + +/* + * Helper for ASPM support. + * + * Disable PLL when in L0s as well as receiver clock when in L1. + * This power saving option must be enabled through the SerDes. + * + * Programming the SerDes must go through the same 288 bit serial shift + * register as the other analog registers. Hence the 9 writes. + */ +static void ar9003_hw_configpcipowersave(struct ath_hw *ah, + int restore, + int power_off) +{ + if (ah->is_pciexpress != true) + return; + + /* Do not touch SerDes registers */ + if (ah->config.pcie_powersave_enable == 2) + return; + + /* Nothing to do on restore for 11N */ + if (!restore) { + /* set bit 19 to allow forcing of pcie core into L1 state */ + REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + + /* Several PCIe massages to ensure proper behaviour */ + if (ah->config.pcie_waen) + REG_WRITE(ah, AR_WA, ah->config.pcie_waen); + } +} + +/* Sets up the AR9003 hardware familiy callbacks */ +void ar9003_hw_attach_ops(struct ath_hw *ah) +{ + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + struct ath_hw_ops *ops = ath9k_hw_ops(ah); + + priv_ops->init_mode_regs = ar9003_hw_init_mode_regs; + priv_ops->macversion_supported = ar9003_hw_macversion_supported; + + ops->config_pci_powersave = ar9003_hw_configpcipowersave; + + ar9003_hw_attach_phy_ops(ah); + ar9003_hw_attach_calib_ops(ah); + ar9003_hw_attach_mac_ops(ah); +} diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 0db3475487cb..3157ddeab31c 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2010 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -20,18 +20,12 @@ #include "hw.h" #include "hw-ops.h" #include "rc.h" -#include "ar5008_initvals.h" -#include "ar9001_initvals.h" #include "ar9002_initvals.h" -#include "ar9003_initvals.h" #define ATH9K_CLOCK_RATE_CCK 22 #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 -static void ar9002_hw_attach_ops(struct ath_hw *ah); -static void ar9003_hw_attach_ops(struct ath_hw *ah); - static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); MODULE_AUTHOR("Atheros Communications"); @@ -571,296 +565,6 @@ static int ath9k_hw_post_init(struct ath_hw *ah) return 0; } -static bool ar9002_hw_macversion_supported(u32 macversion) -{ - switch (macversion) { - case AR_SREV_VERSION_5416_PCI: - case AR_SREV_VERSION_5416_PCIE: - case AR_SREV_VERSION_9160: - case AR_SREV_VERSION_9100: - case AR_SREV_VERSION_9280: - case AR_SREV_VERSION_9285: - case AR_SREV_VERSION_9287: - case AR_SREV_VERSION_9271: - return true; - default: - break; - } - return false; -} - -static bool ar9003_hw_macversion_supported(u32 macversion) -{ - switch (macversion) { - case AR_SREV_VERSION_9300: - return true; - default: - break; - } - return false; -} - -static void ar9002_hw_init_mode_regs(struct ath_hw *ah) -{ - if (AR_SREV_9271(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271, - ARRAY_SIZE(ar9271Modes_9271), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271, - ARRAY_SIZE(ar9271Common_9271), 2); - INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271, - ar9271Common_normal_cck_fir_coeff_9271, - ARRAY_SIZE(ar9271Common_normal_cck_fir_coeff_9271), 2); - INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271, - ar9271Common_japan_2484_cck_fir_coeff_9271, - ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2); - INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only, - ar9271Modes_9271_1_0_only, - ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6); - INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg, - ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6); - INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271, - ar9271Modes_high_power_tx_gain_9271, - ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6); - INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, - ar9271Modes_normal_power_tx_gain_9271, - ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6); - return; - } - - if (AR_SREV_9287_11_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1, - ARRAY_SIZE(ar9287Modes_9287_1_1), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1, - ARRAY_SIZE(ar9287Common_9287_1_1), 2); - if (ah->config.pcie_clock_req) - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9287PciePhy_clkreq_off_L1_9287_1_1, - ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2); - else - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9287PciePhy_clkreq_always_on_L1_9287_1_1, - ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1), - 2); - } else if (AR_SREV_9287_10_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_0, - ARRAY_SIZE(ar9287Modes_9287_1_0), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_0, - ARRAY_SIZE(ar9287Common_9287_1_0), 2); - - if (ah->config.pcie_clock_req) - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9287PciePhy_clkreq_off_L1_9287_1_0, - ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_0), 2); - else - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9287PciePhy_clkreq_always_on_L1_9287_1_0, - ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_0), - 2); - } else if (AR_SREV_9285_12_OR_LATER(ah)) { - - - INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, - ARRAY_SIZE(ar9285Modes_9285_1_2), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2, - ARRAY_SIZE(ar9285Common_9285_1_2), 2); - - if (ah->config.pcie_clock_req) { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9285PciePhy_clkreq_off_L1_9285_1_2, - ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2); - } else { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9285PciePhy_clkreq_always_on_L1_9285_1_2, - ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2), - 2); - } - } else if (AR_SREV_9285_10_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285, - ARRAY_SIZE(ar9285Modes_9285), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285, - ARRAY_SIZE(ar9285Common_9285), 2); - - if (ah->config.pcie_clock_req) { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9285PciePhy_clkreq_off_L1_9285, - ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2); - } else { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9285PciePhy_clkreq_always_on_L1_9285, - ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2); - } - } else if (AR_SREV_9280_20_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2, - ARRAY_SIZE(ar9280Modes_9280_2), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2, - ARRAY_SIZE(ar9280Common_9280_2), 2); - - if (ah->config.pcie_clock_req) { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9280PciePhy_clkreq_off_L1_9280, - ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280),2); - } else { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9280PciePhy_clkreq_always_on_L1_9280, - ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2); - } - INIT_INI_ARRAY(&ah->iniModesAdditional, - ar9280Modes_fast_clock_9280_2, - ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3); - } else if (AR_SREV_9280_10_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280, - ARRAY_SIZE(ar9280Modes_9280), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280, - ARRAY_SIZE(ar9280Common_9280), 2); - } else if (AR_SREV_9160_10_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160, - ARRAY_SIZE(ar5416Modes_9160), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160, - ARRAY_SIZE(ar5416Common_9160), 2); - INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160, - ARRAY_SIZE(ar5416Bank0_9160), 2); - INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160, - ARRAY_SIZE(ar5416BB_RfGain_9160), 3); - INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160, - ARRAY_SIZE(ar5416Bank1_9160), 2); - INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160, - ARRAY_SIZE(ar5416Bank2_9160), 2); - INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160, - ARRAY_SIZE(ar5416Bank3_9160), 3); - INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160, - ARRAY_SIZE(ar5416Bank6_9160), 3); - INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160, - ARRAY_SIZE(ar5416Bank6TPC_9160), 3); - INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160, - ARRAY_SIZE(ar5416Bank7_9160), 2); - if (AR_SREV_9160_11(ah)) { - INIT_INI_ARRAY(&ah->iniAddac, - ar5416Addac_91601_1, - ARRAY_SIZE(ar5416Addac_91601_1), 2); - } else { - INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160, - ARRAY_SIZE(ar5416Addac_9160), 2); - } - } else if (AR_SREV_9100_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100, - ARRAY_SIZE(ar5416Modes_9100), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100, - ARRAY_SIZE(ar5416Common_9100), 2); - INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100, - ARRAY_SIZE(ar5416Bank0_9100), 2); - INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100, - ARRAY_SIZE(ar5416BB_RfGain_9100), 3); - INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100, - ARRAY_SIZE(ar5416Bank1_9100), 2); - INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100, - ARRAY_SIZE(ar5416Bank2_9100), 2); - INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100, - ARRAY_SIZE(ar5416Bank3_9100), 3); - INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100, - ARRAY_SIZE(ar5416Bank6_9100), 3); - INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100, - ARRAY_SIZE(ar5416Bank6TPC_9100), 3); - INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100, - ARRAY_SIZE(ar5416Bank7_9100), 2); - INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100, - ARRAY_SIZE(ar5416Addac_9100), 2); - } else { - INIT_INI_ARRAY(&ah->iniModes, ar5416Modes, - ARRAY_SIZE(ar5416Modes), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar5416Common, - ARRAY_SIZE(ar5416Common), 2); - INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0, - ARRAY_SIZE(ar5416Bank0), 2); - INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain, - ARRAY_SIZE(ar5416BB_RfGain), 3); - INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1, - ARRAY_SIZE(ar5416Bank1), 2); - INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2, - ARRAY_SIZE(ar5416Bank2), 2); - INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3, - ARRAY_SIZE(ar5416Bank3), 3); - INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6, - ARRAY_SIZE(ar5416Bank6), 3); - INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC, - ARRAY_SIZE(ar5416Bank6TPC), 3); - INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7, - ARRAY_SIZE(ar5416Bank7), 2); - INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac, - ARRAY_SIZE(ar5416Addac), 2); - } -} - -/* AR9003 2.0 - new INI format (pre, core, post arrays per subsystem) */ -static void ar9003_hw_init_mode_regs(struct ath_hw *ah) -{ - /* mac */ - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], - ar9300_2p0_mac_core, - ARRAY_SIZE(ar9300_2p0_mac_core), 2); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], - ar9300_2p0_mac_postamble, - ARRAY_SIZE(ar9300_2p0_mac_postamble), 5); - - /* bb */ - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], - ar9300_2p0_baseband_core, - ARRAY_SIZE(ar9300_2p0_baseband_core), 2); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], - ar9300_2p0_baseband_postamble, - ARRAY_SIZE(ar9300_2p0_baseband_postamble), 5); - - /* radio */ - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], - ar9300_2p0_radio_core, - ARRAY_SIZE(ar9300_2p0_radio_core), 2); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], - ar9300_2p0_radio_postamble, - ARRAY_SIZE(ar9300_2p0_radio_postamble), 5); - - /* soc */ - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], - ar9300_2p0_soc_preamble, - ARRAY_SIZE(ar9300_2p0_soc_preamble), 2); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], - ar9300_2p0_soc_postamble, - ARRAY_SIZE(ar9300_2p0_soc_postamble), 5); - - /* rx/tx gain */ - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9300Common_rx_gain_table_2p0, - ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), 2); - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_lowest_ob_db_tx_gain_table_2p0, - ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0), - 5); - - /* Load PCIE SERDES settings from INI */ - - /* Awake Setting */ - - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9300PciePhy_pll_on_clkreq_disable_L1_2p0, - ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p0), - 2); - - /* Sleep Setting */ - - INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, - ar9300PciePhy_clkreq_enable_L1_2p0, - ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p0), - 2); - - /* Fast clock modal settings */ - INIT_INI_ARRAY(&ah->iniModesAdditional, - ar9300Modes_fast_clock_2p0, - ARRAY_SIZE(ar9300Modes_fast_clock_2p0), - 3); -} - static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) { if (AR_SREV_9287_11_OR_LATER(ah)) @@ -2179,140 +1883,6 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) } EXPORT_SYMBOL(ath9k_hw_setpower); -/* - * Helper for ASPM support. - * - * Disable PLL when in L0s as well as receiver clock when in L1. - * This power saving option must be enabled through the SerDes. - * - * Programming the SerDes must go through the same 288 bit serial shift - * register as the other analog registers. Hence the 9 writes. - */ -static void ar9002_hw_configpcipowersave(struct ath_hw *ah, - int restore, - int power_off) -{ - u8 i; - u32 val; - - if (ah->is_pciexpress != true) - return; - - /* Do not touch SerDes registers */ - if (ah->config.pcie_powersave_enable == 2) - return; - - /* Nothing to do on restore for 11N */ - if (!restore) { - if (AR_SREV_9280_20_OR_LATER(ah)) { - /* - * AR9280 2.0 or later chips use SerDes values from the - * initvals.h initialized depending on chipset during - * __ath9k_hw_init() - */ - for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { - REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), - INI_RA(&ah->iniPcieSerdes, i, 1)); - } - } else if (AR_SREV_9280(ah) && - (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) { - REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00); - REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); - - /* RX shut off when elecidle is asserted */ - REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019); - REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820); - REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560); - - /* Shut off CLKREQ active in L1 */ - if (ah->config.pcie_clock_req) - REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc); - else - REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd); - - REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); - REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); - REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); - - /* Load the new settings */ - REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); - - } else { - REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); - REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); - - /* RX shut off when elecidle is asserted */ - REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); - REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); - REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); - - /* - * Ignore ah->ah_config.pcie_clock_req setting for - * pre-AR9280 11n - */ - REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); - - REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); - REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); - REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); - - /* Load the new settings */ - REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); - } - - udelay(1000); - - /* set bit 19 to allow forcing of pcie core into L1 state */ - REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); - - /* Several PCIe massages to ensure proper behaviour */ - if (ah->config.pcie_waen) { - val = ah->config.pcie_waen; - if (!power_off) - val &= (~AR_WA_D3_L1_DISABLE); - } else { - if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || - AR_SREV_9287(ah)) { - val = AR9285_WA_DEFAULT; - if (!power_off) - val &= (~AR_WA_D3_L1_DISABLE); - } else if (AR_SREV_9280(ah)) { - /* - * On AR9280 chips bit 22 of 0x4004 needs to be - * set otherwise card may disappear. - */ - val = AR9280_WA_DEFAULT; - if (!power_off) - val &= (~AR_WA_D3_L1_DISABLE); - } else - val = AR_WA_DEFAULT; - } - - REG_WRITE(ah, AR_WA, val); - } - - if (power_off) { - /* - * Set PCIe workaround bits - * bit 14 in WA register (disable L1) should only - * be set when device enters D3 and be cleared - * when device comes back to D0. - */ - if (ah->config.pcie_waen) { - if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) - REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); - } else { - if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) || - AR_SREV_9287(ah)) && - (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) || - (AR_SREV_9280(ah) && - (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) { - REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); - } - } - } -} - /**********************/ /* Interrupt Handling */ /**********************/ @@ -2594,37 +2164,6 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) } EXPORT_SYMBOL(ath9k_hw_set_interrupts); -/* - * Helper for ASPM support. - * - * Disable PLL when in L0s as well as receiver clock when in L1. - * This power saving option must be enabled through the SerDes. - * - * Programming the SerDes must go through the same 288 bit serial shift - * register as the other analog registers. Hence the 9 writes. - */ -static void ar9003_hw_configpcipowersave(struct ath_hw *ah, - int restore, - int power_off) -{ - if (ah->is_pciexpress != true) - return; - - /* Do not touch SerDes registers */ - if (ah->config.pcie_powersave_enable == 2) - return; - - /* Nothing to do on restore for 11N */ - if (!restore) { - /* set bit 19 to allow forcing of pcie core into L1 state */ - REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); - - /* Several PCIe massages to ensure proper behaviour */ - if (ah->config.pcie_waen) - REG_WRITE(ah, AR_WA, ah->config.pcie_waen); - } -} - /*******************/ /* Beacon Handling */ /*******************/ @@ -3635,38 +3174,3 @@ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len) hw_name[used] = '\0'; } EXPORT_SYMBOL(ath9k_hw_name); - -/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */ -static void ar9002_hw_attach_ops(struct ath_hw *ah) -{ - struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); - struct ath_hw_ops *ops = ath9k_hw_ops(ah); - - priv_ops->init_mode_regs = ar9002_hw_init_mode_regs; - priv_ops->macversion_supported = ar9002_hw_macversion_supported; - - ops->config_pci_powersave = ar9002_hw_configpcipowersave; - - ar5008_hw_attach_phy_ops(ah); - if (AR_SREV_9280_10_OR_LATER(ah)) - ar9002_hw_attach_phy_ops(ah); - - ar9002_hw_attach_calib_ops(ah); - ar9002_hw_attach_mac_ops(ah); -} - -/* Sets up the AR9003 hardware familiy callbacks */ -static void ar9003_hw_attach_ops(struct ath_hw *ah) -{ - struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); - struct ath_hw_ops *ops = ath9k_hw_ops(ah); - - priv_ops->init_mode_regs = ar9003_hw_init_mode_regs; - priv_ops->macversion_supported = ar9003_hw_macversion_supported; - - ops->config_pci_powersave = ar9003_hw_configpcipowersave; - - ar9003_hw_attach_phy_ops(ah); - ar9003_hw_attach_calib_ops(ah); - ar9003_hw_attach_mac_ops(ah); -} diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7ef93c8df923..9325095da536 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2010 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -852,6 +852,9 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah); void ar9002_hw_attach_calib_ops(struct ath_hw *ah); void ar9003_hw_attach_calib_ops(struct ath_hw *ah); +void ar9002_hw_attach_ops(struct ath_hw *ah); +void ar9003_hw_attach_ops(struct ath_hw *ah); + #define ATH_PCIE_CAP_LINK_CTRL 0x70 #define ATH_PCIE_CAP_LINK_L0S 1 #define ATH_PCIE_CAP_LINK_L1 2 -- cgit v1.2.3 From d8f492b7d9a4c1cfdac69ba18a81acbd86d1dc6e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:04 -0400 Subject: ath9k_hw: move the cck channel 14 INI to the AR9002 hw code This is specific to the AR9002 family only. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_hw.c | 15 +++++++++++++++ drivers/net/wireless/ath/ath9k/hw.c | 11 ++--------- drivers/net/wireless/ath/ath9k/hw.h | 2 ++ 3 files changed, 19 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index aa52fd7b630c..ff81efa8bc00 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -229,6 +229,21 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) } } +/* Support for Japan ch.14 (2484) spread */ +void ar9002_hw_cck_chan14_spread(struct ath_hw *ah) +{ + if (AR_SREV_9287_11_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniCckfirNormal, + ar9287Common_normal_cck_fir_coeff_92871_1, + ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_92871_1), + 2); + INIT_INI_ARRAY(&ah->iniCckfirJapan2484, + ar9287Common_japan_2484_cck_fir_coeff_92871_1, + ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_92871_1), + 2); + } +} + /* * Helper for ASPM support. * diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 3157ddeab31c..40cacbfee30f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -712,15 +712,8 @@ static int __ath9k_hw_init(struct ath_hw *ah) else ath9k_hw_disablepcie(ah); - /* Support for Japan ch.14 (2484) spread */ - if (AR_SREV_9287_11_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniCckfirNormal, - ar9287Common_normal_cck_fir_coeff_92871_1, - ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_92871_1), 2); - INIT_INI_ARRAY(&ah->iniCckfirJapan2484, - ar9287Common_japan_2484_cck_fir_coeff_92871_1, - ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_92871_1), 2); - } + if (!AR_SREV_9300_20_OR_LATER(ah)) + ar9002_hw_cck_chan14_spread(ah); r = ath9k_hw_post_init(ah); if (r) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 9325095da536..56c573556454 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -838,6 +838,8 @@ void ath9k_hw_htc_resetinit(struct ath_hw *ah); void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, u32 *coef_mantissa, u32 *coef_exponent); +void ar9002_hw_cck_chan14_spread(struct ath_hw *ah); + /* * Code specifric to AR9003, we stuff these here to avoid callbacks * for older families -- cgit v1.2.3 From 991312d88cb8844e3e1a1e57a72823802da36fcd Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:05 -0400 Subject: ath9k_hw: move TX/RX gain INI stuff to its own hardware family code The AR9003 TX/RX gain is currently initialized with the other components, so for now AR9003 does not implment this callback, after hardware bring up we can test moving the TX/RX gain there as well and if it works well move them to its own callback as well. Since all INI stuff is now moved out hw.c no longer needs to include and touch any original INI headers/structs. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_hw.c | 106 +++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_hw.c | 4 ++ drivers/net/wireless/ath/ath9k/hw.c | 112 +++-------------------------- drivers/net/wireless/ath/ath9k/hw.h | 2 + 4 files changed, 120 insertions(+), 104 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index ff81efa8bc00..eeaea2631c18 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -244,6 +244,111 @@ void ar9002_hw_cck_chan14_spread(struct ath_hw *ah) } } +static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah) +{ + u32 rxgain_type; + + if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= + AR5416_EEP_MINOR_VER_17) { + rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE); + + if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9280Modes_backoff_13db_rxgain_9280_2, + ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6); + else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9280Modes_backoff_23db_rxgain_9280_2, + ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6); + else + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9280Modes_original_rxgain_9280_2, + ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); + } else { + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9280Modes_original_rxgain_9280_2, + ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); + } +} + +static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah) +{ + u32 txgain_type; + + if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= + AR5416_EEP_MINOR_VER_19) { + txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); + + if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9280Modes_high_power_tx_gain_9280_2, + ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6); + else + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9280Modes_original_tx_gain_9280_2, + ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); + } else { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9280Modes_original_tx_gain_9280_2, + ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); + } +} + +static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah) +{ + if (AR_SREV_9287_11_OR_LATER(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9287Modes_rx_gain_9287_1_1, + ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6); + else if (AR_SREV_9287_10(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9287Modes_rx_gain_9287_1_0, + ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_0), 6); + else if (AR_SREV_9280_20(ah)) + ar9280_20_hw_init_rxgain_ini(ah); + + if (AR_SREV_9287_11_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9287Modes_tx_gain_9287_1_1, + ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); + } else if (AR_SREV_9287_10(ah)) { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9287Modes_tx_gain_9287_1_0, + ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_0), 6); + } else if (AR_SREV_9280_20(ah)) { + ar9280_20_hw_init_txgain_ini(ah); + } else if (AR_SREV_9285_12_OR_LATER(ah)) { + u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); + + /* txgain table */ + if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { + if (AR_SREV_9285E_20(ah)) { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9285Modes_XE2_0_high_power, + ARRAY_SIZE( + ar9285Modes_XE2_0_high_power), 6); + } else { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9285Modes_high_power_tx_gain_9285_1_2, + ARRAY_SIZE( + ar9285Modes_high_power_tx_gain_9285_1_2), 6); + } + } else { + if (AR_SREV_9285E_20(ah)) { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9285Modes_XE2_0_normal_power, + ARRAY_SIZE( + ar9285Modes_XE2_0_normal_power), 6); + } else { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9285Modes_original_tx_gain_9285_1_2, + ARRAY_SIZE( + ar9285Modes_original_tx_gain_9285_1_2), 6); + } + } + } +} + /* * Helper for ASPM support. * @@ -385,6 +490,7 @@ void ar9002_hw_attach_ops(struct ath_hw *ah) struct ath_hw_ops *ops = ath9k_hw_ops(ah); priv_ops->init_mode_regs = ar9002_hw_init_mode_regs; + priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs; priv_ops->macversion_supported = ar9002_hw_macversion_supported; ops->config_pci_powersave = ar9002_hw_configpcipowersave; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 6111bdb7779b..1984b4f78bc7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -31,6 +31,10 @@ static bool ar9003_hw_macversion_supported(u32 macversion) } /* AR9003 2.0 - new INI format (pre, core, post arrays per subsystem) */ +/* + * XXX: move TX/RX gain INI to its own init_mode_gain_regs after + * ensuring it does not affect hardware bring up + */ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) { /* mac */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 40cacbfee30f..127546c42223 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -20,7 +20,6 @@ #include "hw.h" #include "hw-ops.h" #include "rc.h" -#include "ar9002_initvals.h" #define ATH9K_CLOCK_RATE_CCK 22 #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 @@ -70,6 +69,14 @@ static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah, return ath9k_hw_private_ops(ah)->compute_pll_control(ah, chan); } +static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) +{ + if (!ath9k_hw_private_ops(ah)->init_mode_gain_regs) + return; + + ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah); +} + /********************/ /* Helper Functions */ /********************/ @@ -479,54 +486,6 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah) return 0; } -static void ath9k_hw_init_rxgain_ini(struct ath_hw *ah) -{ - u32 rxgain_type; - - if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_17) { - rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE); - - if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9280Modes_backoff_13db_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6); - else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9280Modes_backoff_23db_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6); - else - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9280Modes_original_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); - } else { - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9280Modes_original_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); - } -} - -static void ath9k_hw_init_txgain_ini(struct ath_hw *ah) -{ - u32 txgain_type; - - if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_19) { - txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); - - if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9280Modes_high_power_tx_gain_9280_2, - ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6); - else - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9280Modes_original_tx_gain_9280_2, - ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); - } else { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9280Modes_original_tx_gain_9280_2, - ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); - } -} - static int ath9k_hw_post_init(struct ath_hw *ah) { int ecode; @@ -565,61 +524,6 @@ static int ath9k_hw_post_init(struct ath_hw *ah) return 0; } -static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) -{ - if (AR_SREV_9287_11_OR_LATER(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9287Modes_rx_gain_9287_1_1, - ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6); - else if (AR_SREV_9287_10(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9287Modes_rx_gain_9287_1_0, - ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_0), 6); - else if (AR_SREV_9280_20(ah)) - ath9k_hw_init_rxgain_ini(ah); - - if (AR_SREV_9287_11_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9287Modes_tx_gain_9287_1_1, - ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); - } else if (AR_SREV_9287_10(ah)) { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9287Modes_tx_gain_9287_1_0, - ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_0), 6); - } else if (AR_SREV_9280_20(ah)) { - ath9k_hw_init_txgain_ini(ah); - } else if (AR_SREV_9285_12_OR_LATER(ah)) { - u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); - - /* txgain table */ - if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { - if (AR_SREV_9285E_20(ah)) { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9285Modes_XE2_0_high_power, - ARRAY_SIZE( - ar9285Modes_XE2_0_high_power), 6); - } else { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9285Modes_high_power_tx_gain_9285_1_2, - ARRAY_SIZE( - ar9285Modes_high_power_tx_gain_9285_1_2), 6); - } - } else { - if (AR_SREV_9285E_20(ah)) { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9285Modes_XE2_0_normal_power, - ARRAY_SIZE( - ar9285Modes_XE2_0_normal_power), 6); - } else { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9285Modes_original_tx_gain_9285_1_2, - ARRAY_SIZE( - ar9285Modes_original_tx_gain_9285_1_2), 6); - } - } - } -} - static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah) { struct base_eep_header *pBase = &(ah->eeprom.def.baseEepHeader); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 56c573556454..b27e76b82dcf 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -473,6 +473,7 @@ struct ath_gen_timer_table { * @init_cal: starts actual calibration * * @init_mode_regs: Initializes mode registers + * @init_mode_gain_regs: Initialize TX/RX gain registers * @macversion_supported: If this specific mac revision is supported * * @rf_set_freq: change frequency @@ -491,6 +492,7 @@ struct ath_hw_private_ops { bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan); void (*init_mode_regs)(struct ath_hw *ah); + void (*init_mode_gain_regs)(struct ath_hw *ah); bool (*macversion_supported)(u32 macversion); void (*setup_calibration)(struct ath_hw *ah, struct ath9k_cal_list *currCal); -- cgit v1.2.3 From 55e82df4be45305bfb5e7ecb877a349ed4da8ed2 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:06 -0400 Subject: ath9k_hw: Abstract the routine which returns interrupt status Also move interrupt related code to mac.c Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 6 + drivers/net/wireless/ath/ath9k/hw-ops.h | 5 + drivers/net/wireless/ath/ath9k/hw.c | 281 --------------------------- drivers/net/wireless/ath/ath9k/hw.h | 7 +- drivers/net/wireless/ath/ath9k/mac.c | 290 ++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/mac.h | 5 + drivers/net/wireless/ath/ath9k/reg.h | 2 + 7 files changed, 310 insertions(+), 286 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index b229597e54cd..15f1b0f0d070 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -30,6 +30,11 @@ static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link) *ds_link = &((struct ar9003_txc *) ds)->link; } +static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) +{ + return true; +} + void ar9003_hw_attach_mac_ops(struct ath_hw *hw) { struct ath_hw_ops *ops = ath9k_hw_ops(hw); @@ -37,6 +42,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) ops->rx_enable = ar9003_hw_rx_enable; ops->set_desc_link = ar9003_hw_set_desc_link; ops->get_desc_link = ar9003_hw_get_desc_link; + ops->get_isr = ar9003_hw_get_isr; } void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 3848c0d3f99e..b777fd1894f0 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -52,6 +52,11 @@ static inline bool ath9k_hw_calibrate(struct ath_hw *ah, return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal); } +static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) +{ + return ath9k_hw_ops(ah)->get_isr(ah, masked); +} + /* Private hardware call ops */ /* PHY ops */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 127546c42223..ac57a975d014 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1780,287 +1780,6 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) } EXPORT_SYMBOL(ath9k_hw_setpower); -/**********************/ -/* Interrupt Handling */ -/**********************/ - -bool ath9k_hw_intrpend(struct ath_hw *ah) -{ - u32 host_isr; - - if (AR_SREV_9100(ah)) - return true; - - host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE); - if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS)) - return true; - - host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE); - if ((host_isr & AR_INTR_SYNC_DEFAULT) - && (host_isr != AR_INTR_SPURIOUS)) - return true; - - return false; -} -EXPORT_SYMBOL(ath9k_hw_intrpend); - -bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) -{ - u32 isr = 0; - u32 mask2 = 0; - struct ath9k_hw_capabilities *pCap = &ah->caps; - u32 sync_cause = 0; - bool fatal_int = false; - struct ath_common *common = ath9k_hw_common(ah); - - if (!AR_SREV_9100(ah)) { - if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { - if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) - == AR_RTC_STATUS_ON) { - isr = REG_READ(ah, AR_ISR); - } - } - - sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & - AR_INTR_SYNC_DEFAULT; - - *masked = 0; - - if (!isr && !sync_cause) - return false; - } else { - *masked = 0; - isr = REG_READ(ah, AR_ISR); - } - - if (isr) { - if (isr & AR_ISR_BCNMISC) { - u32 isr2; - isr2 = REG_READ(ah, AR_ISR_S2); - if (isr2 & AR_ISR_S2_TIM) - mask2 |= ATH9K_INT_TIM; - if (isr2 & AR_ISR_S2_DTIM) - mask2 |= ATH9K_INT_DTIM; - if (isr2 & AR_ISR_S2_DTIMSYNC) - mask2 |= ATH9K_INT_DTIMSYNC; - if (isr2 & (AR_ISR_S2_CABEND)) - mask2 |= ATH9K_INT_CABEND; - if (isr2 & AR_ISR_S2_GTT) - mask2 |= ATH9K_INT_GTT; - if (isr2 & AR_ISR_S2_CST) - mask2 |= ATH9K_INT_CST; - if (isr2 & AR_ISR_S2_TSFOOR) - mask2 |= ATH9K_INT_TSFOOR; - } - - isr = REG_READ(ah, AR_ISR_RAC); - if (isr == 0xffffffff) { - *masked = 0; - return false; - } - - *masked = isr & ATH9K_INT_COMMON; - - if (ah->config.rx_intr_mitigation) { - if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) - *masked |= ATH9K_INT_RX; - } - - if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) - *masked |= ATH9K_INT_RX; - if (isr & - (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | - AR_ISR_TXEOL)) { - u32 s0_s, s1_s; - - *masked |= ATH9K_INT_TX; - - s0_s = REG_READ(ah, AR_ISR_S0_S); - ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); - ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); - - s1_s = REG_READ(ah, AR_ISR_S1_S); - ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); - ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); - } - - if (isr & AR_ISR_RXORN) { - ath_print(common, ATH_DBG_INTERRUPT, - "receive FIFO overrun interrupt\n"); - } - - if (!AR_SREV_9100(ah)) { - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - u32 isr5 = REG_READ(ah, AR_ISR_S5_S); - if (isr5 & AR_ISR_S5_TIM_TIMER) - *masked |= ATH9K_INT_TIM_TIMER; - } - } - - *masked |= mask2; - } - - if (AR_SREV_9100(ah)) - return true; - - if (isr & AR_ISR_GENTMR) { - u32 s5_s; - - s5_s = REG_READ(ah, AR_ISR_S5_S); - if (isr & AR_ISR_GENTMR) { - ah->intr_gen_timer_trigger = - MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); - - ah->intr_gen_timer_thresh = - MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); - - if (ah->intr_gen_timer_trigger) - *masked |= ATH9K_INT_GENTIMER; - - } - } - - if (sync_cause) { - fatal_int = - (sync_cause & - (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) - ? true : false; - - if (fatal_int) { - if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { - ath_print(common, ATH_DBG_ANY, - "received PCI FATAL interrupt\n"); - } - if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { - ath_print(common, ATH_DBG_ANY, - "received PCI PERR interrupt\n"); - } - *masked |= ATH9K_INT_FATAL; - } - if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { - ath_print(common, ATH_DBG_INTERRUPT, - "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); - REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); - REG_WRITE(ah, AR_RC, 0); - *masked |= ATH9K_INT_FATAL; - } - if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { - ath_print(common, ATH_DBG_INTERRUPT, - "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); - } - - REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); - (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); - } - - return true; -} -EXPORT_SYMBOL(ath9k_hw_getisr); - -enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) -{ - enum ath9k_int omask = ah->imask; - u32 mask, mask2; - struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath_common *common = ath9k_hw_common(ah); - - ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); - - if (omask & ATH9K_INT_GLOBAL) { - ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n"); - REG_WRITE(ah, AR_IER, AR_IER_DISABLE); - (void) REG_READ(ah, AR_IER); - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); - (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); - - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); - (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); - } - } - - mask = ints & ATH9K_INT_COMMON; - mask2 = 0; - - if (ints & ATH9K_INT_TX) { - if (ah->txok_interrupt_mask) - mask |= AR_IMR_TXOK; - if (ah->txdesc_interrupt_mask) - mask |= AR_IMR_TXDESC; - if (ah->txerr_interrupt_mask) - mask |= AR_IMR_TXERR; - if (ah->txeol_interrupt_mask) - mask |= AR_IMR_TXEOL; - } - if (ints & ATH9K_INT_RX) { - mask |= AR_IMR_RXERR; - if (ah->config.rx_intr_mitigation) - mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; - else - mask |= AR_IMR_RXOK | AR_IMR_RXDESC; - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) - mask |= AR_IMR_GENTMR; - } - - if (ints & (ATH9K_INT_BMISC)) { - mask |= AR_IMR_BCNMISC; - if (ints & ATH9K_INT_TIM) - mask2 |= AR_IMR_S2_TIM; - if (ints & ATH9K_INT_DTIM) - mask2 |= AR_IMR_S2_DTIM; - if (ints & ATH9K_INT_DTIMSYNC) - mask2 |= AR_IMR_S2_DTIMSYNC; - if (ints & ATH9K_INT_CABEND) - mask2 |= AR_IMR_S2_CABEND; - if (ints & ATH9K_INT_TSFOOR) - mask2 |= AR_IMR_S2_TSFOOR; - } - - if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) { - mask |= AR_IMR_BCNMISC; - if (ints & ATH9K_INT_GTT) - mask2 |= AR_IMR_S2_GTT; - if (ints & ATH9K_INT_CST) - mask2 |= AR_IMR_S2_CST; - } - - ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); - REG_WRITE(ah, AR_IMR, mask); - ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | - AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | - AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST); - ah->imrs2_reg |= mask2; - REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); - - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - if (ints & ATH9K_INT_TIM_TIMER) - REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); - else - REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); - } - - if (ints & ATH9K_INT_GLOBAL) { - ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n"); - REG_WRITE(ah, AR_IER, AR_IER_ENABLE); - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, - AR_INTR_MAC_IRQ); - REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); - - - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, - AR_INTR_SYNC_DEFAULT); - REG_WRITE(ah, AR_INTR_SYNC_MASK, - AR_INTR_SYNC_DEFAULT); - } - ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", - REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); - } - - return omask; -} -EXPORT_SYMBOL(ath9k_hw_set_interrupts); - /*******************/ /* Beacon Handling */ /*******************/ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index b27e76b82dcf..7a32733108a2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -227,6 +227,7 @@ struct ath9k_ops_config { u32 enable_ani; int serialize_regmode; bool rx_intr_mitigation; + bool tx_intr_mitigation; #define SPUR_DISABLE 0 #define SPUR_ENABLE_IOCTL 1 #define SPUR_ENABLE_EEPROM 2 @@ -549,6 +550,7 @@ struct ath_hw_ops { struct ath9k_channel *chan, u8 rxchainmask, bool longcal); + bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked); }; struct ath_hw { @@ -810,11 +812,6 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); -/* Interrupt Handling */ -bool ath9k_hw_intrpend(struct ath_hw *ah); -bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked); -enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints); - /* Generic hw timer primitives */ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, void (*trigger)(void *), diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index a8dab23622f1..4a36ec53f732 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -31,6 +31,158 @@ static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link) *ds_link = &((struct ath_desc *)ds)->ds_link; } +static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) +{ + u32 isr = 0; + u32 mask2 = 0; + struct ath9k_hw_capabilities *pCap = &ah->caps; + u32 sync_cause = 0; + bool fatal_int = false; + struct ath_common *common = ath9k_hw_common(ah); + + if (!AR_SREV_9100(ah)) { + if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { + if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) + == AR_RTC_STATUS_ON) { + isr = REG_READ(ah, AR_ISR); + } + } + + sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & + AR_INTR_SYNC_DEFAULT; + + *masked = 0; + + if (!isr && !sync_cause) + return false; + } else { + *masked = 0; + isr = REG_READ(ah, AR_ISR); + } + + if (isr) { + if (isr & AR_ISR_BCNMISC) { + u32 isr2; + isr2 = REG_READ(ah, AR_ISR_S2); + if (isr2 & AR_ISR_S2_TIM) + mask2 |= ATH9K_INT_TIM; + if (isr2 & AR_ISR_S2_DTIM) + mask2 |= ATH9K_INT_DTIM; + if (isr2 & AR_ISR_S2_DTIMSYNC) + mask2 |= ATH9K_INT_DTIMSYNC; + if (isr2 & (AR_ISR_S2_CABEND)) + mask2 |= ATH9K_INT_CABEND; + if (isr2 & AR_ISR_S2_GTT) + mask2 |= ATH9K_INT_GTT; + if (isr2 & AR_ISR_S2_CST) + mask2 |= ATH9K_INT_CST; + if (isr2 & AR_ISR_S2_TSFOOR) + mask2 |= ATH9K_INT_TSFOOR; + } + + isr = REG_READ(ah, AR_ISR_RAC); + if (isr == 0xffffffff) { + *masked = 0; + return false; + } + + *masked = isr & ATH9K_INT_COMMON; + + if (ah->config.rx_intr_mitigation) { + if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) + *masked |= ATH9K_INT_RX; + } + + if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) + *masked |= ATH9K_INT_RX; + if (isr & + (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | + AR_ISR_TXEOL)) { + u32 s0_s, s1_s; + + *masked |= ATH9K_INT_TX; + + s0_s = REG_READ(ah, AR_ISR_S0_S); + ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); + ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); + + s1_s = REG_READ(ah, AR_ISR_S1_S); + ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); + ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); + } + + if (isr & AR_ISR_RXORN) { + ath_print(common, ATH_DBG_INTERRUPT, + "receive FIFO overrun interrupt\n"); + } + + if (!AR_SREV_9100(ah)) { + if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { + u32 isr5 = REG_READ(ah, AR_ISR_S5_S); + if (isr5 & AR_ISR_S5_TIM_TIMER) + *masked |= ATH9K_INT_TIM_TIMER; + } + } + + *masked |= mask2; + } + + if (AR_SREV_9100(ah)) + return true; + + if (isr & AR_ISR_GENTMR) { + u32 s5_s; + + s5_s = REG_READ(ah, AR_ISR_S5_S); + if (isr & AR_ISR_GENTMR) { + ah->intr_gen_timer_trigger = + MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); + + ah->intr_gen_timer_thresh = + MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); + + if (ah->intr_gen_timer_trigger) + *masked |= ATH9K_INT_GENTIMER; + + } + } + + if (sync_cause) { + fatal_int = + (sync_cause & + (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) + ? true : false; + + if (fatal_int) { + if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { + ath_print(common, ATH_DBG_ANY, + "received PCI FATAL interrupt\n"); + } + if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { + ath_print(common, ATH_DBG_ANY, + "received PCI PERR interrupt\n"); + } + *masked |= ATH9K_INT_FATAL; + } + if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { + ath_print(common, ATH_DBG_INTERRUPT, + "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); + REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); + REG_WRITE(ah, AR_RC, 0); + *masked |= ATH9K_INT_FATAL; + } + if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { + ath_print(common, ATH_DBG_INTERRUPT, + "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); + } + + REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); + (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); + } + + return true; +} + void ar9002_hw_attach_mac_ops(struct ath_hw *ah) { struct ath_hw_ops *ops = ath9k_hw_ops(ah); @@ -38,6 +190,7 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah) ops->rx_enable = ar9002_hw_rx_enable; ops->set_desc_link = ar9002_hw_set_desc_link; ops->get_desc_link = ar9002_hw_get_desc_link; + ops->get_isr = ar9002_hw_get_isr; } static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, @@ -1089,3 +1242,140 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah) return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); } EXPORT_SYMBOL(ath9k_hw_beaconq_setup); + +bool ath9k_hw_intrpend(struct ath_hw *ah) +{ + u32 host_isr; + + if (AR_SREV_9100(ah)) + return true; + + host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE); + if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS)) + return true; + + host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE); + if ((host_isr & AR_INTR_SYNC_DEFAULT) + && (host_isr != AR_INTR_SPURIOUS)) + return true; + + return false; +} +EXPORT_SYMBOL(ath9k_hw_intrpend); + +enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, + enum ath9k_int ints) +{ + enum ath9k_int omask = ah->imask; + u32 mask, mask2; + struct ath9k_hw_capabilities *pCap = &ah->caps; + struct ath_common *common = ath9k_hw_common(ah); + + ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); + + if (omask & ATH9K_INT_GLOBAL) { + ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n"); + REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + (void) REG_READ(ah, AR_IER); + if (!AR_SREV_9100(ah)) { + REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); + (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); + + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); + (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); + } + } + + /* TODO: global int Ref count */ + mask = ints & ATH9K_INT_COMMON; + mask2 = 0; + + if (ints & ATH9K_INT_TX) { + if (ah->config.tx_intr_mitigation) + mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM; + if (ah->txok_interrupt_mask) + mask |= AR_IMR_TXOK; + if (ah->txdesc_interrupt_mask) + mask |= AR_IMR_TXDESC; + if (ah->txerr_interrupt_mask) + mask |= AR_IMR_TXERR; + if (ah->txeol_interrupt_mask) + mask |= AR_IMR_TXEOL; + } + if (ints & ATH9K_INT_RX) { + if (AR_SREV_9300_20_OR_LATER(ah)) { + mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP; + if (ah->config.rx_intr_mitigation) { + mask &= ~AR_IMR_RXOK_LP; + mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; + } else { + mask |= AR_IMR_RXOK_LP; + } + } else { + if (ah->config.rx_intr_mitigation) + mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; + else + mask |= AR_IMR_RXOK | AR_IMR_RXDESC; + } + if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) + mask |= AR_IMR_GENTMR; + } + + if (ints & (ATH9K_INT_BMISC)) { + mask |= AR_IMR_BCNMISC; + if (ints & ATH9K_INT_TIM) + mask2 |= AR_IMR_S2_TIM; + if (ints & ATH9K_INT_DTIM) + mask2 |= AR_IMR_S2_DTIM; + if (ints & ATH9K_INT_DTIMSYNC) + mask2 |= AR_IMR_S2_DTIMSYNC; + if (ints & ATH9K_INT_CABEND) + mask2 |= AR_IMR_S2_CABEND; + if (ints & ATH9K_INT_TSFOOR) + mask2 |= AR_IMR_S2_TSFOOR; + } + + if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) { + mask |= AR_IMR_BCNMISC; + if (ints & ATH9K_INT_GTT) + mask2 |= AR_IMR_S2_GTT; + if (ints & ATH9K_INT_CST) + mask2 |= AR_IMR_S2_CST; + } + + ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); + REG_WRITE(ah, AR_IMR, mask); + ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | + AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | + AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST); + ah->imrs2_reg |= mask2; + REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); + + if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { + if (ints & ATH9K_INT_TIM_TIMER) + REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); + else + REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); + } + + if (ints & ATH9K_INT_GLOBAL) { + ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n"); + REG_WRITE(ah, AR_IER, AR_IER_ENABLE); + if (!AR_SREV_9100(ah)) { + REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, + AR_INTR_MAC_IRQ); + REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); + + + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, + AR_INTR_SYNC_DEFAULT); + REG_WRITE(ah, AR_INTR_SYNC_MASK, + AR_INTR_SYNC_DEFAULT); + } + ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", + REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); + } + + return omask; +} +EXPORT_SYMBOL(ath9k_hw_set_interrupts); diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 99f81ebb35bf..7c0d75490211 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -736,6 +736,11 @@ void ath9k_hw_stoppcurecv(struct ath_hw *ah); bool ath9k_hw_stopdmarecv(struct ath_hw *ah); int ath9k_hw_beaconq_setup(struct ath_hw *ah); +/* Interrupt Handling */ +bool ath9k_hw_intrpend(struct ath_hw *ah); +enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, + enum ath9k_int ints); + void ar9002_hw_attach_mac_ops(struct ath_hw *ah); #endif /* MAC_H */ diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 96b2cfee8e33..7f856334a28a 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -253,6 +253,8 @@ #define AR_IMR 0x00a0 #define AR_IMR_RXOK 0x00000001 #define AR_IMR_RXDESC 0x00000002 +#define AR_IMR_RXOK_HP 0x00000001 +#define AR_IMR_RXOK_LP 0x00000002 #define AR_IMR_RXERR 0x00000004 #define AR_IMR_RXNOPKT 0x00000008 #define AR_IMR_RXEOL 0x00000010 -- cgit v1.2.3 From 668602404d7398d841681c5e23fd8a9a45e4bb30 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:07 -0400 Subject: ath9k_hw: Initialize interrupt mask for AR9003 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 29 ++++++++++++++++++++++++----- drivers/net/wireless/ath/ath9k/reg.h | 5 +++++ 2 files changed, 29 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ac57a975d014..d074cc0a2319 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -736,12 +736,24 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, AR_IMR_RXORN | AR_IMR_BCNMISC; - if (ah->config.rx_intr_mitigation) - imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; - else - imr_reg |= AR_IMR_RXOK; + if (AR_SREV_9300_20_OR_LATER(ah)) { + imr_reg |= AR_IMR_RXOK_HP; + if (ah->config.rx_intr_mitigation) + imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; + else + imr_reg |= AR_IMR_RXOK_LP; - imr_reg |= AR_IMR_TXOK; + } else { + if (ah->config.rx_intr_mitigation) + imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; + else + imr_reg |= AR_IMR_RXOK; + } + + if (ah->config.tx_intr_mitigation) + imr_reg |= AR_IMR_TXINTM | AR_IMR_TXMINTR; + else + imr_reg |= AR_IMR_TXOK; if (opmode == NL80211_IFTYPE_AP) imr_reg |= AR_IMR_MIB; @@ -755,6 +767,13 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT); REG_WRITE(ah, AR_INTR_SYNC_MASK, 0); } + + if (AR_SREV_9300_20_OR_LATER(ah)) { + REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0); + REG_WRITE(ah, AR_INTR_PRIO_ASYNC_MASK, 0); + REG_WRITE(ah, AR_INTR_PRIO_SYNC_ENABLE, 0); + REG_WRITE(ah, AR_INTR_PRIO_SYNC_MASK, 0); + } } static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us) diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 7f856334a28a..7758d99a84d4 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1042,6 +1042,11 @@ enum { #define AR_PCIE_MSI (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094) #define AR_PCIE_MSI_ENABLE 0x00000001 +#define AR_INTR_PRIO_SYNC_ENABLE 0x40c4 +#define AR_INTR_PRIO_ASYNC_MASK 0x40c8 +#define AR_INTR_PRIO_SYNC_MASK 0x40cc +#define AR_INTR_PRIO_ASYNC_ENABLE 0x40d4 + #define AR_RTC_9300_PLL_DIV 0x000003ff #define AR_RTC_9300_PLL_DIV_S 0 #define AR_RTC_9300_PLL_REFDIV 0x00003C00 -- cgit v1.2.3 From 400b738678bf6f0b65a76a4ec2925473ba3e06ff Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:08 -0400 Subject: ath9k_hw: abstract the AR_PHY_AGC_CONTROL register access This is so we can share routines which access this register on calib.c Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_phy.h | 7 ------- drivers/net/wireless/ath/ath9k/ar9003_phy.h | 13 ------------- drivers/net/wireless/ath/ath9k/reg.h | 15 +++++++++++++++ 3 files changed, 15 insertions(+), 20 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index 4fe204ed3a7c..afe48086250d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h @@ -120,13 +120,6 @@ #define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000 #define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15 -#define AR_PHY_AGC_CONTROL 0x9860 -#define AR_PHY_AGC_CONTROL_CAL 0x00000001 -#define AR_PHY_AGC_CONTROL_NF 0x00000002 -#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 -#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 -#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 - #define AR_PHY_CCA 0x9864 #define AR_PHY_MINCCA_PWR 0x0FF80000 #define AR_PHY_MINCCA_PWR_S 19 diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 70e647b13e0a..4e1177dc24ac 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -359,7 +359,6 @@ #define AR_PHY_SWITCH_COM_2 (AR_SM_BASE + 0x8c) #define AR_PHY_RX_CHAINMASK (AR_SM_BASE + 0xa0) #define AR_PHY_CAL_CHAINMASK (AR_SM_BASE + 0xc0) -#define AR_PHY_AGC_CONTROL (AR_SM_BASE + 0xc4) #define AR_PHY_CALMODE (AR_SM_BASE + 0xc8) #define AR_PHY_FCAL_1 (AR_SM_BASE + 0xcc) #define AR_PHY_FCAL_2_0 (AR_SM_BASE + 0xd0) @@ -509,18 +508,6 @@ #define AR_PHY_GC_ENABLE_DAC_FIFO 0x00000800 /* fifo between bb and dac */ #define AR_PHY_RX_DELAY_DELAY 0x00003FFF /* delay from wakeup to rx ena */ -#define AR_PHY_AGC_CONTROL_CAL 0x00000001 /* do internal calibration */ -#define AR_PHY_AGC_CONTROL_NF 0x00000002 /* do noise-floor calibration */ -#define AR_PHY_AGC_CONTROL_OFFSET_CAL 0x00000800 /* allow offset calibration */ -#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 /* enable noise floor calibration to happen */ -#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 /* allow tx filter calibration */ -#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 /* don't update noise floor automatically */ -#define AR_PHY_AGC_CONTROL_EXT_NF_PWR_MEAS 0x00040000 /* extend noise floor power measurement */ -#define AR_PHY_AGC_CONTROL_CLC_SUCCESS 0x00080000 /* carrier leak calibration done */ - -#define AR_PHY_AGC_CONTROL_YCOK_MAX 0x000003c0 -#define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6 - #define AR_PHY_CALMODE_IQ 0x00000000 #define AR_PHY_CALMODE_ADC_GAIN 0x00000001 #define AR_PHY_CALMODE_ADC_DC_PER 0x00000002 diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 7758d99a84d4..aacc29a5ad71 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1776,4 +1776,19 @@ enum { * pcu_txsm. */ +#define AR9300_SM_BASE 0xa200 +#define AR9002_PHY_AGC_CONTROL 0x9860 +#define AR9003_PHY_AGC_CONTROL AR9300_SM_BASE + 0xc4 +#define AR_PHY_AGC_CONTROL (AR_SREV_9300_20_OR_LATER(ah) ? AR9003_PHY_AGC_CONTROL : AR9002_PHY_AGC_CONTROL) +#define AR_PHY_AGC_CONTROL_CAL 0x00000001 /* do internal calibration */ +#define AR_PHY_AGC_CONTROL_NF 0x00000002 /* do noise-floor calibration */ +#define AR_PHY_AGC_CONTROL_OFFSET_CAL 0x00000800 /* allow offset calibration */ +#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 /* enable noise floor calibration to happen */ +#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 /* allow tx filter calibration */ +#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 /* don't update noise floor automatically */ +#define AR_PHY_AGC_CONTROL_EXT_NF_PWR_MEAS 0x00040000 /* extend noise floor power measurement */ +#define AR_PHY_AGC_CONTROL_CLC_SUCCESS 0x00080000 /* carrier leak calibration done */ +#define AR_PHY_AGC_CONTROL_YCOK_MAX 0x000003c0 +#define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6 + #endif -- cgit v1.2.3 From 77d6d39a77939e5ed7e2ec72a1c1dce828ee582e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:09 -0400 Subject: ath9k_hw: abstract loading noisefloor This is the last call on calib.c which acceses PHY stuff, with this change we calib.c is now generic between both all supported hardware families. Signed-off-by: Luis R. Rodriguez Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar5008_phy.c | 67 +++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_calib.c | 6 +++ drivers/net/wireless/ath/ath9k/calib.c | 67 --------------------------- drivers/net/wireless/ath/ath9k/calib.h | 1 - drivers/net/wireless/ath/ath9k/hw-ops.h | 6 +++ drivers/net/wireless/ath/ath9k/hw.h | 2 + 6 files changed, 81 insertions(+), 68 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index bd3792c78af1..94eb069b5ae3 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -1247,6 +1247,72 @@ static void ar5008_hw_do_getnf(struct ath_hw *ah, nfarray[5] = nf; } +static void ar5008_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) +{ + struct ath9k_nfcal_hist *h; + int i, j; + int32_t val; + const u32 ar5416_cca_regs[6] = { + AR_PHY_CCA, + AR_PHY_CH1_CCA, + AR_PHY_CH2_CCA, + AR_PHY_EXT_CCA, + AR_PHY_CH1_EXT_CCA, + AR_PHY_CH2_EXT_CCA + }; + u8 chainmask, rx_chain_status; + + rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); + if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) + chainmask = 0x9; + else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { + if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) + chainmask = 0x1B; + else + chainmask = 0x09; + } else { + if (rx_chain_status & 0x4) + chainmask = 0x3F; + else if (rx_chain_status & 0x2) + chainmask = 0x1B; + else + chainmask = 0x09; + } + + h = ah->nfCalHist; + + for (i = 0; i < NUM_NF_READINGS; i++) { + if (chainmask & (1 << i)) { + val = REG_READ(ah, ar5416_cca_regs[i]); + val &= 0xFFFFFE00; + val |= (((u32) (h[i].privNF) << 1) & 0x1ff); + REG_WRITE(ah, ar5416_cca_regs[i], val); + } + } + + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_ENABLE_NF); + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + + for (j = 0; j < 5; j++) { + if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & + AR_PHY_AGC_CONTROL_NF) == 0) + break; + udelay(50); + } + + for (i = 0; i < NUM_NF_READINGS; i++) { + if (chainmask & (1 << i)) { + val = REG_READ(ah, ar5416_cca_regs[i]); + val &= 0xFFFFFE00; + val |= (((u32) (-50) << 1) & 0x1ff); + REG_WRITE(ah, ar5416_cca_regs[i], val); + } + } +} + void ar5008_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); @@ -1270,6 +1336,7 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->set_diversity = ar5008_set_diversity; priv_ops->ani_control = ar5008_hw_ani_control; priv_ops->do_getnf = ar5008_hw_do_getnf; + priv_ops->loadnf = ar5008_hw_loadnf; if (AR_SREV_9100(ah)) priv_ops->compute_pll_control = ar9100_hw_compute_pll_control; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 00e4cb8d5f04..cd80a43ffcff 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -195,6 +195,11 @@ static bool ar9003_hw_iscal_supported(struct ath_hw *ah, return false; } +static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) +{ + /* TODO */ +} + void ar9003_hw_attach_calib_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); @@ -204,6 +209,7 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah) priv_ops->init_cal = ar9003_hw_init_cal; priv_ops->setup_calibration = ar9003_hw_setup_calibration; priv_ops->iscal_supported = ar9003_hw_iscal_supported; + priv_ops->loadnf = ar9003_hw_loadnf; ops->calibrate = ar9003_hw_calibrate; } diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 085e1264fbe0..6982577043b8 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -16,7 +16,6 @@ #include "hw.h" #include "hw-ops.h" -#include "ar9002_phy.h" /* Common calibration code */ @@ -174,72 +173,6 @@ void ath9k_hw_start_nfcal(struct ath_hw *ah) REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); } -void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) -{ - struct ath9k_nfcal_hist *h; - int i, j; - int32_t val; - const u32 ar5416_cca_regs[6] = { - AR_PHY_CCA, - AR_PHY_CH1_CCA, - AR_PHY_CH2_CCA, - AR_PHY_EXT_CCA, - AR_PHY_CH1_EXT_CCA, - AR_PHY_CH2_EXT_CCA - }; - u8 chainmask, rx_chain_status; - - rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); - if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) - chainmask = 0x9; - else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { - if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) - chainmask = 0x1B; - else - chainmask = 0x09; - } else { - if (rx_chain_status & 0x4) - chainmask = 0x3F; - else if (rx_chain_status & 0x2) - chainmask = 0x1B; - else - chainmask = 0x09; - } - - h = ah->nfCalHist; - - for (i = 0; i < NUM_NF_READINGS; i++) { - if (chainmask & (1 << i)) { - val = REG_READ(ah, ar5416_cca_regs[i]); - val &= 0xFFFFFE00; - val |= (((u32) (h[i].privNF) << 1) & 0x1ff); - REG_WRITE(ah, ar5416_cca_regs[i], val); - } - } - - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_ENABLE_NF); - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_NO_UPDATE_NF); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); - - for (j = 0; j < 5; j++) { - if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & - AR_PHY_AGC_CONTROL_NF) == 0) - break; - udelay(50); - } - - for (i = 0; i < NUM_NF_READINGS; i++) { - if (chainmask & (1 << i)) { - val = REG_READ(ah, ar5416_cca_regs[i]); - val &= 0xFFFFFE00; - val |= (((u32) (-50) << 1) & 0x1ff); - REG_WRITE(ah, ar5416_cca_regs[i], val); - } - } -} - int16_t ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) { diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 9f6c21d50f17..25828e89e7c7 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -114,7 +114,6 @@ struct ath9k_pacal_info{ bool ath9k_hw_reset_calvalid(struct ath_hw *ah); void ath9k_hw_start_nfcal(struct ath_hw *ah); -void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); int16_t ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah); diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index b777fd1894f0..b444ce5f09f8 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -182,6 +182,12 @@ static inline void ath9k_hw_do_getnf(struct ath_hw *ah, ath9k_hw_private_ops(ah)->do_getnf(ah, nfarray); } +static inline void ath9k_hw_loadnf(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + ath9k_hw_private_ops(ah)->loadnf(ah, chan); +} + static inline bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) { diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7a32733108a2..d28a904606b8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -486,6 +486,7 @@ struct ath_gen_timer_table { * AR_RTC_PLL_CONTROL for a given channel * @setup_calibration: set up calibration * @iscal_supported: used to query if a type of calibration is supported + * @loadnf: load noise floor read from each chain on the CCA registers */ struct ath_hw_private_ops { /* Calibration ops */ @@ -528,6 +529,7 @@ struct ath_hw_private_ops { bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd, int param); void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]); + void (*loadnf)(struct ath_hw *ah, struct ath9k_channel *chan); }; /** -- cgit v1.2.3 From 4b01931e3a3ca5ec49604e2b279b8b9dd42fbe4c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:10 -0400 Subject: ath9k_hw: fill in the callbacks for calibration for AR9003 Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_calib.c | 2 ++ drivers/net/wireless/ath/ath9k/ar9003_calib.c | 36 ++++++++++++++++++++++++++- drivers/net/wireless/ath/ath9k/calib.h | 3 ++- 3 files changed, 39 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index cd234aafaa4a..968529b3988f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -50,6 +50,8 @@ static void ar9002_hw_setup_calibration(struct ath_hw *ah, ath_print(common, ATH_DBG_CALIBRATE, "starting Init ADC DC Calibration\n"); break; + case TEMP_COMP_CAL: + break; /* Not supported */ } REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index cd80a43ffcff..f0e8f639ecfd 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -21,7 +21,41 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal) { - /* TODO */ + struct ath_common *common = ath9k_hw_common(ah); + + /* Select calibration to run */ + switch (currCal->calData->calType) { + case IQ_MISMATCH_CAL: + /* + * Start calibration with + * 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples + */ + REG_RMW_FIELD(ah, AR_PHY_TIMING4, + AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX, + currCal->calData->calCountMax); + REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); + + ath_print(common, ATH_DBG_CALIBRATE, + "starting IQ Mismatch Calibration\n"); + + /* Kick-off cal */ + REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL); + break; + case TEMP_COMP_CAL: + REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM, + AR_PHY_65NM_CH0_THERM_LOCAL, 1); + REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM, + AR_PHY_65NM_CH0_THERM_START, 1); + + ath_print(common, ATH_DBG_CALIBRATE, + "starting Temperature Compensation Calibration\n"); + break; + case ADC_DC_INIT_CAL: + case ADC_GAIN_CAL: + case ADC_DC_CAL: + /* Not yet */ + break; + } } static bool ar9003_hw_calibrate(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 25828e89e7c7..24538bdb9126 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -68,7 +68,8 @@ enum ath9k_cal_types { ADC_DC_INIT_CAL = 0x1, ADC_GAIN_CAL = 0x2, ADC_DC_CAL = 0x4, - IQ_MISMATCH_CAL = 0x8 + IQ_MISMATCH_CAL = 0x8, + TEMP_COMP_CAL = 0x10, }; enum ath9k_cal_state { -- cgit v1.2.3 From df23acaa5d3239745805650e2f27a4252182c063 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:11 -0400 Subject: ath9k_hw: complete AR9003 calibration This goes with some new shiny TX IQ calibration that AR9003 hardware family supports. Signed-off-by: Luis R. Rodriguez Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 577 +++++++++++++++++++++++++- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 100 +++++ drivers/net/wireless/ath/ath9k/eeprom.h | 1 + drivers/net/wireless/ath/ath9k/hw.h | 1 + 4 files changed, 667 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index f0e8f639ecfd..5e20b4860c7f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -58,20 +58,108 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah, } } +/* + * Generic calibration routine. + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +static bool ar9003_hw_per_calibration(struct ath_hw *ah, + struct ath9k_channel *ichan, + u8 rxchainmask, + struct ath9k_cal_list *currCal) +{ + /* Cal is assumed not done until explicitly set below */ + bool iscaldone = false; + + /* Calibration in progress. */ + if (currCal->calState == CAL_RUNNING) { + /* Check to see if it has finished. */ + if (!(REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) { + /* + * Accumulate cal measures for active chains + */ + currCal->calData->calCollect(ah); + ah->cal_samples++; + + if (ah->cal_samples >= + currCal->calData->calNumSamples) { + unsigned int i, numChains = 0; + for (i = 0; i < AR9300_MAX_CHAINS; i++) { + if (rxchainmask & (1 << i)) + numChains++; + } + + /* + * Process accumulated data + */ + currCal->calData->calPostProc(ah, numChains); + + /* Calibration has finished. */ + ichan->CalValid |= currCal->calData->calType; + currCal->calState = CAL_DONE; + iscaldone = true; + } else { + /* + * Set-up collection of another sub-sample until we + * get desired number + */ + ar9003_hw_setup_calibration(ah, currCal); + } + } + } else if (!(ichan->CalValid & currCal->calData->calType)) { + /* If current cal is marked invalid in channel, kick it off */ + ath9k_hw_reset_calibration(ah, currCal); + } + + return iscaldone; +} + static bool ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, u8 rxchainmask, bool longcal) { - /* TODO */ - return false; -} + bool iscaldone = true; + struct ath9k_cal_list *currCal = ah->cal_list_curr; + + /* + * For given calibration: + * 1. Call generic cal routine + * 2. When this cal is done (isCalDone) if we have more cals waiting + * (eg after reset), mask this to upper layers by not propagating + * isCalDone if it is set to TRUE. + * Instead, change isCalDone to FALSE and setup the waiting cal(s) + * to be run. + */ + if (currCal && + (currCal->calState == CAL_RUNNING || + currCal->calState == CAL_WAITING)) { + iscaldone = ar9003_hw_per_calibration(ah, chan, + rxchainmask, currCal); + if (iscaldone) { + ah->cal_list_curr = currCal = currCal->calNext; + + if (currCal->calState == CAL_WAITING) { + iscaldone = false; + ath9k_hw_reset_calibration(ah, currCal); + } + } + } -static bool ar9003_hw_init_cal(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - /* TODO */ - return false; + /* Do NF cal only at longer intervals */ + if (longcal) { + /* + * Load the NF from history buffer of the current channel. + * NF is slow time-variant, so it is OK to use a historical + * value. + */ + ath9k_hw_loadnf(ah, ah->curchan); + + /* start NF calibration, without updating BB NF register */ + ath9k_hw_start_nfcal(ah); + } + + return iscaldone; } static void ar9003_hw_iqcal_collect(struct ath_hw *ah) @@ -225,13 +313,479 @@ static void ar9003_hw_init_cal_settings(struct ath_hw *ah) static bool ar9003_hw_iscal_supported(struct ath_hw *ah, enum ath9k_cal_types calType) { - /* TODO */ + switch (calType & ah->supp_cals) { + case IQ_MISMATCH_CAL: + /* + * XXX: Run IQ Mismatch for non-CCK only + * Note that CHANNEL_B is never set though. + */ + return true; + case ADC_GAIN_CAL: + case ADC_DC_CAL: + return false; + case TEMP_COMP_CAL: + return true; + } + return false; } -static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) +/* + * solve 4x4 linear equation used in loopback iq cal. + */ +static bool ar9003_hw_solve_iq_cal(struct ath_hw *ah, + s32 sin_2phi_1, + s32 cos_2phi_1, + s32 sin_2phi_2, + s32 cos_2phi_2, + s32 mag_a0_d0, + s32 phs_a0_d0, + s32 mag_a1_d0, + s32 phs_a1_d0, + s32 solved_eq[]) +{ + s32 f1 = cos_2phi_1 - cos_2phi_2, + f3 = sin_2phi_1 - sin_2phi_2, + f2; + s32 mag_tx, phs_tx, mag_rx, phs_rx; + const s32 result_shift = 1 << 15; + struct ath_common *common = ath9k_hw_common(ah); + + f2 = (f1 * f1 + f3 * f3) / result_shift; + + if (!f2) { + ath_print(common, ATH_DBG_CALIBRATE, "Divide by 0\n"); + return false; + } + + /* mag mismatch, tx */ + mag_tx = f1 * (mag_a0_d0 - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0); + /* phs mismatch, tx */ + phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0); + + mag_tx = (mag_tx / f2); + phs_tx = (phs_tx / f2); + + /* mag mismatch, rx */ + mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) / + result_shift; + /* phs mismatch, rx */ + phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) / + result_shift; + + solved_eq[0] = mag_tx; + solved_eq[1] = phs_tx; + solved_eq[2] = mag_rx; + solved_eq[3] = phs_rx; + + return true; +} + +static s32 ar9003_hw_find_mag_approx(struct ath_hw *ah, s32 in_re, s32 in_im) { - /* TODO */ + s32 abs_i = abs(in_re), + abs_q = abs(in_im), + max_abs, min_abs; + + if (abs_i > abs_q) { + max_abs = abs_i; + min_abs = abs_q; + } else { + max_abs = abs_q; + min_abs = abs_i; + } + + return max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4); +} + +#define DELPT 32 + +static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, + s32 chain_idx, + const s32 iq_res[], + s32 iqc_coeff[]) +{ + s32 i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0, + i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1, + i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0, + i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1; + s32 mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1, + phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1, + sin_2phi_1, cos_2phi_1, + sin_2phi_2, cos_2phi_2; + s32 mag_tx, phs_tx, mag_rx, phs_rx; + s32 solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx, + q_q_coff, q_i_coff; + const s32 res_scale = 1 << 15; + const s32 delpt_shift = 1 << 8; + s32 mag1, mag2; + struct ath_common *common = ath9k_hw_common(ah); + + i2_m_q2_a0_d0 = iq_res[0] & 0xfff; + i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff; + iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8); + + if (i2_m_q2_a0_d0 > 0x800) + i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1); + + if (i2_p_q2_a0_d0 > 0x800) + i2_p_q2_a0_d0 = -((0xfff - i2_p_q2_a0_d0) + 1); + + if (iq_corr_a0_d0 > 0x800) + iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1); + + i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff; + i2_p_q2_a0_d1 = (iq_res[2] & 0xfff); + iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff; + + if (i2_m_q2_a0_d1 > 0x800) + i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1); + + if (i2_p_q2_a0_d1 > 0x800) + i2_p_q2_a0_d1 = -((0xfff - i2_p_q2_a0_d1) + 1); + + if (iq_corr_a0_d1 > 0x800) + iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1); + + i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8); + i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff; + iq_corr_a1_d0 = iq_res[4] & 0xfff; + + if (i2_m_q2_a1_d0 > 0x800) + i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1); + + if (i2_p_q2_a1_d0 > 0x800) + i2_p_q2_a1_d0 = -((0xfff - i2_p_q2_a1_d0) + 1); + + if (iq_corr_a1_d0 > 0x800) + iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1); + + i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff; + i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8); + iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff; + + if (i2_m_q2_a1_d1 > 0x800) + i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1); + + if (i2_p_q2_a1_d1 > 0x800) + i2_p_q2_a1_d1 = -((0xfff - i2_p_q2_a1_d1) + 1); + + if (iq_corr_a1_d1 > 0x800) + iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1); + + if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) || + (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) { + ath_print(common, ATH_DBG_CALIBRATE, + "Divide by 0:\na0_d0=%d\n" + "a0_d1=%d\na2_d0=%d\na1_d1=%d\n", + i2_p_q2_a0_d0, i2_p_q2_a0_d1, + i2_p_q2_a1_d0, i2_p_q2_a1_d1); + return false; + } + + mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0; + phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0; + + mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1; + phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1; + + mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0; + phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0; + + mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1; + phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1; + + /* w/o analog phase shift */ + sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT); + /* w/o analog phase shift */ + cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT); + /* w/ analog phase shift */ + sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT); + /* w/ analog phase shift */ + cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT); + + /* + * force sin^2 + cos^2 = 1; + * find magnitude by approximation + */ + mag1 = ar9003_hw_find_mag_approx(ah, cos_2phi_1, sin_2phi_1); + mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2); + + if ((mag1 == 0) || (mag2 == 0)) { + ath_print(common, ATH_DBG_CALIBRATE, + "Divide by 0: mag1=%d, mag2=%d\n", + mag1, mag2); + return false; + } + + /* normalization sin and cos by mag */ + sin_2phi_1 = (sin_2phi_1 * res_scale / mag1); + cos_2phi_1 = (cos_2phi_1 * res_scale / mag1); + sin_2phi_2 = (sin_2phi_2 * res_scale / mag2); + cos_2phi_2 = (cos_2phi_2 * res_scale / mag2); + + /* calculate IQ mismatch */ + if (!ar9003_hw_solve_iq_cal(ah, + sin_2phi_1, cos_2phi_1, + sin_2phi_2, cos_2phi_2, + mag_a0_d0, phs_a0_d0, + mag_a1_d0, + phs_a1_d0, solved_eq)) { + ath_print(common, ATH_DBG_CALIBRATE, + "Call to ar9003_hw_solve_iq_cal() failed.\n"); + return false; + } + + mag_tx = solved_eq[0]; + phs_tx = solved_eq[1]; + mag_rx = solved_eq[2]; + phs_rx = solved_eq[3]; + + ath_print(common, ATH_DBG_CALIBRATE, + "chain %d: mag mismatch=%d phase mismatch=%d\n", + chain_idx, mag_tx/res_scale, phs_tx/res_scale); + + if (res_scale == mag_tx) { + ath_print(common, ATH_DBG_CALIBRATE, + "Divide by 0: mag_tx=%d, res_scale=%d\n", + mag_tx, res_scale); + return false; + } + + /* calculate and quantize Tx IQ correction factor */ + mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx); + phs_corr_tx = -phs_tx; + + q_q_coff = (mag_corr_tx * 128 / res_scale); + q_i_coff = (phs_corr_tx * 256 / res_scale); + + ath_print(common, ATH_DBG_CALIBRATE, + "tx chain %d: mag corr=%d phase corr=%d\n", + chain_idx, q_q_coff, q_i_coff); + + if (q_i_coff < -63) + q_i_coff = -63; + if (q_i_coff > 63) + q_i_coff = 63; + if (q_q_coff < -63) + q_q_coff = -63; + if (q_q_coff > 63) + q_q_coff = 63; + + iqc_coeff[0] = (q_q_coff * 128) + q_i_coff; + + ath_print(common, ATH_DBG_CALIBRATE, + "tx chain %d: iq corr coeff=%x\n", + chain_idx, iqc_coeff[0]); + + if (-mag_rx == res_scale) { + ath_print(common, ATH_DBG_CALIBRATE, + "Divide by 0: mag_rx=%d, res_scale=%d\n", + mag_rx, res_scale); + return false; + } + + /* calculate and quantize Rx IQ correction factors */ + mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx); + phs_corr_rx = -phs_rx; + + q_q_coff = (mag_corr_rx * 128 / res_scale); + q_i_coff = (phs_corr_rx * 256 / res_scale); + + ath_print(common, ATH_DBG_CALIBRATE, + "rx chain %d: mag corr=%d phase corr=%d\n", + chain_idx, q_q_coff, q_i_coff); + + if (q_i_coff < -63) + q_i_coff = -63; + if (q_i_coff > 63) + q_i_coff = 63; + if (q_q_coff < -63) + q_q_coff = -63; + if (q_q_coff > 63) + q_q_coff = 63; + + iqc_coeff[1] = (q_q_coff * 128) + q_i_coff; + + ath_print(common, ATH_DBG_CALIBRATE, + "rx chain %d: iq corr coeff=%x\n", + chain_idx, iqc_coeff[1]); + + return true; +} + +static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + const u32 txiqcal_status[AR9300_MAX_CHAINS] = { + AR_PHY_TX_IQCAL_STATUS_B0, + AR_PHY_TX_IQCAL_STATUS_B1, + AR_PHY_TX_IQCAL_STATUS_B2, + }; + const u32 tx_corr_coeff[AR9300_MAX_CHAINS] = { + AR_PHY_TX_IQCAL_CORR_COEFF_01_B0, + AR_PHY_TX_IQCAL_CORR_COEFF_01_B1, + AR_PHY_TX_IQCAL_CORR_COEFF_01_B2, + }; + const u32 rx_corr[AR9300_MAX_CHAINS] = { + AR_PHY_RX_IQCAL_CORR_B0, + AR_PHY_RX_IQCAL_CORR_B1, + AR_PHY_RX_IQCAL_CORR_B2, + }; + const u_int32_t chan_info_tab[] = { + AR_PHY_CHAN_INFO_TAB_0, + AR_PHY_CHAN_INFO_TAB_1, + AR_PHY_CHAN_INFO_TAB_2, + }; + s32 iq_res[6]; + s32 iqc_coeff[2]; + s32 i, j; + u32 num_chains = 0; + + for (i = 0; i < AR9300_MAX_CHAINS; i++) { + if (ah->txchainmask & (1 << i)) + num_chains++; + } + + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, + AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, + DELPT); + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, + AR_PHY_TX_IQCAL_START_DO_CAL, + AR_PHY_TX_IQCAL_START_DO_CAL); + + if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, + AR_PHY_TX_IQCAL_START_DO_CAL, + 0, AH_WAIT_TIMEOUT)) { + ath_print(common, ATH_DBG_CALIBRATE, + "Tx IQ Cal not complete.\n"); + goto TX_IQ_CAL_FAILED; + } + + for (i = 0; i < num_chains; i++) { + ath_print(common, ATH_DBG_CALIBRATE, + "Doing Tx IQ Cal for chain %d.\n", i); + + if (REG_READ(ah, txiqcal_status[i]) & + AR_PHY_TX_IQCAL_STATUS_FAILED) { + ath_print(common, ATH_DBG_CALIBRATE, + "Tx IQ Cal failed for chain %d.\n", i); + goto TX_IQ_CAL_FAILED; + } + + for (j = 0; j < 3; j++) { + u_int8_t idx = 2 * j, + offset = 4 * j; + + REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, + AR_PHY_CHAN_INFO_TAB_S2_READ, 0); + + /* 32 bits */ + iq_res[idx] = REG_READ(ah, chan_info_tab[i] + offset); + + REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, + AR_PHY_CHAN_INFO_TAB_S2_READ, 1); + + /* 16 bits */ + iq_res[idx+1] = 0xffff & REG_READ(ah, + chan_info_tab[i] + + offset); + + ath_print(common, ATH_DBG_CALIBRATE, + "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n", + idx, iq_res[idx], idx+1, iq_res[idx+1]); + } + + if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, iqc_coeff)) { + ath_print(common, ATH_DBG_CALIBRATE, + "Failed in calculation of IQ correction.\n"); + goto TX_IQ_CAL_FAILED; + } + + ath_print(common, ATH_DBG_CALIBRATE, + "IQ_COEFF[0] = 0x%x IQ_COEFF[1] = 0x%x\n", + iqc_coeff[0], iqc_coeff[1]); + + REG_RMW_FIELD(ah, tx_corr_coeff[i], + AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE, + iqc_coeff[0]); + REG_RMW_FIELD(ah, rx_corr[i], + AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF, + iqc_coeff[1] >> 7); + REG_RMW_FIELD(ah, rx_corr[i], + AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF, + iqc_coeff[1]); + } + + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, + AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1); + REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, + AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); + + return; + +TX_IQ_CAL_FAILED: + ath_print(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); + return; +} + +static bool ar9003_hw_init_cal(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + struct ath_common *common = ath9k_hw_common(ah); + + /* + * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain mode before + * running AGC/TxIQ cals + */ + ar9003_hw_set_chain_masks(ah, 0x7, 0x7); + + /* Calibrate the AGC */ + REG_WRITE(ah, AR_PHY_AGC_CONTROL, + REG_READ(ah, AR_PHY_AGC_CONTROL) | + AR_PHY_AGC_CONTROL_CAL); + + /* Poll for offset calibration complete */ + if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, + 0, AH_WAIT_TIMEOUT)) { + ath_print(common, ATH_DBG_CALIBRATE, + "offset calibration failed to " + "complete in 1ms; noisy environment?\n"); + return false; + } + + /* Do Tx IQ Calibration */ + ar9003_hw_tx_iq_cal(ah); + + /* Revert chainmasks to their original values before NF cal */ + ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); + + /* Initialize list pointers */ + ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; + + if (ar9003_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { + INIT_CAL(&ah->iq_caldata); + INSERT_CAL(ah, &ah->iq_caldata); + ath_print(common, ATH_DBG_CALIBRATE, + "enabling IQ Calibration.\n"); + } + + if (ar9003_hw_iscal_supported(ah, TEMP_COMP_CAL)) { + INIT_CAL(&ah->tempCompCalData); + INSERT_CAL(ah, &ah->tempCompCalData); + ath_print(common, ATH_DBG_CALIBRATE, + "enabling Temperature Compensation Calibration.\n"); + } + + /* Initialize current pointer to first element in list */ + ah->cal_list_curr = ah->cal_list; + + if (ah->cal_list_curr) + ath9k_hw_reset_calibration(ah, ah->cal_list_curr); + + chan->CalValid = 0; + + return true; } void ar9003_hw_attach_calib_ops(struct ath_hw *ah) @@ -243,7 +797,6 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah) priv_ops->init_cal = ar9003_hw_init_cal; priv_ops->setup_calibration = ar9003_hw_setup_calibration; priv_ops->iscal_supported = ar9003_hw_iscal_supported; - priv_ops->loadnf = ar9003_hw_loadnf; ops->calibrate = ar9003_hw_calibrate; } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 67b3b6518436..fee07fd7a595 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -814,6 +814,105 @@ void ar9003_hw_set_nf_limits(struct ath_hw *ah) ah->nf_5g_min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ; } +/* + * Find out which of the RX chains are enabled + */ +static u32 ar9003_hw_get_rx_chainmask(struct ath_hw *ah) +{ + u32 chain = REG_READ(ah, AR_PHY_RX_CHAINMASK); + /* + * The bits [2:0] indicate the rx chain mask and are to be + * interpreted as follows: + * 00x => Only chain 0 is enabled + * 01x => Chain 1 and 0 enabled + * 1xx => Chain 2,1 and 0 enabled + */ + return chain & 0x7; +} + +static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) +{ + struct ath9k_nfcal_hist *h; + unsigned i, j; + int32_t val; + const u32 ar9300_cca_regs[6] = { + AR_PHY_CCA_0, + AR_PHY_CCA_1, + AR_PHY_CCA_2, + AR_PHY_EXT_CCA, + AR_PHY_EXT_CCA_1, + AR_PHY_EXT_CCA_2, + }; + u8 chainmask, rx_chain_status; + struct ath_common *common = ath9k_hw_common(ah); + + rx_chain_status = ar9003_hw_get_rx_chainmask(ah); + + chainmask = 0x3F; + h = ah->nfCalHist; + + for (i = 0; i < NUM_NF_READINGS; i++) { + if (chainmask & (1 << i)) { + val = REG_READ(ah, ar9300_cca_regs[i]); + val &= 0xFFFFFE00; + val |= (((u32) (h[i].privNF) << 1) & 0x1ff); + REG_WRITE(ah, ar9300_cca_regs[i], val); + } + } + + /* + * Load software filtered NF value into baseband internal minCCApwr + * variable. + */ + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_ENABLE_NF); + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + + /* + * Wait for load to complete, should be fast, a few 10s of us. + * The max delay was changed from an original 250us to 10000us + * since 250us often results in NF load timeout and causes deaf + * condition during stress testing 12/12/2009 + */ + for (j = 0; j < 1000; j++) { + if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & + AR_PHY_AGC_CONTROL_NF) == 0) + break; + udelay(10); + } + + /* + * We timed out waiting for the noisefloor to load, probably due to an + * in-progress rx. Simply return here and allow the load plenty of time + * to complete before the next calibration interval. We need to avoid + * trying to load -50 (which happens below) while the previous load is + * still in progress as this can cause rx deafness. Instead by returning + * here, the baseband nf cal will just be capped by our present + * noisefloor until the next calibration timer. + */ + if (j == 1000) { + ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf " + "to load: AR_PHY_AGC_CONTROL=0x%x\n", + REG_READ(ah, AR_PHY_AGC_CONTROL)); + } + + /* + * Restore maxCCAPower register parameter again so that we're not capped + * by the median we just loaded. This will be initial (and max) value + * of next noise floor calibration the baseband does. + */ + for (i = 0; i < NUM_NF_READINGS; i++) { + if (chainmask & (1 << i)) { + val = REG_READ(ah, ar9300_cca_regs[i]); + val &= 0xFFFFFE00; + val |= (((u32) (-50) << 1) & 0x1ff); + REG_WRITE(ah, ar9300_cca_regs[i], val); + } + } +} + void ar9003_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); @@ -833,4 +932,5 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->set_diversity = ar9003_hw_set_diversity; priv_ops->ani_control = ar9003_hw_ani_control; priv_ops->do_getnf = ar9003_hw_do_getnf; + priv_ops->loadnf = ar9003_hw_loadnf; } diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index e087e2de6067..c0cd717738c0 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -155,6 +155,7 @@ #define AR5416_BCHAN_UNUSED 0xFF #define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 #define AR5416_MAX_CHAINS 3 +#define AR9300_MAX_CHAINS 3 #define AR5416_PWR_TABLE_OFFSET_DB -5 /* Rx gain type values */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index d28a904606b8..cb0421a910d2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -611,6 +611,7 @@ struct ath_hw { struct ath9k_cal_list adcgain_caldata; struct ath9k_cal_list adcdc_calinitdata; struct ath9k_cal_list adcdc_caldata; + struct ath9k_cal_list tempCompCalData; struct ath9k_cal_list *cal_list; struct ath9k_cal_list *cal_list_last; struct ath9k_cal_list *cal_list_curr; -- cgit v1.2.3 From 0b8f6f2b1b18c7a3cb70fbb44ab5f4883d59f738 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:12 -0400 Subject: ath9k_hw: rename eep_AR9287_ops to eep_ar9287_ops Signed-off-by: Senthil Balasubramanian Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom.c | 2 +- drivers/net/wireless/ath/ath9k/eeprom.h | 2 +- drivers/net/wireless/ath/ath9k/eeprom_9287.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index 1a48f43f653e..aec6ebbb6584 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -257,7 +257,7 @@ int ath9k_hw_eeprom_init(struct ath_hw *ah) int status; if (AR_SREV_9287(ah)) { - ah->eep_ops = &eep_AR9287_ops; + ah->eep_ops = &eep_ar9287_ops; } else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) { ah->eep_ops = &eep_4k_ops; } else { diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index c0cd717738c0..60fd5b6f3523 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -707,6 +707,6 @@ int ath9k_hw_eeprom_init(struct ath_hw *ah); extern const struct eeprom_ops eep_def_ops; extern const struct eeprom_ops eep_4k_ops; -extern const struct eeprom_ops eep_AR9287_ops; +extern const struct eeprom_ops eep_ar9287_ops; #endif /* EEPROM_H */ diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index e57c5b48c039..0b1e885c961b 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -1170,7 +1170,7 @@ static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah, #undef EEP_MAP9287_SPURCHAN } -const struct eeprom_ops eep_AR9287_ops = { +const struct eeprom_ops eep_ar9287_ops = { .check_eeprom = ath9k_hw_AR9287_check_eeprom, .get_eeprom = ath9k_hw_AR9287_get_eeprom, .fill_eeprom = ath9k_hw_AR9287_fill_eeprom, -- cgit v1.2.3 From 49101676b2f1a66e0043509423e876414c73b5aa Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:13 -0400 Subject: ath9k_hw: restore mac address reading logic Once upon a time the AR_EEPROM_MAC macro was added to let us add a random attribute to the three 4-bytes of MAC addresses entries we read from the EEPROM. This was good while a random high-enough value was used which did not conflict with any of the already existing enum eeprom_param values. With AR9003 support the enums overlap and it means we either increment the random offset or just restore the reading logic to match what the HAL has. I choose to do the later to synchronize the logic on both code bases. This should fix reading the MAC address from the EEPROM on AR9003 hardware. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom.h | 1 - drivers/net/wireless/ath/ath9k/eeprom_4k.c | 6 +++--- drivers/net/wireless/ath/ath9k/eeprom_9287.c | 6 +++--- drivers/net/wireless/ath/ath9k/eeprom_def.c | 6 +++--- drivers/net/wireless/ath/ath9k/hw.c | 3 ++- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 60fd5b6f3523..289084c71527 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -93,7 +93,6 @@ */ #define AR9285_RDEXT_DEFAULT 0x1F -#define AR_EEPROM_MAC(i) (0x1d+(i)) #define ATH9K_POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) #define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) #define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM)) diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 97279a5e01e8..2384a9f4f5fb 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -183,11 +183,11 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, switch (param) { case EEP_NFTHRESH_2: return pModal->noiseFloorThreshCh[0]; - case AR_EEPROM_MAC(0): + case EEP_MAC_LSW: return pBase->macAddr[0] << 8 | pBase->macAddr[1]; - case AR_EEPROM_MAC(1): + case EEP_MAC_MID: return pBase->macAddr[2] << 8 | pBase->macAddr[3]; - case AR_EEPROM_MAC(2): + case EEP_MAC_MSW: return pBase->macAddr[4] << 8 | pBase->macAddr[5]; case EEP_REG_0: return pBase->regDmn[0]; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 0b1e885c961b..b471db5fb82d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -173,11 +173,11 @@ static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah, switch (param) { case EEP_NFTHRESH_2: return pModal->noiseFloorThreshCh[0]; - case AR_EEPROM_MAC(0): + case EEP_MAC_LSW: return pBase->macAddr[0] << 8 | pBase->macAddr[1]; - case AR_EEPROM_MAC(1): + case EEP_MAC_MID: return pBase->macAddr[2] << 8 | pBase->macAddr[3]; - case AR_EEPROM_MAC(2): + case EEP_MAC_MSW: return pBase->macAddr[4] << 8 | pBase->macAddr[5]; case EEP_REG_0: return pBase->regDmn[0]; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 99f16a3a5be8..3d1b86bd07df 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -238,11 +238,11 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, return pModal[0].noiseFloorThreshCh[0]; case EEP_NFTHRESH_2: return pModal[1].noiseFloorThreshCh[0]; - case AR_EEPROM_MAC(0): + case EEP_MAC_LSW: return pBase->macAddr[0] << 8 | pBase->macAddr[1]; - case AR_EEPROM_MAC(1): + case EEP_MAC_MID: return pBase->macAddr[2] << 8 | pBase->macAddr[3]; - case AR_EEPROM_MAC(2): + case EEP_MAC_MSW: return pBase->macAddr[4] << 8 | pBase->macAddr[5]; case EEP_REG_0: return pBase->regDmn[0]; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index d074cc0a2319..01706d9cfc56 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -472,10 +472,11 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah) u32 sum; int i; u16 eeval; + u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW }; sum = 0; for (i = 0; i < 3; i++) { - eeval = ah->eep_ops->get_eeprom(ah, AR_EEPROM_MAC(i)); + eeval = ah->eep_ops->get_eeprom(ah, EEP_MAC[i]); sum += eeval; common->macaddr[2 * i] = eeval >> 8; common->macaddr[2 * i + 1] = eeval & 0xff; -- cgit v1.2.3 From 15c9ee7af8a3527a82013ea447da2d8c491aabfe Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Thu, 15 Apr 2010 17:39:14 -0400 Subject: ath9k_hw: Implement AR9003 eeprom callbacks Signed-off-by: Senthil Balasubramanian Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Makefile | 3 +- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 1842 ++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 319 ++++ drivers/net/wireless/ath/ath9k/eeprom.c | 4 +- drivers/net/wireless/ath/ath9k/eeprom.h | 11 +- drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/reg.h | 11 + 7 files changed, 2187 insertions(+), 4 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/ar9003_eeprom.c create mode 100644 drivers/net/wireless/ath/ath9k/ar9003_eeprom.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index ee8f7e87e9ce..b0702fc84651 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -30,7 +30,8 @@ ath9k_hw-y:= \ ani.o \ btcoex.o \ mac.o \ - ar9003_mac.o + ar9003_mac.o \ + ar9003_eeprom.o obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c new file mode 100644 index 000000000000..fb39e392d9f7 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -0,0 +1,1842 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" +#include "ar9003_phy.h" +#include "ar9003_eeprom.h" + +#define COMP_HDR_LEN 4 +#define COMP_CKSUM_LEN 2 + +#define AR_CH0_TOP (0x00016288) +#define AR_CH0_TOP_XPABIASLVL (0x3) +#define AR_CH0_TOP_XPABIASLVL_S (8) + +#define AR_CH0_THERM (0x00016290) +#define AR_CH0_THERM_SPARE (0x3f) +#define AR_CH0_THERM_SPARE_S (0) + +#define AR_SWITCH_TABLE_COM_ALL (0xffff) +#define AR_SWITCH_TABLE_COM_ALL_S (0) + +#define AR_SWITCH_TABLE_COM2_ALL (0xffffff) +#define AR_SWITCH_TABLE_COM2_ALL_S (0) + +#define AR_SWITCH_TABLE_ALL (0xfff) +#define AR_SWITCH_TABLE_ALL_S (0) + +static const struct ar9300_eeprom ar9300_default = { + .eepromVersion = 2, + .templateVersion = 2, + .macAddr = {1, 2, 3, 4, 5, 6}, + .custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + .baseEepHeader = { + .regDmn = {0, 0x1f}, + .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ + .opCapFlags = { + .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A, + .eepMisc = 0, + }, + .rfSilent = 0, + .blueToothOptions = 0, + .deviceCap = 0, + .deviceType = 5, /* takes lower byte in eeprom location */ + .pwrTableOffset = AR9300_PWR_TABLE_OFFSET, + .params_for_tuning_caps = {0, 0}, + .featureEnable = 0x0c, + /* + * bit0 - enable tx temp comp - disabled + * bit1 - enable tx volt comp - disabled + * bit2 - enable fastClock - enabled + * bit3 - enable doubling - enabled + * bit4 - enable internal regulator - disabled + */ + .miscConfiguration = 0, /* bit0 - turn down drivestrength */ + .eepromWriteEnableGpio = 3, + .wlanDisableGpio = 0, + .wlanLedGpio = 8, + .rxBandSelectGpio = 0xff, + .txrxgain = 0, + .swreg = 0, + }, + .modalHeader2G = { + /* ar9300_modal_eep_header 2g */ + /* 4 idle,t1,t2,b(4 bits per setting) */ + .antCtrlCommon = 0x110, + /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ + .antCtrlCommon2 = 0x22222, + + /* + * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r, + * rx1, rx12, b (2 bits each) + */ + .antCtrlChain = {0x150, 0x150, 0x150}, + + /* + * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db + * for ar9280 (0xa20c/b20c 5:0) + */ + .xatten1DB = {0, 0, 0}, + + /* + * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin + * for ar9280 (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0, 0, 0}, + .tempSlope = 36, + .voltSlope = 0, + + /* + * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur + * channels in usual fbin coding format + */ + .spurChans = {0, 0, 0, 0, 0}, + + /* + * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check + * if the register is per chain + */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {1, 1, 1},/* 3 chain */ + .db_stage2 = {1, 1, 1}, /* 3 chain */ + .db_stage3 = {0, 0, 0}, + .db_stage4 = {0, 0, 0}, + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2c, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .futureModal = { /* [32] */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + }, + .calFreqPier2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1), + }, + /* ar9300_cal_data_per_freq_op_loop 2g */ + .calPierData2G = { + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + }, + .calTarget_freqbin_Cck = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2484, 1), + }, + .calTarget_freqbin_2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT20 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT40 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTargetPowerCck = { + /* 1L-5L,5S,11L,11S */ + { {36, 36, 36, 36} }, + { {36, 36, 36, 36} }, + }, + .calTargetPower2G = { + /* 6-24,36,48,54 */ + { {32, 32, 28, 24} }, + { {32, 32, 28, 24} }, + { {32, 32, 28, 24} }, + }, + .calTargetPower2GHT20 = { + { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} }, + { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} }, + { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} }, + }, + .calTargetPower2GHT40 = { + { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} }, + { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} }, + { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} }, + }, + .ctlIndex_2G = { + 0x11, 0x12, 0x15, 0x17, 0x41, 0x42, + 0x45, 0x47, 0x31, 0x32, 0x35, 0x37, + }, + .ctl_freqbin_2G = { + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2457, 1), + FREQ2FBIN(2462, 1) + }, + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + { + FREQ2FBIN(2422, 1), + FREQ2FBIN(2427, 1), + FREQ2FBIN(2447, 1), + FREQ2FBIN(2452, 1) + }, + + { + /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1), + }, + + { + /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), + /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), + /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), + /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), + }, + + { + /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + }, + + { + /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), + /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), + /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), + /* Data[11].ctlEdges[3].bChannel */ + FREQ2FBIN(2462, 1), + } + }, + .ctlPowerData_2G = { + { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, + { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, + { { {60, 1}, {60, 0}, {60, 0}, {60, 1} } }, + + { { {60, 1}, {60, 0}, {0, 0}, {0, 0} } }, + { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, + { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, + + { { {60, 0}, {60, 1}, {60, 1}, {60, 0} } }, + { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, + { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, + + { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, + { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } }, + }, + .modalHeader5G = { + /* 4 idle,t1,t2,b (4 bits per setting) */ + .antCtrlCommon = 0x110, + /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ + .antCtrlCommon2 = 0x22222, + /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ + .antCtrlChain = { + 0x000, 0x000, 0x000, + }, + /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ + .xatten1DB = {0, 0, 0}, + + /* + * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin + * for merlin (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0, 0, 0}, + .tempSlope = 68, + .voltSlope = 0, + /* spurChans spur channels in usual fbin coding format */ + .spurChans = {0, 0, 0, 0, 0}, + /* noiseFloorThreshCh Check if the register is per chain */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {3, 3, 3}, /* 3 chain */ + .db_stage2 = {3, 3, 3}, /* 3 chain */ + .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ + .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2d, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + }, + .calFreqPier5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5725, 0), + FREQ2FBIN(5825, 0) + }, + .calPierData5G = { + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + + }, + .calTarget_freqbin_5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5725, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT20 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5725, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT40 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5725, 0), + FREQ2FBIN(5825, 0) + }, + .calTargetPower5G = { + /* 6-24,36,48,54 */ + { {20, 20, 20, 10} }, + { {20, 20, 20, 10} }, + { {20, 20, 20, 10} }, + { {20, 20, 20, 10} }, + { {20, 20, 20, 10} }, + { {20, 20, 20, 10} }, + { {20, 20, 20, 10} }, + { {20, 20, 20, 10} }, + }, + .calTargetPower5GHT20 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + }, + .calTargetPower5GHT40 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, + }, + .ctlIndex_5G = { + 0x10, 0x16, 0x18, 0x40, 0x46, + 0x48, 0x30, 0x36, 0x38 + }, + .ctl_freqbin_5G = { + { + /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), + /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0), + /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + { + /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), + /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0), + /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), + /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), + /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0), + /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0), + /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0), + /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0), + /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0) + }, + + { + /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), + /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0), + /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0), + /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), + /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[3].ctlEdges[6].bChannel */ 0xFF, + /* Data[3].ctlEdges[7].bChannel */ 0xFF, + }, + + { + /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0), + /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0), + /* Data[4].ctlEdges[4].bChannel */ 0xFF, + /* Data[4].ctlEdges[5].bChannel */ 0xFF, + /* Data[4].ctlEdges[6].bChannel */ 0xFF, + /* Data[4].ctlEdges[7].bChannel */ 0xFF, + }, + + { + /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0), + /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0), + /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), + /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0), + /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), + /* Data[5].ctlEdges[6].bChannel */ 0xFF, + /* Data[5].ctlEdges[7].bChannel */ 0xFF + }, + + { + /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), + /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0), + /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0), + /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), + /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0), + /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0), + /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0) + }, + + { + /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0), + /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0), + /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), + /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), + /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), + /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0), + /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), + /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0), + /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0) + } + }, + .ctlPowerData_5G = { + { + { + {60, 1}, {60, 1}, {60, 1}, {60, 1}, + {60, 1}, {60, 1}, {60, 1}, {60, 0}, + } + }, + { + { + {60, 1}, {60, 1}, {60, 1}, {60, 1}, + {60, 1}, {60, 1}, {60, 1}, {60, 0}, + } + }, + { + { + {60, 0}, {60, 1}, {60, 0}, {60, 1}, + {60, 1}, {60, 1}, {60, 1}, {60, 1}, + } + }, + { + { + {60, 0}, {60, 1}, {60, 1}, {60, 0}, + {60, 1}, {60, 0}, {60, 0}, {60, 0}, + } + }, + { + { + {60, 1}, {60, 1}, {60, 1}, {60, 0}, + {60, 0}, {60, 0}, {60, 0}, {60, 0}, + } + }, + { + { + {60, 1}, {60, 1}, {60, 1}, {60, 1}, + {60, 1}, {60, 0}, {60, 0}, {60, 0}, + } + }, + { + { + {60, 1}, {60, 1}, {60, 1}, {60, 1}, + {60, 1}, {60, 1}, {60, 1}, {60, 1}, + } + }, + { + { + {60, 1}, {60, 1}, {60, 0}, {60, 1}, + {60, 1}, {60, 1}, {60, 1}, {60, 0}, + } + }, + { + { + {60, 1}, {60, 0}, {60, 1}, {60, 1}, + {60, 1}, {60, 1}, {60, 0}, {60, 1}, + } + }, + } +}; + +static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah) +{ + return 0; +} + +static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, + enum eeprom_param param) +{ + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader; + + switch (param) { + case EEP_MAC_LSW: + return eep->macAddr[0] << 8 | eep->macAddr[1]; + case EEP_MAC_MID: + return eep->macAddr[2] << 8 | eep->macAddr[3]; + case EEP_MAC_MSW: + return eep->macAddr[4] << 8 | eep->macAddr[5]; + case EEP_REG_0: + return pBase->regDmn[0]; + case EEP_REG_1: + return pBase->regDmn[1]; + case EEP_OP_CAP: + return pBase->deviceCap; + case EEP_OP_MODE: + return pBase->opCapFlags.opFlags; + case EEP_RF_SILENT: + return pBase->rfSilent; + case EEP_TX_MASK: + return (pBase->txrxMask >> 4) & 0xf; + case EEP_RX_MASK: + return pBase->txrxMask & 0xf; + case EEP_DRIVE_STRENGTH: +#define AR9300_EEP_BASE_DRIV_STRENGTH 0x1 + return pBase->miscConfiguration & AR9300_EEP_BASE_DRIV_STRENGTH; + case EEP_INTERNAL_REGULATOR: + /* Bit 4 is internal regulator flag */ + return (pBase->featureEnable & 0x10) >> 4; + case EEP_SWREG: + return pBase->swreg; + default: + return 0; + } +} + +#ifdef __BIG_ENDIAN +static void ar9300_swap_eeprom(struct ar9300_eeprom *eep) +{ + u32 dword; + u16 word; + int i; + + word = swab16(eep->baseEepHeader.regDmn[0]); + eep->baseEepHeader.regDmn[0] = word; + + word = swab16(eep->baseEepHeader.regDmn[1]); + eep->baseEepHeader.regDmn[1] = word; + + dword = swab32(eep->modalHeader2G.antCtrlCommon); + eep->modalHeader2G.antCtrlCommon = dword; + + dword = swab32(eep->modalHeader2G.antCtrlCommon2); + eep->modalHeader2G.antCtrlCommon2 = dword; + + dword = swab32(eep->modalHeader5G.antCtrlCommon); + eep->modalHeader5G.antCtrlCommon = dword; + + dword = swab32(eep->modalHeader5G.antCtrlCommon2); + eep->modalHeader5G.antCtrlCommon2 = dword; + + for (i = 0; i < AR9300_MAX_CHAINS; i++) { + word = swab16(eep->modalHeader2G.antCtrlChain[i]); + eep->modalHeader2G.antCtrlChain[i] = word; + + word = swab16(eep->modalHeader5G.antCtrlChain[i]); + eep->modalHeader5G.antCtrlChain[i] = word; + } +} +#endif + +static bool ar9300_hw_read_eeprom(struct ath_hw *ah, + long address, u8 *buffer, int many) +{ + int i; + u8 value[2]; + unsigned long eepAddr; + unsigned long byteAddr; + u16 *svalue; + struct ath_common *common = ath9k_hw_common(ah); + + if ((address < 0) || ((address + many) > AR9300_EEPROM_SIZE - 1)) { + ath_print(common, ATH_DBG_EEPROM, + "eeprom address not in range\n"); + return false; + } + + for (i = 0; i < many; i++) { + eepAddr = (u16) (address + i) / 2; + byteAddr = (u16) (address + i) % 2; + svalue = (u16 *) value; + if (!ath9k_hw_nvram_read(common, eepAddr, svalue)) { + ath_print(common, ATH_DBG_EEPROM, + "unable to read eeprom region\n"); + return false; + } + *svalue = le16_to_cpu(*svalue); + buffer[i] = value[byteAddr]; + } + + return true; +} + +static bool ar9300_read_eeprom(struct ath_hw *ah, + int address, u8 *buffer, int many) +{ + int it; + + for (it = 0; it < many; it++) + if (!ar9300_hw_read_eeprom(ah, + (address - it), + (buffer + it), 1)) + return false; + return true; +} + +static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference, + int *length, int *major, int *minor) +{ + unsigned long value[4]; + + value[0] = best[0]; + value[1] = best[1]; + value[2] = best[2]; + value[3] = best[3]; + *code = ((value[0] >> 5) & 0x0007); + *reference = (value[0] & 0x001f) | ((value[1] >> 2) & 0x0020); + *length = ((value[1] << 4) & 0x07f0) | ((value[2] >> 4) & 0x000f); + *major = (value[2] & 0x000f); + *minor = (value[3] & 0x00ff); +} + +static u16 ar9300_comp_cksum(u8 *data, int dsize) +{ + int it, checksum = 0; + + for (it = 0; it < dsize; it++) { + checksum += data[it]; + checksum &= 0xffff; + } + + return checksum; +} + +static bool ar9300_uncompress_block(struct ath_hw *ah, + u8 *mptr, + int mdataSize, + u8 *block, + int size) +{ + int it; + int spot; + int offset; + int length; + struct ath_common *common = ath9k_hw_common(ah); + + spot = 0; + + for (it = 0; it < size; it += (length+2)) { + offset = block[it]; + offset &= 0xff; + spot += offset; + length = block[it+1]; + length &= 0xff; + + if (length > 0 && spot >= 0 && spot+length < mdataSize) { + ath_print(common, ATH_DBG_EEPROM, + "Restore at %d: spot=%d " + "offset=%d length=%d\n", + it, spot, offset, length); + memcpy(&mptr[spot], &block[it+2], length); + spot += length; + } else if (length > 0) { + ath_print(common, ATH_DBG_EEPROM, + "Bad restore at %d: spot=%d " + "offset=%d length=%d\n", + it, spot, offset, length); + return false; + } + } + return true; +} + +static int ar9300_compress_decision(struct ath_hw *ah, + int it, + int code, + int reference, + u8 *mptr, + u8 *word, int length, int mdata_size) +{ + struct ath_common *common = ath9k_hw_common(ah); + u8 *dptr; + + switch (code) { + case _CompressNone: + if (length != mdata_size) { + ath_print(common, ATH_DBG_EEPROM, + "EEPROM structure size mismatch" + "memory=%d eeprom=%d\n", mdata_size, length); + return -1; + } + memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length); + ath_print(common, ATH_DBG_EEPROM, "restored eeprom %d:" + " uncompressed, length %d\n", it, length); + break; + case _CompressBlock: + if (reference == 0) { + dptr = mptr; + } else { + if (reference != 2) { + ath_print(common, ATH_DBG_EEPROM, + "cant find reference eeprom" + "struct %d\n", reference); + return -1; + } + memcpy(mptr, &ar9300_default, mdata_size); + } + ath_print(common, ATH_DBG_EEPROM, + "restore eeprom %d: block, reference %d," + " length %d\n", it, reference, length); + ar9300_uncompress_block(ah, mptr, mdata_size, + (u8 *) (word + COMP_HDR_LEN), length); + break; + default: + ath_print(common, ATH_DBG_EEPROM, "unknown compression" + " code %d\n", code); + return -1; + } + return 0; +} + +/* + * Read the configuration data from the eeprom. + * The data can be put in any specified memory buffer. + * + * Returns -1 on error. + * Returns address of next memory location on success. + */ +static int ar9300_eeprom_restore_internal(struct ath_hw *ah, + u8 *mptr, int mdata_size) +{ +#define MDEFAULT 15 +#define MSTATE 100 + int cptr; + u8 *word; + int code; + int reference, length, major, minor; + int osize; + int it; + u16 checksum, mchecksum; + struct ath_common *common = ath9k_hw_common(ah); + + word = kzalloc(2048, GFP_KERNEL); + if (!word) + return -1; + + memcpy(mptr, &ar9300_default, mdata_size); + + cptr = AR9300_BASE_ADDR; + for (it = 0; it < MSTATE; it++) { + if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN)) + goto fail; + + if ((word[0] == 0 && word[1] == 0 && word[2] == 0 && + word[3] == 0) || (word[0] == 0xff && word[1] == 0xff + && word[2] == 0xff && word[3] == 0xff)) + break; + + ar9300_comp_hdr_unpack(word, &code, &reference, + &length, &major, &minor); + ath_print(common, ATH_DBG_EEPROM, + "Found block at %x: code=%d ref=%d" + "length=%d major=%d minor=%d\n", cptr, code, + reference, length, major, minor); + if (length >= 1024) { + ath_print(common, ATH_DBG_EEPROM, + "Skipping bad header\n"); + cptr -= COMP_HDR_LEN; + continue; + } + + osize = length; + ar9300_read_eeprom(ah, cptr, word, + COMP_HDR_LEN + osize + COMP_CKSUM_LEN); + checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length); + mchecksum = word[COMP_HDR_LEN + osize] | + (word[COMP_HDR_LEN + osize + 1] << 8); + ath_print(common, ATH_DBG_EEPROM, + "checksum %x %x\n", checksum, mchecksum); + if (checksum == mchecksum) { + ar9300_compress_decision(ah, it, code, reference, mptr, + word, length, mdata_size); + } else { + ath_print(common, ATH_DBG_EEPROM, + "skipping block with bad checksum\n"); + } + cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN); + } + + kfree(word); + return cptr; + +fail: + kfree(word); + return -1; +} + +/* + * Restore the configuration structure by reading the eeprom. + * This function destroys any existing in-memory structure + * content. + */ +static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah) +{ + u8 *mptr = NULL; + int mdata_size; + + mptr = (u8 *) &ah->eeprom.ar9300_eep; + mdata_size = sizeof(struct ar9300_eeprom); + + if (mptr && mdata_size > 0) { + /* At this point, mptr points to the eeprom data structure + * in it's "default" state. If this is big endian, swap the + * data structures back to "little endian" + */ + /* First swap, default to Little Endian */ +#ifdef __BIG_ENDIAN + ar9300_swap_eeprom((struct ar9300_eeprom *)mptr); +#endif + if (ar9300_eeprom_restore_internal(ah, mptr, mdata_size) >= 0) + return true; + + /* Second Swap, back to Big Endian */ +#ifdef __BIG_ENDIAN + ar9300_swap_eeprom((struct ar9300_eeprom *)mptr); +#endif + } + return false; +} + +/* XXX: review hardware docs */ +static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah) +{ + return ah->eeprom.ar9300_eep.eepromVersion; +} + +/* XXX: could be read from the eepromVersion, not sure yet */ +static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah) +{ + return 0; +} + +static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah, + enum ieee80211_band freq_band) +{ + return 1; +} + +static u16 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + return -EINVAL; +} + +static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz) +{ + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + + if (is2ghz) + return eep->modalHeader2G.xpaBiasLvl; + else + return eep->modalHeader5G.xpaBiasLvl; +} + +static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) +{ + int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz); + REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, (bias & 0x3)); + REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_SPARE, + ((bias >> 2) & 0x3)); +} + +static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz) +{ + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + + if (is2ghz) + return eep->modalHeader2G.antCtrlCommon; + else + return eep->modalHeader5G.antCtrlCommon; +} + +static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz) +{ + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + + if (is2ghz) + return eep->modalHeader2G.antCtrlCommon2; + else + return eep->modalHeader5G.antCtrlCommon2; +} + +static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, + int chain, + bool is2ghz) +{ + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + + if (chain >= 0 && chain < AR9300_MAX_CHAINS) { + if (is2ghz) + return eep->modalHeader2G.antCtrlChain[chain]; + else + return eep->modalHeader5G.antCtrlChain[chain]; + } + + return 0; +} + +static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) +{ + u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); + REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value); + + value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); + REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); + + value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz); + REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value); + + value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz); + REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value); + + value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz); + REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value); +} + +static void ar9003_hw_drive_strength_apply(struct ath_hw *ah) +{ + int drive_strength; + unsigned long reg; + + drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH); + + if (!drive_strength) + return; + + reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS1); + reg &= ~0x00ffffc0; + reg |= 0x5 << 21; + reg |= 0x5 << 18; + reg |= 0x5 << 15; + reg |= 0x5 << 12; + reg |= 0x5 << 9; + reg |= 0x5 << 6; + REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg); + + reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS2); + reg &= ~0xffffffe0; + reg |= 0x5 << 29; + reg |= 0x5 << 26; + reg |= 0x5 << 23; + reg |= 0x5 << 20; + reg |= 0x5 << 17; + reg |= 0x5 << 14; + reg |= 0x5 << 11; + reg |= 0x5 << 8; + reg |= 0x5 << 5; + REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg); + + reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS4); + reg &= ~0xff800000; + reg |= 0x5 << 29; + reg |= 0x5 << 26; + reg |= 0x5 << 23; + REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg); +} + +static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah) +{ + int internal_regulator = + ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR); + + if (internal_regulator) { + /* Internal regulator is ON. Write swreg register. */ + int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG); + REG_WRITE(ah, AR_RTC_REG_CONTROL1, + REG_READ(ah, AR_RTC_REG_CONTROL1) & + (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM)); + REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg); + /* Set REG_CONTROL1.SWREG_PROGRAM */ + REG_WRITE(ah, AR_RTC_REG_CONTROL1, + REG_READ(ah, + AR_RTC_REG_CONTROL1) | + AR_RTC_REG_CONTROL1_SWREG_PROGRAM); + } else { + REG_WRITE(ah, AR_RTC_SLEEP_CLK, + (REG_READ(ah, + AR_RTC_SLEEP_CLK) | + AR_RTC_FORCE_SWREG_PRD)); + } +} + +static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan)); + ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan)); + ar9003_hw_drive_strength_apply(ah); + ar9003_hw_internal_regulator_apply(ah); +} + +static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah, + struct ath9k_channel *chan) +{ +} + +/* + * Returns the interpolated y value corresponding to the specified x value + * from the np ordered pairs of data (px,py). + * The pairs do not have to be in any order. + * If the specified x value is less than any of the px, + * the returned y value is equal to the py for the lowest px. + * If the specified x value is greater than any of the px, + * the returned y value is equal to the py for the highest px. + */ +static int ar9003_hw_power_interpolate(int32_t x, + int32_t *px, int32_t *py, u_int16_t np) +{ + int ip = 0; + int lx = 0, ly = 0, lhave = 0; + int hx = 0, hy = 0, hhave = 0; + int dx = 0; + int y = 0; + + lhave = 0; + hhave = 0; + + /* identify best lower and higher x calibration measurement */ + for (ip = 0; ip < np; ip++) { + dx = x - px[ip]; + + /* this measurement is higher than our desired x */ + if (dx <= 0) { + if (!hhave || dx > (x - hx)) { + /* new best higher x measurement */ + hx = px[ip]; + hy = py[ip]; + hhave = 1; + } + } + /* this measurement is lower than our desired x */ + if (dx >= 0) { + if (!lhave || dx < (x - lx)) { + /* new best lower x measurement */ + lx = px[ip]; + ly = py[ip]; + lhave = 1; + } + } + } + + /* the low x is good */ + if (lhave) { + /* so is the high x */ + if (hhave) { + /* they're the same, so just pick one */ + if (hx == lx) + y = ly; + else /* interpolate */ + y = ly + (((x - lx) * (hy - ly)) / (hx - lx)); + } else /* only low is good, use it */ + y = ly; + } else if (hhave) /* only high is good, use it */ + y = hy; + else /* nothing is good,this should never happen unless np=0, ???? */ + y = -(1 << 30); + return y; +} + +static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah, + u16 rateIndex, u16 freq, bool is2GHz) +{ + u16 numPiers, i; + s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS]; + s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS]; + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + struct cal_tgt_pow_legacy *pEepromTargetPwr; + u8 *pFreqBin; + + if (is2GHz) { + numPiers = AR9300_NUM_5G_20_TARGET_POWERS; + pEepromTargetPwr = eep->calTargetPower2G; + pFreqBin = eep->calTarget_freqbin_2G; + } else { + numPiers = AR9300_NUM_5G_20_TARGET_POWERS; + pEepromTargetPwr = eep->calTargetPower5G; + pFreqBin = eep->calTarget_freqbin_5G; + } + + /* + * create array of channels and targetpower from + * targetpower piers stored on eeprom + */ + for (i = 0; i < numPiers; i++) { + freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz); + targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; + } + + /* interpolate to get target power for given frequency */ + return (u8) ar9003_hw_power_interpolate((s32) freq, + freqArray, + targetPowerArray, numPiers); +} + +static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah, + u16 rateIndex, + u16 freq, bool is2GHz) +{ + u16 numPiers, i; + s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS]; + s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS]; + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + struct cal_tgt_pow_ht *pEepromTargetPwr; + u8 *pFreqBin; + + if (is2GHz) { + numPiers = AR9300_NUM_5G_20_TARGET_POWERS; + pEepromTargetPwr = eep->calTargetPower2GHT20; + pFreqBin = eep->calTarget_freqbin_2GHT20; + } else { + numPiers = AR9300_NUM_5G_20_TARGET_POWERS; + pEepromTargetPwr = eep->calTargetPower5GHT20; + pFreqBin = eep->calTarget_freqbin_5GHT20; + } + + /* + * create array of channels and targetpower + * from targetpower piers stored on eeprom + */ + for (i = 0; i < numPiers; i++) { + freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz); + targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; + } + + /* interpolate to get target power for given frequency */ + return (u8) ar9003_hw_power_interpolate((s32) freq, + freqArray, + targetPowerArray, numPiers); +} + +static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah, + u16 rateIndex, + u16 freq, bool is2GHz) +{ + u16 numPiers, i; + s32 targetPowerArray[AR9300_NUM_5G_40_TARGET_POWERS]; + s32 freqArray[AR9300_NUM_5G_40_TARGET_POWERS]; + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + struct cal_tgt_pow_ht *pEepromTargetPwr; + u8 *pFreqBin; + + if (is2GHz) { + numPiers = AR9300_NUM_2G_40_TARGET_POWERS; + pEepromTargetPwr = eep->calTargetPower2GHT40; + pFreqBin = eep->calTarget_freqbin_2GHT40; + } else { + numPiers = AR9300_NUM_5G_40_TARGET_POWERS; + pEepromTargetPwr = eep->calTargetPower5GHT40; + pFreqBin = eep->calTarget_freqbin_5GHT40; + } + + /* + * create array of channels and targetpower from + * targetpower piers stored on eeprom + */ + for (i = 0; i < numPiers; i++) { + freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz); + targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; + } + + /* interpolate to get target power for given frequency */ + return (u8) ar9003_hw_power_interpolate((s32) freq, + freqArray, + targetPowerArray, numPiers); +} + +static u8 ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw *ah, + u16 rateIndex, u16 freq) +{ + u16 numPiers = AR9300_NUM_2G_CCK_TARGET_POWERS, i; + s32 targetPowerArray[AR9300_NUM_2G_CCK_TARGET_POWERS]; + s32 freqArray[AR9300_NUM_2G_CCK_TARGET_POWERS]; + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + struct cal_tgt_pow_legacy *pEepromTargetPwr = eep->calTargetPowerCck; + u8 *pFreqBin = eep->calTarget_freqbin_Cck; + + /* + * create array of channels and targetpower from + * targetpower piers stored on eeprom + */ + for (i = 0; i < numPiers; i++) { + freqArray[i] = FBIN2FREQ(pFreqBin[i], 1); + targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; + } + + /* interpolate to get target power for given frequency */ + return (u8) ar9003_hw_power_interpolate((s32) freq, + freqArray, + targetPowerArray, numPiers); +} + +/* Set tx power registers to array of values passed in */ +static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) +{ +#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) + /* make sure forced gain is not set */ + REG_WRITE(ah, 0xa458, 0); + + /* Write the OFDM power per rate set */ + + /* 6 (LSB), 9, 12, 18 (MSB) */ + REG_WRITE(ah, 0xa3c0, + POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) | + POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) | + POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) | + POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0)); + + /* 24 (LSB), 36, 48, 54 (MSB) */ + REG_WRITE(ah, 0xa3c4, + POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) | + POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) | + POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) | + POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0)); + + /* Write the CCK power per rate set */ + + /* 1L (LSB), reserved, 2L, 2S (MSB) */ + REG_WRITE(ah, 0xa3c8, + POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) | + POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) | + /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */ + POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)); + + /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */ + REG_WRITE(ah, 0xa3cc, + POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) | + POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) | + POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) | + POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0) + ); + + /* Write the HT20 power per rate set */ + + /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ + REG_WRITE(ah, 0xa3d0, + POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) | + POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) | + POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) | + POW_SM(pPwrArray[ALL_TARGET_HT20_0_8_16], 0) + ); + + /* 6 (LSB), 7, 12, 13 (MSB) */ + REG_WRITE(ah, 0xa3d4, + POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) | + POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) | + POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) | + POW_SM(pPwrArray[ALL_TARGET_HT20_6], 0) + ); + + /* 14 (LSB), 15, 20, 21 */ + REG_WRITE(ah, 0xa3e4, + POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) | + POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) | + POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) | + POW_SM(pPwrArray[ALL_TARGET_HT20_14], 0) + ); + + /* Mixed HT20 and HT40 rates */ + + /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */ + REG_WRITE(ah, 0xa3e8, + POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) | + POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) | + POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) | + POW_SM(pPwrArray[ALL_TARGET_HT20_22], 0) + ); + + /* + * Write the HT40 power per rate set + * correct PAR difference between HT40 and HT20/LEGACY + * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) + */ + REG_WRITE(ah, 0xa3d8, + POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) | + POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) | + POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) | + POW_SM(pPwrArray[ALL_TARGET_HT40_0_8_16], 0) + ); + + /* 6 (LSB), 7, 12, 13 (MSB) */ + REG_WRITE(ah, 0xa3dc, + POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) | + POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) | + POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) | + POW_SM(pPwrArray[ALL_TARGET_HT40_6], 0) + ); + + /* 14 (LSB), 15, 20, 21 */ + REG_WRITE(ah, 0xa3ec, + POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) | + POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) | + POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) | + POW_SM(pPwrArray[ALL_TARGET_HT40_14], 0) + ); + + return 0; +#undef POW_SM +} + +static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq) +{ + u8 targetPowerValT2[ar9300RateSize]; + /* XXX: hard code for now, need to get from eeprom struct */ + u8 ht40PowerIncForPdadc = 0; + bool is2GHz = false; + unsigned int i = 0; + struct ath_common *common = ath9k_hw_common(ah); + + if (freq < 4000) + is2GHz = true; + + targetPowerValT2[ALL_TARGET_LEGACY_6_24] = + ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_6_24, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_LEGACY_36] = + ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_36, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_LEGACY_48] = + ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_48, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_LEGACY_54] = + ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_54, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_LEGACY_1L_5L] = + ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_1L_5L, + freq); + targetPowerValT2[ALL_TARGET_LEGACY_5S] = + ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_5S, freq); + targetPowerValT2[ALL_TARGET_LEGACY_11L] = + ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11L, freq); + targetPowerValT2[ALL_TARGET_LEGACY_11S] = + ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11S, freq); + targetPowerValT2[ALL_TARGET_HT20_0_8_16] = + ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_HT20_1_3_9_11_17_19] = + ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19, + freq, is2GHz); + targetPowerValT2[ALL_TARGET_HT20_4] = + ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_4, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_HT20_5] = + ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_5, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_HT20_6] = + ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_6, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_HT20_7] = + ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_7, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_HT20_12] = + ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_12, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_HT20_13] = + ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_13, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_HT20_14] = + ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_14, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_HT20_15] = + ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_15, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_HT20_20] = + ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_20, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_HT20_21] = + ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_21, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_HT20_22] = + ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_22, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_HT20_23] = + ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_23, freq, + is2GHz); + targetPowerValT2[ALL_TARGET_HT40_0_8_16] = + ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq, + is2GHz) + ht40PowerIncForPdadc; + targetPowerValT2[ALL_TARGET_HT40_1_3_9_11_17_19] = + ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19, + freq, + is2GHz) + ht40PowerIncForPdadc; + targetPowerValT2[ALL_TARGET_HT40_4] = + ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_4, freq, + is2GHz) + ht40PowerIncForPdadc; + targetPowerValT2[ALL_TARGET_HT40_5] = + ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_5, freq, + is2GHz) + ht40PowerIncForPdadc; + targetPowerValT2[ALL_TARGET_HT40_6] = + ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_6, freq, + is2GHz) + ht40PowerIncForPdadc; + targetPowerValT2[ALL_TARGET_HT40_7] = + ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_7, freq, + is2GHz) + ht40PowerIncForPdadc; + targetPowerValT2[ALL_TARGET_HT40_12] = + ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_12, freq, + is2GHz) + ht40PowerIncForPdadc; + targetPowerValT2[ALL_TARGET_HT40_13] = + ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_13, freq, + is2GHz) + ht40PowerIncForPdadc; + targetPowerValT2[ALL_TARGET_HT40_14] = + ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_14, freq, + is2GHz) + ht40PowerIncForPdadc; + targetPowerValT2[ALL_TARGET_HT40_15] = + ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_15, freq, + is2GHz) + ht40PowerIncForPdadc; + targetPowerValT2[ALL_TARGET_HT40_20] = + ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_20, freq, + is2GHz) + ht40PowerIncForPdadc; + targetPowerValT2[ALL_TARGET_HT40_21] = + ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_21, freq, + is2GHz) + ht40PowerIncForPdadc; + targetPowerValT2[ALL_TARGET_HT40_22] = + ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_22, freq, + is2GHz) + ht40PowerIncForPdadc; + targetPowerValT2[ALL_TARGET_HT40_23] = + ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq, + is2GHz) + ht40PowerIncForPdadc; + + while (i < ar9300RateSize) { + ath_print(common, ATH_DBG_EEPROM, + "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); + i++; + + ath_print(common, ATH_DBG_EEPROM, + "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); + i++; + + ath_print(common, ATH_DBG_EEPROM, + "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); + i++; + + ath_print(common, ATH_DBG_EEPROM, + "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); + i++; + } + + /* Write target power array to registers */ + ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); +} + +static int ar9003_hw_cal_pier_get(struct ath_hw *ah, + int mode, + int ipier, + int ichain, + int *pfrequency, + int *pcorrection, + int *ptemperature, int *pvoltage) +{ + u8 *pCalPier; + struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct; + int is2GHz; + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + struct ath_common *common = ath9k_hw_common(ah); + + if (ichain >= AR9300_MAX_CHAINS) { + ath_print(common, ATH_DBG_EEPROM, + "Invalid chain index, must be less than %d\n", + AR9300_MAX_CHAINS); + return -1; + } + + if (mode) { /* 5GHz */ + if (ipier >= AR9300_NUM_5G_CAL_PIERS) { + ath_print(common, ATH_DBG_EEPROM, + "Invalid 5GHz cal pier index, must " + "be less than %d\n", + AR9300_NUM_5G_CAL_PIERS); + return -1; + } + pCalPier = &(eep->calFreqPier5G[ipier]); + pCalPierStruct = &(eep->calPierData5G[ichain][ipier]); + is2GHz = 0; + } else { + if (ipier >= AR9300_NUM_2G_CAL_PIERS) { + ath_print(common, ATH_DBG_EEPROM, + "Invalid 2GHz cal pier index, must " + "be less than %d\n", AR9300_NUM_2G_CAL_PIERS); + return -1; + } + + pCalPier = &(eep->calFreqPier2G[ipier]); + pCalPierStruct = &(eep->calPierData2G[ichain][ipier]); + is2GHz = 1; + } + + *pfrequency = FBIN2FREQ(*pCalPier, is2GHz); + *pcorrection = pCalPierStruct->refPower; + *ptemperature = pCalPierStruct->tempMeas; + *pvoltage = pCalPierStruct->voltMeas; + + return 0; +} + +static int ar9003_hw_power_control_override(struct ath_hw *ah, + int frequency, + int *correction, + int *voltage, int *temperature) +{ + int tempSlope = 0; + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + + REG_RMW(ah, AR_PHY_TPC_11_B0, + (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), + AR_PHY_TPC_OLPC_GAIN_DELTA); + REG_RMW(ah, AR_PHY_TPC_11_B1, + (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), + AR_PHY_TPC_OLPC_GAIN_DELTA); + REG_RMW(ah, AR_PHY_TPC_11_B2, + (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), + AR_PHY_TPC_OLPC_GAIN_DELTA); + + /* enable open loop power control on chip */ + REG_RMW(ah, AR_PHY_TPC_6_B0, + (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), + AR_PHY_TPC_6_ERROR_EST_MODE); + REG_RMW(ah, AR_PHY_TPC_6_B1, + (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), + AR_PHY_TPC_6_ERROR_EST_MODE); + REG_RMW(ah, AR_PHY_TPC_6_B2, + (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), + AR_PHY_TPC_6_ERROR_EST_MODE); + + /* + * enable temperature compensation + * Need to use register names + */ + if (frequency < 4000) + tempSlope = eep->modalHeader2G.tempSlope; + else + tempSlope = eep->modalHeader5G.tempSlope; + + REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope); + REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE, + temperature[0]); + + return 0; +} + +/* Apply the recorded correction values. */ +static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) +{ + int ichain, ipier, npier; + int mode; + int lfrequency[AR9300_MAX_CHAINS], + lcorrection[AR9300_MAX_CHAINS], + ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS]; + int hfrequency[AR9300_MAX_CHAINS], + hcorrection[AR9300_MAX_CHAINS], + htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS]; + int fdiff; + int correction[AR9300_MAX_CHAINS], + voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS]; + int pfrequency, pcorrection, ptemperature, pvoltage; + struct ath_common *common = ath9k_hw_common(ah); + + mode = (frequency >= 4000); + if (mode) + npier = AR9300_NUM_5G_CAL_PIERS; + else + npier = AR9300_NUM_2G_CAL_PIERS; + + for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { + lfrequency[ichain] = 0; + hfrequency[ichain] = 100000; + } + /* identify best lower and higher frequency calibration measurement */ + for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { + for (ipier = 0; ipier < npier; ipier++) { + if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain, + &pfrequency, &pcorrection, + &ptemperature, &pvoltage)) { + fdiff = frequency - pfrequency; + + /* + * this measurement is higher than + * our desired frequency + */ + if (fdiff <= 0) { + if (hfrequency[ichain] <= 0 || + hfrequency[ichain] >= 100000 || + fdiff > + (frequency - hfrequency[ichain])) { + /* + * new best higher + * frequency measurement + */ + hfrequency[ichain] = pfrequency; + hcorrection[ichain] = + pcorrection; + htemperature[ichain] = + ptemperature; + hvoltage[ichain] = pvoltage; + } + } + if (fdiff >= 0) { + if (lfrequency[ichain] <= 0 + || fdiff < + (frequency - lfrequency[ichain])) { + /* + * new best lower + * frequency measurement + */ + lfrequency[ichain] = pfrequency; + lcorrection[ichain] = + pcorrection; + ltemperature[ichain] = + ptemperature; + lvoltage[ichain] = pvoltage; + } + } + } + } + } + + /* interpolate */ + for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { + ath_print(common, ATH_DBG_EEPROM, + "ch=%d f=%d low=%d %d h=%d %d\n", + ichain, frequency, lfrequency[ichain], + lcorrection[ichain], hfrequency[ichain], + hcorrection[ichain]); + /* they're the same, so just pick one */ + if (hfrequency[ichain] == lfrequency[ichain]) { + correction[ichain] = lcorrection[ichain]; + voltage[ichain] = lvoltage[ichain]; + temperature[ichain] = ltemperature[ichain]; + } + /* the low frequency is good */ + else if (frequency - lfrequency[ichain] < 1000) { + /* so is the high frequency, interpolate */ + if (hfrequency[ichain] - frequency < 1000) { + + correction[ichain] = lcorrection[ichain] + + (((frequency - lfrequency[ichain]) * + (hcorrection[ichain] - + lcorrection[ichain])) / + (hfrequency[ichain] - lfrequency[ichain])); + + temperature[ichain] = ltemperature[ichain] + + (((frequency - lfrequency[ichain]) * + (htemperature[ichain] - + ltemperature[ichain])) / + (hfrequency[ichain] - lfrequency[ichain])); + + voltage[ichain] = + lvoltage[ichain] + + (((frequency - + lfrequency[ichain]) * (hvoltage[ichain] - + lvoltage[ichain])) + / (hfrequency[ichain] - + lfrequency[ichain])); + } + /* only low is good, use it */ + else { + correction[ichain] = lcorrection[ichain]; + temperature[ichain] = ltemperature[ichain]; + voltage[ichain] = lvoltage[ichain]; + } + } + /* only high is good, use it */ + else if (hfrequency[ichain] - frequency < 1000) { + correction[ichain] = hcorrection[ichain]; + temperature[ichain] = htemperature[ichain]; + voltage[ichain] = hvoltage[ichain]; + } else { /* nothing is good, presume 0???? */ + correction[ichain] = 0; + temperature[ichain] = 0; + voltage[ichain] = 0; + } + } + + ar9003_hw_power_control_override(ah, frequency, correction, voltage, + temperature); + + ath_print(common, ATH_DBG_EEPROM, + "for frequency=%d, calibration correction = %d %d %d\n", + frequency, correction[0], correction[1], correction[2]); + + return 0; +} + +static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, + struct ath9k_channel *chan, u16 cfgCtl, + u8 twiceAntennaReduction, + u8 twiceMaxRegulatoryPower, + u8 powerLimit) +{ + ar9003_hw_set_target_power_eeprom(ah, chan->channel); + ar9003_hw_calibration_apply(ah, chan->channel); +} + +static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah, + u16 i, bool is2GHz) +{ + return AR_NO_SPUR; +} + +const struct eeprom_ops eep_ar9300_ops = { + .check_eeprom = ath9k_hw_ar9300_check_eeprom, + .get_eeprom = ath9k_hw_ar9300_get_eeprom, + .fill_eeprom = ath9k_hw_ar9300_fill_eeprom, + .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver, + .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev, + .get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config, + .get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg, + .set_board_values = ath9k_hw_ar9300_set_board_values, + .set_addac = ath9k_hw_ar9300_set_addac, + .set_txpower = ath9k_hw_ar9300_set_txpower, + .get_spur_channel = ath9k_hw_ar9300_get_spur_channel +}; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h new file mode 100644 index 000000000000..3ca520c4b6a3 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -0,0 +1,319 @@ +#ifndef AR9003_EEPROM_H +#define AR9003_EEPROM_H + +#include + +#define AR9300_EEP_VER 0xD000 +#define AR9300_EEP_VER_MINOR_MASK 0xFFF +#define AR9300_EEP_MINOR_VER_1 0x1 +#define AR9300_EEP_MINOR_VER AR9300_EEP_MINOR_VER_1 + +/* 16-bit offset location start of calibration struct */ +#define AR9300_EEP_START_LOC 256 +#define AR9300_NUM_5G_CAL_PIERS 8 +#define AR9300_NUM_2G_CAL_PIERS 3 +#define AR9300_NUM_5G_20_TARGET_POWERS 8 +#define AR9300_NUM_5G_40_TARGET_POWERS 8 +#define AR9300_NUM_2G_CCK_TARGET_POWERS 2 +#define AR9300_NUM_2G_20_TARGET_POWERS 3 +#define AR9300_NUM_2G_40_TARGET_POWERS 3 +/* #define AR9300_NUM_CTLS 21 */ +#define AR9300_NUM_CTLS_5G 9 +#define AR9300_NUM_CTLS_2G 12 +#define AR9300_CTL_MODE_M 0xF +#define AR9300_NUM_BAND_EDGES_5G 8 +#define AR9300_NUM_BAND_EDGES_2G 4 +#define AR9300_NUM_PD_GAINS 4 +#define AR9300_PD_GAINS_IN_MASK 4 +#define AR9300_PD_GAIN_ICEPTS 5 +#define AR9300_EEPROM_MODAL_SPURS 5 +#define AR9300_MAX_RATE_POWER 63 +#define AR9300_NUM_PDADC_VALUES 128 +#define AR9300_NUM_RATES 16 +#define AR9300_BCHAN_UNUSED 0xFF +#define AR9300_MAX_PWR_RANGE_IN_HALF_DB 64 +#define AR9300_OPFLAGS_11A 0x01 +#define AR9300_OPFLAGS_11G 0x02 +#define AR9300_OPFLAGS_5G_HT40 0x04 +#define AR9300_OPFLAGS_2G_HT40 0x08 +#define AR9300_OPFLAGS_5G_HT20 0x10 +#define AR9300_OPFLAGS_2G_HT20 0x20 +#define AR9300_EEPMISC_BIG_ENDIAN 0x01 +#define AR9300_EEPMISC_WOW 0x02 +#define AR9300_CUSTOMER_DATA_SIZE 20 + +#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) +#define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x)) +#define AR9300_MAX_CHAINS 3 +#define AR9300_ANT_16S 25 +#define AR9300_FUTURE_MODAL_SZ 6 + +#define AR9300_NUM_ANT_CHAIN_FIELDS 7 +#define AR9300_NUM_ANT_COMMON_FIELDS 4 +#define AR9300_SIZE_ANT_CHAIN_FIELD 3 +#define AR9300_SIZE_ANT_COMMON_FIELD 4 +#define AR9300_ANT_CHAIN_MASK 0x7 +#define AR9300_ANT_COMMON_MASK 0xf +#define AR9300_CHAIN_0_IDX 0 +#define AR9300_CHAIN_1_IDX 1 +#define AR9300_CHAIN_2_IDX 2 + +#define AR928X_NUM_ANT_CHAIN_FIELDS 6 +#define AR928X_SIZE_ANT_CHAIN_FIELD 2 +#define AR928X_ANT_CHAIN_MASK 0x3 + +/* Delta from which to start power to pdadc table */ +/* This offset is used in both open loop and closed loop power control + * schemes. In open loop power control, it is not really needed, but for + * the "sake of consistency" it was kept. For certain AP designs, this + * value is overwritten by the value in the flag "pwrTableOffset" just + * before writing the pdadc vs pwr into the chip registers. + */ +#define AR9300_PWR_TABLE_OFFSET 0 + +/* enable flags for voltage and temp compensation */ +#define ENABLE_TEMP_COMPENSATION 0x01 +#define ENABLE_VOLT_COMPENSATION 0x02 +/* byte addressable */ +#define AR9300_EEPROM_SIZE (16*1024) +#define FIXED_CCA_THRESHOLD 15 + +#define AR9300_BASE_ADDR 0x3ff + +enum targetPowerHTRates { + HT_TARGET_RATE_0_8_16, + HT_TARGET_RATE_1_3_9_11_17_19, + HT_TARGET_RATE_4, + HT_TARGET_RATE_5, + HT_TARGET_RATE_6, + HT_TARGET_RATE_7, + HT_TARGET_RATE_12, + HT_TARGET_RATE_13, + HT_TARGET_RATE_14, + HT_TARGET_RATE_15, + HT_TARGET_RATE_20, + HT_TARGET_RATE_21, + HT_TARGET_RATE_22, + HT_TARGET_RATE_23 +}; + +enum targetPowerLegacyRates { + LEGACY_TARGET_RATE_6_24, + LEGACY_TARGET_RATE_36, + LEGACY_TARGET_RATE_48, + LEGACY_TARGET_RATE_54 +}; + +enum targetPowerCckRates { + LEGACY_TARGET_RATE_1L_5L, + LEGACY_TARGET_RATE_5S, + LEGACY_TARGET_RATE_11L, + LEGACY_TARGET_RATE_11S +}; + +enum ar9300_Rates { + ALL_TARGET_LEGACY_6_24, + ALL_TARGET_LEGACY_36, + ALL_TARGET_LEGACY_48, + ALL_TARGET_LEGACY_54, + ALL_TARGET_LEGACY_1L_5L, + ALL_TARGET_LEGACY_5S, + ALL_TARGET_LEGACY_11L, + ALL_TARGET_LEGACY_11S, + ALL_TARGET_HT20_0_8_16, + ALL_TARGET_HT20_1_3_9_11_17_19, + ALL_TARGET_HT20_4, + ALL_TARGET_HT20_5, + ALL_TARGET_HT20_6, + ALL_TARGET_HT20_7, + ALL_TARGET_HT20_12, + ALL_TARGET_HT20_13, + ALL_TARGET_HT20_14, + ALL_TARGET_HT20_15, + ALL_TARGET_HT20_20, + ALL_TARGET_HT20_21, + ALL_TARGET_HT20_22, + ALL_TARGET_HT20_23, + ALL_TARGET_HT40_0_8_16, + ALL_TARGET_HT40_1_3_9_11_17_19, + ALL_TARGET_HT40_4, + ALL_TARGET_HT40_5, + ALL_TARGET_HT40_6, + ALL_TARGET_HT40_7, + ALL_TARGET_HT40_12, + ALL_TARGET_HT40_13, + ALL_TARGET_HT40_14, + ALL_TARGET_HT40_15, + ALL_TARGET_HT40_20, + ALL_TARGET_HT40_21, + ALL_TARGET_HT40_22, + ALL_TARGET_HT40_23, + ar9300RateSize, +}; + + +struct eepFlags { + u8 opFlags; + u8 eepMisc; +} __packed; + +enum CompressAlgorithm { + _CompressNone = 0, + _CompressLzma, + _CompressPairs, + _CompressBlock, + _Compress4, + _Compress5, + _Compress6, + _Compress7, +}; + +struct ar9300_base_eep_hdr { + u16 regDmn[2]; + /* 4 bits tx and 4 bits rx */ + u8 txrxMask; + struct eepFlags opCapFlags; + u8 rfSilent; + u8 blueToothOptions; + u8 deviceCap; + /* takes lower byte in eeprom location */ + u8 deviceType; + /* offset in dB to be added to beginning + * of pdadc table in calibration + */ + int8_t pwrTableOffset; + u8 params_for_tuning_caps[2]; + /* + * bit0 - enable tx temp comp + * bit1 - enable tx volt comp + * bit2 - enable fastClock - default to 1 + * bit3 - enable doubling - default to 1 + * bit4 - enable internal regulator - default to 1 + */ + u8 featureEnable; + /* misc flags: bit0 - turn down drivestrength */ + u8 miscConfiguration; + u8 eepromWriteEnableGpio; + u8 wlanDisableGpio; + u8 wlanLedGpio; + u8 rxBandSelectGpio; + u8 txrxgain; + /* SW controlled internal regulator fields */ + u32 swreg; +} __packed; + +struct ar9300_modal_eep_header { + /* 4 idle, t1, t2, b (4 bits per setting) */ + u32 antCtrlCommon; + /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ + u32 antCtrlCommon2; + /* 6 idle, t, r, rx1, rx12, b (2 bits each) */ + u16 antCtrlChain[AR9300_MAX_CHAINS]; + /* 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ + u8 xatten1DB[AR9300_MAX_CHAINS]; + /* 3 xatten1_margin for merlin (0xa20c/b20c 16:12 */ + u8 xatten1Margin[AR9300_MAX_CHAINS]; + int8_t tempSlope; + int8_t voltSlope; + /* spur channels in usual fbin coding format */ + u8 spurChans[AR9300_EEPROM_MODAL_SPURS]; + /* 3 Check if the register is per chain */ + int8_t noiseFloorThreshCh[AR9300_MAX_CHAINS]; + u8 ob[AR9300_MAX_CHAINS]; + u8 db_stage2[AR9300_MAX_CHAINS]; + u8 db_stage3[AR9300_MAX_CHAINS]; + u8 db_stage4[AR9300_MAX_CHAINS]; + u8 xpaBiasLvl; + u8 txFrameToDataStart; + u8 txFrameToPaOn; + u8 txClip; + int8_t antennaGain; + u8 switchSettling; + int8_t adcDesiredSize; + u8 txEndToXpaOff; + u8 txEndToRxOn; + u8 txFrameToXpaOn; + u8 thresh62; + u8 futureModal[32]; +} __packed; + +struct ar9300_cal_data_per_freq_op_loop { + int8_t refPower; + /* pdadc voltage at power measurement */ + u8 voltMeas; + /* pcdac used for power measurement */ + u8 tempMeas; + /* range is -60 to -127 create a mapping equation 1db resolution */ + int8_t rxNoisefloorCal; + /*range is same as noisefloor */ + int8_t rxNoisefloorPower; + /* temp measured when noisefloor cal was performed */ + u8 rxTempMeas; +} __packed; + +struct cal_tgt_pow_legacy { + u8 tPow2x[4]; +} __packed; + +struct cal_tgt_pow_ht { + u8 tPow2x[14]; +} __packed; + +struct cal_ctl_edge_pwr { + u8 tPower:6, + flag:2; +} __packed; + +struct cal_ctl_data_2g { + struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_5G]; +} __packed; + +struct cal_ctl_data_5g { + struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_5G]; +} __packed; + +struct ar9300_eeprom { + u8 eepromVersion; + u8 templateVersion; + u8 macAddr[6]; + u8 custData[AR9300_CUSTOMER_DATA_SIZE]; + + struct ar9300_base_eep_hdr baseEepHeader; + + struct ar9300_modal_eep_header modalHeader2G; + u8 calFreqPier2G[AR9300_NUM_2G_CAL_PIERS]; + struct ar9300_cal_data_per_freq_op_loop + calPierData2G[AR9300_MAX_CHAINS][AR9300_NUM_2G_CAL_PIERS]; + u8 calTarget_freqbin_Cck[AR9300_NUM_2G_CCK_TARGET_POWERS]; + u8 calTarget_freqbin_2G[AR9300_NUM_2G_20_TARGET_POWERS]; + u8 calTarget_freqbin_2GHT20[AR9300_NUM_2G_20_TARGET_POWERS]; + u8 calTarget_freqbin_2GHT40[AR9300_NUM_2G_40_TARGET_POWERS]; + struct cal_tgt_pow_legacy + calTargetPowerCck[AR9300_NUM_2G_CCK_TARGET_POWERS]; + struct cal_tgt_pow_legacy + calTargetPower2G[AR9300_NUM_2G_20_TARGET_POWERS]; + struct cal_tgt_pow_ht + calTargetPower2GHT20[AR9300_NUM_2G_20_TARGET_POWERS]; + struct cal_tgt_pow_ht + calTargetPower2GHT40[AR9300_NUM_2G_40_TARGET_POWERS]; + u8 ctlIndex_2G[AR9300_NUM_CTLS_2G]; + u8 ctl_freqbin_2G[AR9300_NUM_CTLS_2G][AR9300_NUM_BAND_EDGES_2G]; + struct cal_ctl_data_2g ctlPowerData_2G[AR9300_NUM_CTLS_2G]; + struct ar9300_modal_eep_header modalHeader5G; + u8 calFreqPier5G[AR9300_NUM_5G_CAL_PIERS]; + struct ar9300_cal_data_per_freq_op_loop + calPierData5G[AR9300_MAX_CHAINS][AR9300_NUM_5G_CAL_PIERS]; + u8 calTarget_freqbin_5G[AR9300_NUM_5G_20_TARGET_POWERS]; + u8 calTarget_freqbin_5GHT20[AR9300_NUM_5G_20_TARGET_POWERS]; + u8 calTarget_freqbin_5GHT40[AR9300_NUM_5G_40_TARGET_POWERS]; + struct cal_tgt_pow_legacy + calTargetPower5G[AR9300_NUM_5G_20_TARGET_POWERS]; + struct cal_tgt_pow_ht + calTargetPower5GHT20[AR9300_NUM_5G_20_TARGET_POWERS]; + struct cal_tgt_pow_ht + calTargetPower5GHT40[AR9300_NUM_5G_40_TARGET_POWERS]; + u8 ctlIndex_5G[AR9300_NUM_CTLS_5G]; + u8 ctl_freqbin_5G[AR9300_NUM_CTLS_5G][AR9300_NUM_BAND_EDGES_5G]; + struct cal_ctl_data_5g ctlPowerData_5G[AR9300_NUM_CTLS_5G]; +} __packed; +#endif diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index aec6ebbb6584..bd9dff3293dc 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -256,7 +256,9 @@ int ath9k_hw_eeprom_init(struct ath_hw *ah) { int status; - if (AR_SREV_9287(ah)) { + if (AR_SREV_9300_20_OR_LATER(ah)) + ah->eep_ops = &eep_ar9300_ops; + else if (AR_SREV_9287(ah)) { ah->eep_ops = &eep_ar9287_ops; } else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) { ah->eep_ops = &eep_4k_ops; diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 289084c71527..fb9c8c92eabe 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -19,6 +19,7 @@ #include "../ath.h" #include +#include "ar9003_eeprom.h" #define AH_USE_EEPROM 0x1 @@ -249,16 +250,20 @@ enum eeprom_param { EEP_MINOR_REV, EEP_TX_MASK, EEP_RX_MASK, + EEP_FSTCLK_5G, EEP_RXGAIN_TYPE, - EEP_TXGAIN_TYPE, EEP_OL_PWRCTRL, + EEP_TXGAIN_TYPE, EEP_RC_CHAIN_MASK, EEP_DAC_HPWR_5G, EEP_FRAC_N_5G, EEP_DEV_TYPE, EEP_TEMPSENSE_SLOPE, EEP_TEMPSENSE_SLOPE_PAL_ON, - EEP_PWR_TABLE_OFFSET + EEP_PWR_TABLE_OFFSET, + EEP_DRIVE_STRENGTH, + EEP_INTERNAL_REGULATOR, + EEP_SWREG }; enum ar5416_rates { @@ -707,5 +712,7 @@ int ath9k_hw_eeprom_init(struct ath_hw *ah); extern const struct eeprom_ops eep_def_ops; extern const struct eeprom_ops eep_4k_ops; extern const struct eeprom_ops eep_ar9287_ops; +extern const struct eeprom_ops eep_ar9287_ops; +extern const struct eeprom_ops eep_ar9300_ops; #endif /* EEPROM_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index cb0421a910d2..d1b9940b2ae5 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -568,6 +568,7 @@ struct ath_hw { struct ar5416_eeprom_def def; struct ar5416_eeprom_4k map4k; struct ar9287_eeprom map9287; + struct ar9300_eeprom ar9300_eep; } eeprom; const struct eeprom_ops *eep_ops; diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index aacc29a5ad71..12de95ea7631 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1070,6 +1070,16 @@ enum { #define AR_RTC_RC_COLD_RESET 0x00000004 #define AR_RTC_RC_WARM_RESET 0x00000008 +/* Crystal Control */ +#define AR_RTC_XTAL_CONTROL 0x7004 + +/* Reg Control 0 */ +#define AR_RTC_REG_CONTROL0 0x7008 + +/* Reg Control 1 */ +#define AR_RTC_REG_CONTROL1 0x700c +#define AR_RTC_REG_CONTROL1_SWREG_PROGRAM 0x00000001 + #define AR_RTC_PLL_CONTROL \ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014) @@ -1100,6 +1110,7 @@ enum { #define AR_RTC_SLEEP_CLK \ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0048) : 0x7048) #define AR_RTC_FORCE_DERIVED_CLK 0x2 +#define AR_RTC_FORCE_SWREG_PRD 0x00000004 #define AR_RTC_FORCE_WAKE \ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x004c) : 0x704c) -- cgit v1.2.3 From 1547da37db9b56eb98eb0f33b84d49ab4e83e01e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:15 -0400 Subject: ath9k_hw: add OFDM spur mitigation for AR9003 We add this now as OFDM spur mitigation required accessing the EEPROM for the AR9003 devices. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_phy.h | 2 - drivers/net/wireless/ath/ath9k/ar9003_phy.c | 210 +++++++++++++++++++++++++++- drivers/net/wireless/ath/ath9k/ar9003_phy.h | 54 +++++++ drivers/net/wireless/ath/ath9k/hw.h | 2 + drivers/net/wireless/ath/ath9k/phy.h | 3 + 5 files changed, 267 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index afe48086250d..81bf6e5840e1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h @@ -289,8 +289,6 @@ #define AR_PHY_TIMING11 0x99a0 #define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF #define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0 -#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 -#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 #define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000 #define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000 diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index fee07fd7a595..137543b2d739 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -103,8 +103,8 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) * * Spur mitigation for MRC CCK */ -static void ar9003_hw_spur_mitigate(struct ath_hw *ah, - struct ath9k_channel *chan) +static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, + struct ath9k_channel *chan) { u32 spur_freq[4] = { 2420, 2440, 2464, 2480 }; int cur_bb_spur, negative = 0, cck_spur_freq; @@ -157,6 +157,212 @@ static void ar9003_hw_spur_mitigate(struct ath_hw *ah, AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, 0x0); } +/* Clean all spur register fields */ +static void ar9003_hw_spur_ofdm_clear(struct ath_hw *ah) +{ + REG_RMW_FIELD(ah, AR_PHY_TIMING4, + AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0); + REG_RMW_FIELD(ah, AR_PHY_TIMING11, + AR_PHY_TIMING11_SPUR_FREQ_SD, 0); + REG_RMW_FIELD(ah, AR_PHY_TIMING11, + AR_PHY_TIMING11_SPUR_DELTA_PHASE, 0); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, 0); + REG_RMW_FIELD(ah, AR_PHY_TIMING11, + AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0); + REG_RMW_FIELD(ah, AR_PHY_TIMING11, + AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0); + REG_RMW_FIELD(ah, AR_PHY_TIMING4, + AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0); + REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, + AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 0); + REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, + AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 0); + + REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, + AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0); + REG_RMW_FIELD(ah, AR_PHY_TIMING4, + AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0); + REG_RMW_FIELD(ah, AR_PHY_TIMING4, + AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0); + REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK, + AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, 0); + REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A, + AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, 0); + REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK, + AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, 0); + REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK, + AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0); + REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK, + AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0); + REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A, + AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0); + REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, + AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0); +} + +static void ar9003_hw_spur_ofdm(struct ath_hw *ah, + int freq_offset, + int spur_freq_sd, + int spur_delta_phase, + int spur_subchannel_sd) +{ + int mask_index = 0; + + /* OFDM Spur mitigation */ + REG_RMW_FIELD(ah, AR_PHY_TIMING4, + AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0x1); + REG_RMW_FIELD(ah, AR_PHY_TIMING11, + AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd); + REG_RMW_FIELD(ah, AR_PHY_TIMING11, + AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, spur_subchannel_sd); + REG_RMW_FIELD(ah, AR_PHY_TIMING11, + AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0x1); + REG_RMW_FIELD(ah, AR_PHY_TIMING11, + AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0x1); + REG_RMW_FIELD(ah, AR_PHY_TIMING4, + AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0x1); + REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, + AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, 34); + REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, + AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 1); + + if (REG_READ_FIELD(ah, AR_PHY_MODE, + AR_PHY_MODE_DYNAMIC) == 0x1) + REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, + AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 1); + + mask_index = (freq_offset << 4) / 5; + if (mask_index < 0) + mask_index = mask_index - 1; + + mask_index = mask_index & 0x7f; + + REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, + AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0x1); + REG_RMW_FIELD(ah, AR_PHY_TIMING4, + AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0x1); + REG_RMW_FIELD(ah, AR_PHY_TIMING4, + AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0x1); + REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK, + AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, mask_index); + REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A, + AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, mask_index); + REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK, + AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, mask_index); + REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK, + AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0xc); + REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK, + AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0xc); + REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A, + AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0xa0); + REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, + AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0xff); +} + +static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah, + struct ath9k_channel *chan, + int freq_offset) +{ + int spur_freq_sd = 0; + int spur_subchannel_sd = 0; + int spur_delta_phase = 0; + + if (IS_CHAN_HT40(chan)) { + if (freq_offset < 0) { + if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, + AR_PHY_GC_DYN2040_PRI_CH) == 0x0) + spur_subchannel_sd = 1; + else + spur_subchannel_sd = 0; + + spur_freq_sd = ((freq_offset + 10) << 9) / 11; + + } else { + if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, + AR_PHY_GC_DYN2040_PRI_CH) == 0x0) + spur_subchannel_sd = 0; + else + spur_subchannel_sd = 1; + + spur_freq_sd = ((freq_offset - 10) << 9) / 11; + + } + + spur_delta_phase = (freq_offset << 17) / 5; + + } else { + spur_subchannel_sd = 0; + spur_freq_sd = (freq_offset << 9) /11; + spur_delta_phase = (freq_offset << 18) / 5; + } + + spur_freq_sd = spur_freq_sd & 0x3ff; + spur_delta_phase = spur_delta_phase & 0xfffff; + + ar9003_hw_spur_ofdm(ah, + freq_offset, + spur_freq_sd, + spur_delta_phase, + spur_subchannel_sd); +} + +/* Spur mitigation for OFDM */ +static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + int synth_freq; + int range = 10; + int freq_offset = 0; + int mode; + u8* spurChansPtr; + unsigned int i; + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + + if (IS_CHAN_5GHZ(chan)) { + spurChansPtr = &(eep->modalHeader5G.spurChans[0]); + mode = 0; + } + else { + spurChansPtr = &(eep->modalHeader2G.spurChans[0]); + mode = 1; + } + + if (spurChansPtr[0] == 0) + return; /* No spur in the mode */ + + if (IS_CHAN_HT40(chan)) { + range = 19; + if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, + AR_PHY_GC_DYN2040_PRI_CH) == 0x0) + synth_freq = chan->channel - 10; + else + synth_freq = chan->channel + 10; + } else { + range = 10; + synth_freq = chan->channel; + } + + ar9003_hw_spur_ofdm_clear(ah); + + for (i = 0; spurChansPtr[i] && i < 5; i++) { + freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq; + if (abs(freq_offset) < range) { + ar9003_hw_spur_ofdm_work(ah, chan, freq_offset); + break; + } + } +} + +static void ar9003_hw_spur_mitigate(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + ar9003_hw_spur_mitigate_mrc_cck(ah, chan); + ar9003_hw_spur_mitigate_ofdm(ah, chan); +} + static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah, struct ath9k_channel *chan) { diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 4e1177dc24ac..f08cc8bda005 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -33,6 +33,30 @@ #define AR_PHY_RX_IQCAL_CORR_B0 (AR_CHAN_BASE + 0xdc) #define AR_PHY_TX_IQCAL_CONTROL_3 (AR_CHAN_BASE + 0xb0) +#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 +#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 + +#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF +#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0 + +#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC 0x40000000 +#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC_S 30 + +#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR 0x80000000 +#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR_S 31 + +#define AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT 0x4000000 +#define AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT_S 26 + +#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000 /* bins move with freq offset */ +#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM_S 17 +#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x000000FF +#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0 +#define AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI 0x00000100 +#define AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI_S 8 +#define AR_PHY_SPUR_REG_MASK_RATE_CNTL 0x03FC0000 +#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18 + #define AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN 0x20000000 #define AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN_S 29 @@ -84,6 +108,17 @@ #define AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX 0xF000 #define AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX_S 12 #define AR_PHY_TIMING4_DO_CAL 0x10000 + +#define AR_PHY_TIMING4_ENABLE_PILOT_MASK 0x10000000 +#define AR_PHY_TIMING4_ENABLE_PILOT_MASK_S 28 +#define AR_PHY_TIMING4_ENABLE_CHAN_MASK 0x20000000 +#define AR_PHY_TIMING4_ENABLE_CHAN_MASK_S 29 + +#define AR_PHY_TIMING4_ENABLE_SPUR_FILTER 0x40000000 +#define AR_PHY_TIMING4_ENABLE_SPUR_FILTER_S 30 +#define AR_PHY_TIMING4_ENABLE_SPUR_RSSI 0x80000000 +#define AR_PHY_TIMING4_ENABLE_SPUR_RSSI_S 31 + #define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 #define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 #define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001 @@ -107,6 +142,8 @@ #define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 #define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000 #define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 +#define AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD 0x10000000 +#define AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD_S 28 #define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 #define AR_PHY_EXT_CCA_THRESH62 0x007F0000 #define AR_PHY_EXT_CCA_THRESH62_S 16 @@ -184,6 +221,16 @@ #define AR_PHY_ML_CNTL_2 (AR_MRC_BASE + 0x1c) #define AR_PHY_TST_ADC (AR_MRC_BASE + 0x20) +#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A 0x00000FE0 +#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A_S 5 +#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A 0x1F +#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A_S 0 + +#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A 0x00000FE0 +#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A_S 5 +#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A 0x1F +#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A_S 0 + /* * MRC Feild Definitions */ @@ -372,6 +419,11 @@ #define AR_PHY_ADDAC_PARA_CTL (AR_SM_BASE + 0x150) #define AR_PHY_XPA_CFG (AR_SM_BASE + 0x158) +#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A 0x0001FC00 +#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A_S 10 +#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A 0x3FF +#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A_S 0 + #define AR_PHY_TEST (AR_SM_BASE + 0x160) #define AR_PHY_TEST_BBB_OBS_SEL 0x780000 @@ -499,6 +551,7 @@ #define AR_PHY_GC_DYN2040_EN 0x00000004 /* enable dyn 20/40 mode */ #define AR_PHY_GC_DYN2040_PRI_ONLY 0x00000008 /* dyn 20/40 - primary only */ #define AR_PHY_GC_DYN2040_PRI_CH 0x00000010 /* dyn 20/40 - primary ch offset (0=+10MHz, 1=-10MHz)*/ +#define AR_PHY_GC_DYN2040_PRI_CH_S 4 #define AR_PHY_GC_DYN2040_EXT_CH 0x00000020 /* dyn 20/40 - ext ch spacing (0=20MHz/ 1=25MHz) */ #define AR_PHY_GC_HT_EN 0x00000040 /* ht enable */ #define AR_PHY_GC_SHORT_GI_40 0x00000080 /* allow short GI for HT 40 */ @@ -516,6 +569,7 @@ #define AR_PHY_MODE_OFDM 0x00000000 #define AR_PHY_MODE_CCK 0x00000001 #define AR_PHY_MODE_DYNAMIC 0x00000004 +#define AR_PHY_MODE_DYNAMIC_S 2 #define AR_PHY_MODE_HALF 0x00000020 #define AR_PHY_MODE_QUARTER 0x00000040 #define AR_PHY_MAC_CLK_MODE 0x00000080 diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index d1b9940b2ae5..25713beb8e71 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -76,6 +76,8 @@ #define REG_RMW_FIELD(_a, _r, _f, _v) \ REG_WRITE(_a, _r, \ (REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f)) +#define REG_READ_FIELD(_a, _r, _f) \ + (((REG_READ(_a, _r) & _f) >> _f##_S)) #define REG_SET_BIT(_a, _r, _f) \ REG_WRITE(_a, _r, REG_READ(_a, _r) | _f) #define REG_CLR_BIT(_a, _r, _f) \ diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 7d397fd7bd18..e724c2c1ae2a 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -59,4 +59,7 @@ (_bank)[i] = INI_RA((_iniarray), i, _col);; \ } while (0) +#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 +#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 + #endif -- cgit v1.2.3 From 6c84ce08aaf5995afc7ff7b4c54069c2431fca87 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:16 -0400 Subject: ath9k_hw: Fill get_isr() for AR9003 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 132 ++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_mac.h | 8 ++ drivers/net/wireless/ath/ath9k/hw.c | 3 + drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/reg.h | 2 + 5 files changed, 146 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 15f1b0f0d070..2319456f2f0e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -32,6 +32,138 @@ static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link) static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) { + u32 isr = 0; + u32 mask2 = 0; + struct ath9k_hw_capabilities *pCap = &ah->caps; + u32 sync_cause = 0; + struct ath_common *common = ath9k_hw_common(ah); + + if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { + if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) + == AR_RTC_STATUS_ON) + isr = REG_READ(ah, AR_ISR); + } + + sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT; + + *masked = 0; + + if (!isr && !sync_cause) + return false; + + if (isr) { + if (isr & AR_ISR_BCNMISC) { + u32 isr2; + isr2 = REG_READ(ah, AR_ISR_S2); + + mask2 |= ((isr2 & AR_ISR_S2_TIM) >> + MAP_ISR_S2_TIM); + mask2 |= ((isr2 & AR_ISR_S2_DTIM) >> + MAP_ISR_S2_DTIM); + mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >> + MAP_ISR_S2_DTIMSYNC); + mask2 |= ((isr2 & AR_ISR_S2_CABEND) >> + MAP_ISR_S2_CABEND); + mask2 |= ((isr2 & AR_ISR_S2_GTT) << + MAP_ISR_S2_GTT); + mask2 |= ((isr2 & AR_ISR_S2_CST) << + MAP_ISR_S2_CST); + mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >> + MAP_ISR_S2_TSFOOR); + + if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { + REG_WRITE(ah, AR_ISR_S2, isr2); + isr &= ~AR_ISR_BCNMISC; + } + } + + if ((pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) + isr = REG_READ(ah, AR_ISR_RAC); + + if (isr == 0xffffffff) { + *masked = 0; + return false; + } + + *masked = isr & ATH9K_INT_COMMON; + + if (ah->config.rx_intr_mitigation) + if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) + *masked |= ATH9K_INT_RXLP; + + if (ah->config.tx_intr_mitigation) + if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM)) + *masked |= ATH9K_INT_TX; + + if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR)) + *masked |= ATH9K_INT_RXLP; + + if (isr & AR_ISR_HP_RXOK) + *masked |= ATH9K_INT_RXHP; + + if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) { + *masked |= ATH9K_INT_TX; + + if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { + u32 s0, s1; + s0 = REG_READ(ah, AR_ISR_S0); + REG_WRITE(ah, AR_ISR_S0, s0); + s1 = REG_READ(ah, AR_ISR_S1); + REG_WRITE(ah, AR_ISR_S1, s1); + + isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR | + AR_ISR_TXEOL); + } + } + + if (isr & AR_ISR_GENTMR) { + u32 s5; + + if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) + s5 = REG_READ(ah, AR_ISR_S5_S); + else + s5 = REG_READ(ah, AR_ISR_S5); + + ah->intr_gen_timer_trigger = + MS(s5, AR_ISR_S5_GENTIMER_TRIG); + + ah->intr_gen_timer_thresh = + MS(s5, AR_ISR_S5_GENTIMER_THRESH); + + if (ah->intr_gen_timer_trigger) + *masked |= ATH9K_INT_GENTIMER; + + if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { + REG_WRITE(ah, AR_ISR_S5, s5); + isr &= ~AR_ISR_GENTMR; + } + + } + + *masked |= mask2; + + if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { + REG_WRITE(ah, AR_ISR, isr); + + (void) REG_READ(ah, AR_ISR); + } + } + + if (sync_cause) { + if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { + REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); + REG_WRITE(ah, AR_RC, 0); + *masked |= ATH9K_INT_FATAL; + } + + if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) + ath_print(common, ATH_DBG_INTERRUPT, + "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); + + REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); + (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); + + } return true; } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index 7374439a836c..2ba06d7674e8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h @@ -22,6 +22,14 @@ #define AR_CtrlStat 0x00004000 #define AR_TxRxDesc 0x00008000 +#define MAP_ISR_S2_CST 6 +#define MAP_ISR_S2_GTT 6 +#define MAP_ISR_S2_TIM 3 +#define MAP_ISR_S2_CABEND 0 +#define MAP_ISR_S2_DTIMSYNC 7 +#define MAP_ISR_S2_DTIM 7 +#define MAP_ISR_S2_TSFOOR 4 + struct ar9003_rxs { u32 ds_info; u32 status1; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 01706d9cfc56..2a04251d6063 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2145,6 +2145,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->tx_desc_len = sizeof(struct ath_desc); } + if (AR_SREV_9300_20_OR_LATER(ah)) + pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED; + return 0; } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 25713beb8e71..fcf78424bfab 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -179,6 +179,7 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_AUTOSLEEP = BIT(15), ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16), ATH9K_HW_CAP_EDMA = BIT(17), + ATH9K_HW_CAP_RAC_SUPPORTED = BIT(18), }; enum ath9k_capability_type { diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 12de95ea7631..12f16215c588 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -169,6 +169,8 @@ #define AR_ISR 0x0080 #define AR_ISR_RXOK 0x00000001 #define AR_ISR_RXDESC 0x00000002 +#define AR_ISR_HP_RXOK 0x00000001 +#define AR_ISR_LP_RXOK 0x00000002 #define AR_ISR_RXERR 0x00000004 #define AR_ISR_RXNOPKT 0x00000008 #define AR_ISR_RXEOL 0x00000010 -- cgit v1.2.3 From 57b98384e5450996300d77ece61739b58325a84f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Apr 2010 17:39:17 -0400 Subject: ath9k_hw: move AR9280 PCI EEPROM fix to eeprom_def.c Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom_def.c | 6 ++++++ drivers/net/wireless/ath/ath9k/hw.c | 17 ----------------- 2 files changed, 6 insertions(+), 17 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 3d1b86bd07df..cf59799ef307 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -223,6 +223,12 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) return -EINVAL; } + /* Enable fixup for AR_AN_TOP2 if necessary */ + if (AR_SREV_9280_10_OR_LATER(ah) && + (eep->baseEepHeader.version & 0xff) > 0x0a && + eep->baseEepHeader.pwdclkind == 0) + ah->need_an_top2_fixup = 1; + return 0; } diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2a04251d6063..888a768ee0be 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -525,21 +525,6 @@ static int ath9k_hw_post_init(struct ath_hw *ah) return 0; } -static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah) -{ - struct base_eep_header *pBase = &(ah->eeprom.def.baseEepHeader); - struct ath_common *common = ath9k_hw_common(ah); - - ah->need_an_top2_fixup = (ah->hw_version.devid == AR9280_DEVID_PCI) && - !AR_SREV_9285(ah) && !AR_SREV_9271(ah) && - ((pBase->version & 0xff) > 0x0a) && - (pBase->pwdclkind == 0); - - if (ah->need_an_top2_fixup) - ath_print(common, ATH_DBG_EEPROM, - "needs fixup for AR_AN_TOP2 register\n"); -} - static void ath9k_hw_attach_ops(struct ath_hw *ah) { if (AR_SREV_9300_20_OR_LATER(ah)) @@ -629,8 +614,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (r) return r; - ath9k_hw_init_eeprom_fix(ah); - r = ath9k_hw_init_macaddr(ah); if (r) { ath_print(common, ATH_DBG_FATAL, -- cgit v1.2.3 From ebd5a14a450e31611696dfe96781a3b8915d835c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:18 -0400 Subject: ath9k_hw: move the RF claim stuff to AR9002 hardware family Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_hw.c | 43 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/hw.c | 51 +++--------------------------- drivers/net/wireless/ath/ath9k/hw.h | 5 +++ 3 files changed, 53 insertions(+), 46 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index eeaea2631c18..5b21e6914386 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -483,6 +483,49 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, } } +static int ar9002_hw_get_radiorev(struct ath_hw *ah) +{ + u32 val; + int i; + + REG_WRITE(ah, AR_PHY(0x36), 0x00007058); + + for (i = 0; i < 8; i++) + REG_WRITE(ah, AR_PHY(0x20), 0x00010000); + val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; + val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); + + return ath9k_hw_reverse_bits(val, 8); +} + +int ar9002_hw_rf_claim(struct ath_hw *ah) +{ + u32 val; + + REG_WRITE(ah, AR_PHY(0), 0x00000007); + + val = ar9002_hw_get_radiorev(ah); + switch (val & AR_RADIO_SREV_MAJOR) { + case 0: + val = AR_RAD5133_SREV_MAJOR; + break; + case AR_RAD5133_SREV_MAJOR: + case AR_RAD5122_SREV_MAJOR: + case AR_RAD2133_SREV_MAJOR: + case AR_RAD2122_SREV_MAJOR: + break; + default: + ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, + "Radio Chip Rev 0x%02X not supported\n", + val & AR_RADIO_SREV_MAJOR); + return -EOPNOTSUPP; + } + + ah->hw_version.analog5GhzRev = val; + + return 0; +} + /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */ void ar9002_hw_attach_ops(struct ath_hw *ah) { diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 888a768ee0be..70162db1323e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -264,21 +264,6 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) } } -static int ath9k_hw_get_radiorev(struct ath_hw *ah) -{ - u32 val; - int i; - - REG_WRITE(ah, AR_PHY(0x36), 0x00007058); - - for (i = 0; i < 8; i++) - REG_WRITE(ah, AR_PHY(0x20), 0x00010000); - val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; - val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); - - return ath9k_hw_reverse_bits(val, 8); -} - /************************************/ /* HW Attach, Detach, Init Routines */ /************************************/ @@ -438,34 +423,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) ah->power_mode = ATH9K_PM_UNDEFINED; } -static int ath9k_hw_rf_claim(struct ath_hw *ah) -{ - u32 val; - - REG_WRITE(ah, AR_PHY(0), 0x00000007); - - val = ath9k_hw_get_radiorev(ah); - switch (val & AR_RADIO_SREV_MAJOR) { - case 0: - val = AR_RAD5133_SREV_MAJOR; - break; - case AR_RAD5133_SREV_MAJOR: - case AR_RAD5122_SREV_MAJOR: - case AR_RAD2133_SREV_MAJOR: - case AR_RAD2122_SREV_MAJOR: - break; - default: - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "Radio Chip Rev 0x%02X not supported\n", - val & AR_RADIO_SREV_MAJOR); - return -EOPNOTSUPP; - } - - ah->hw_version.analog5GhzRev = val; - - return 0; -} - static int ath9k_hw_init_macaddr(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -496,9 +453,11 @@ static int ath9k_hw_post_init(struct ath_hw *ah) return -ENODEV; } - ecode = ath9k_hw_rf_claim(ah); - if (ecode != 0) - return ecode; + if (!AR_SREV_9300_20_OR_LATER(ah)) { + ecode = ar9002_hw_rf_claim(ah); + if (ecode != 0) + return ecode; + } ecode = ath9k_hw_eeprom_init(ah); if (ecode != 0) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index fcf78424bfab..16f0f9820796 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -844,7 +844,12 @@ void ath9k_hw_htc_resetinit(struct ath_hw *ah); void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, u32 *coef_mantissa, u32 *coef_exponent); +/* + * Code Specific to AR5008, AR9001 or AR9002, + * we stuff these here to avoid callbacks for AR9003. + */ void ar9002_hw_cck_chan14_spread(struct ath_hw *ah); +int ar9002_hw_rf_claim(struct ath_hw *ah); /* * Code specifric to AR9003, we stuff these here to avoid callbacks -- cgit v1.2.3 From 7f62a136910f70d9b412f48f764321ff20ce6f38 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:19 -0400 Subject: ath9k_hw: Configure Tx interrupt mitigation timer Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 70162db1323e..d1e68c255dea 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1286,6 +1286,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); } + if (ah->config.tx_intr_mitigation) { + REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300); + REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750); + } + ath9k_hw_init_bb(ah, chan); if (!ath9k_hw_init_cal(ah, chan)) -- cgit v1.2.3 From ec83903e67f9d1e8398568c77dc4fdd333531e96 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:20 -0400 Subject: ath9k_hw: add the AR9300 SREV hw name print Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index d1e68c255dea..ccd819a4a816 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2689,6 +2689,7 @@ static struct { { AR_SREV_VERSION_9285, "9285" }, { AR_SREV_VERSION_9287, "9287" }, { AR_SREV_VERSION_9271, "9271" }, + { AR_SREV_VERSION_9300, "9300" }, }; /* For devices with external radios */ -- cgit v1.2.3 From c14a85dad438ee2c3d0bec6f11295d3a6efd4127 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:21 -0400 Subject: ath9k_hw: add TX/RX gain register initialization for AR9003 This is done depending on what the EEPROM settings indicates. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 14 +++++++ drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 4 ++ drivers/net/wireless/ath/ath9k/ar9003_hw.c | 51 ++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index fb39e392d9f7..5d92be47c5a5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -1827,6 +1827,20 @@ static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah, return AR_NO_SPUR; } +s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah) +{ + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + + return (eep->baseEepHeader.txrxgain >> 4) & 0xf; /* bits 7:4 */ +} + +s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah) +{ + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + + return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */ +} + const struct eeprom_ops eep_ar9300_ops = { .check_eeprom = ath9k_hw_ar9300_check_eeprom, .get_eeprom = ath9k_hw_ar9300_get_eeprom, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index 3ca520c4b6a3..5fe335e22c89 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -316,4 +316,8 @@ struct ar9300_eeprom { u8 ctl_freqbin_5G[AR9300_NUM_CTLS_5G][AR9300_NUM_BAND_EDGES_5G]; struct cal_ctl_data_5g ctlPowerData_5G[AR9300_NUM_CTLS_5G]; } __packed; + +s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah); +s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah); + #endif diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 1984b4f78bc7..f32665d9ec0a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -105,6 +105,56 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) 3); } +static void ar9003_tx_gain_table_apply(struct ath_hw *ah) +{ + switch (ar9003_hw_get_tx_gain_idx(ah)) { + case 0: + default: + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_lowest_ob_db_tx_gain_table_2p0, + ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0), + 5); + break; + case 1: + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_high_ob_db_tx_gain_table_2p0, + ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0), + 5); + break; + case 2: + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_low_ob_db_tx_gain_table_2p0, + ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0), + 5); + break; + } +} + +static void ar9003_rx_gain_table_apply(struct ath_hw *ah) +{ + switch (ar9003_hw_get_rx_gain_idx(ah)) { + case 0: + default: + INIT_INI_ARRAY(&ah->iniModesRxGain, ar9300Common_rx_gain_table_2p0, + ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), + 2); + break; + case 1: + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9300Common_wo_xlna_rx_gain_table_2p0, + ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0), + 2); + break; + } +} + +/* set gain table pointers according to values read from the eeprom */ +static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah) +{ + ar9003_tx_gain_table_apply(ah); + ar9003_rx_gain_table_apply(ah); +} + /* * Helper for ASPM support. * @@ -143,6 +193,7 @@ void ar9003_hw_attach_ops(struct ath_hw *ah) struct ath_hw_ops *ops = ath9k_hw_ops(ah); priv_ops->init_mode_regs = ar9003_hw_init_mode_regs; + priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; priv_ops->macversion_supported = ar9003_hw_macversion_supported; ops->config_pci_powersave = ar9003_hw_configpcipowersave; -- cgit v1.2.3 From 57b32227cd7f1f81f4143d8bc82a5ffe37ab4df9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Apr 2010 17:39:22 -0400 Subject: ath9k_hw: Update ath9k_hw_set_dma for AR9300 Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 18 +++++++++++++++--- drivers/net/wireless/ath/ath9k/reg.h | 6 ++++++ 2 files changed, 21 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ccd819a4a816..fd146c8d4cd8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -836,13 +836,16 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan) static inline void ath9k_hw_set_dma(struct ath_hw *ah) { + struct ath_common *common = ath9k_hw_common(ah); u32 regval; /* * set AHB_MODE not to do cacheline prefetches */ - regval = REG_READ(ah, AR_AHB_MODE); - REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); + if (!AR_SREV_9300_20_OR_LATER(ah)) { + regval = REG_READ(ah, AR_AHB_MODE); + REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); + } /* * let mac dma reads be in 128 byte chunks @@ -855,7 +858,8 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) * The initial value depends on whether aggregation is enabled, and is * adjusted whenever underruns are detected. */ - REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level); + if (!AR_SREV_9300_20_OR_LATER(ah)) + REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level); /* * let mac dma writes be in 128 byte chunks @@ -868,6 +872,14 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) */ REG_WRITE(ah, AR_RXFIFO_CFG, 0x200); + if (AR_SREV_9300_20_OR_LATER(ah)) { + REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_HP, 0x1); + REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_LP, 0x1); + + ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize - + ah->caps.rx_status_len); + } + /* * reduce the number of usable entries in PCU TXBUF to avoid * wrap around issues. diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 12f16215c588..2ca478c802c4 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -39,6 +39,12 @@ #define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000 #define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17 +#define AR_RXBP_THRESH 0x0018 +#define AR_RXBP_THRESH_HP 0x0000000f +#define AR_RXBP_THRESH_HP_S 0 +#define AR_RXBP_THRESH_LP 0x00003f00 +#define AR_RXBP_THRESH_LP_S 8 + #define AR_MIRT 0x0020 #define AR_MIRT_VAL 0x0000ffff #define AR_MIRT_VAL_S 16 -- cgit v1.2.3 From 78ec26778803abd4ebb105bb19c729100c829837 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:23 -0400 Subject: ath9k_hw: skip asynch fifo enablement to AR9003 The asynch fifo code is specific to >= AR9287 so stuff it into the AR9002 hardware family code and skip it for AR9003 cards. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_hw.c | 29 +++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/hw.c | 17 ++--------------- drivers/net/wireless/ath/ath9k/hw.h | 1 + 3 files changed, 32 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 5b21e6914386..cf36f6467914 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -526,6 +526,35 @@ int ar9002_hw_rf_claim(struct ath_hw *ah) return 0; } +/* + * Enable ASYNC FIFO + * + * If Async FIFO is enabled, the following counters change as MAC now runs + * at 117 Mhz instead of 88/44MHz when async FIFO is disabled. + * + * The values below tested for ht40 2 chain. + * Overwrite the delay/timeouts initialized in process ini. + */ +void ar9002_hw_enable_async_fifo(struct ath_hw *ah) +{ + if (AR_SREV_9287_12_OR_LATER(ah)) { + REG_WRITE(ah, AR_D_GBL_IFS_SIFS, + AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); + REG_WRITE(ah, AR_D_GBL_IFS_SLOT, + AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR); + REG_WRITE(ah, AR_D_GBL_IFS_EIFS, + AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR); + + REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR); + REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR); + + REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER, + AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768); + REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN, + AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); + } +} + /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */ void ar9002_hw_attach_ops(struct ath_hw *ah) { diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index fd146c8d4cd8..1dc1b485c3c3 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1265,22 +1265,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_init_global_settings(ah); - if (AR_SREV_9287_12_OR_LATER(ah)) { - REG_WRITE(ah, AR_D_GBL_IFS_SIFS, - AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); - REG_WRITE(ah, AR_D_GBL_IFS_SLOT, - AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR); - REG_WRITE(ah, AR_D_GBL_IFS_EIFS, - AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR); - - REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR); - REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR); + if (!AR_SREV_9300_20_OR_LATER(ah)) + ar9002_hw_enable_async_fifo(ah); - REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER, - AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768); - REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN, - AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); - } if (AR_SREV_9287_12_OR_LATER(ah)) { REG_SET_BIT(ah, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_ENABLE_AGGWEP); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 16f0f9820796..e4eacdd4c810 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -850,6 +850,7 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, */ void ar9002_hw_cck_chan14_spread(struct ath_hw *ah); int ar9002_hw_rf_claim(struct ath_hw *ah); +void ar9002_hw_enable_async_fifo(struct ath_hw *ah); /* * Code specifric to AR9003, we stuff these here to avoid callbacks -- cgit v1.2.3 From 6c94fdc97a27bd681afeaf05d9101b3f9a06f986 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:24 -0400 Subject: ath9k_hw: skip WEP aggregation enable code for AR9003 The AR9002 hardware code enables aggregation for WEP but mac80211 doesn't enable aggregation with WEP, and the AR9003 code family does not need this so skip it for now for AR9003 but leave the code and annotate we should eventually consider how to remove this in consideration for the HAL unification goals. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_hw.c | 12 ++++++++++++ drivers/net/wireless/ath/ath9k/hw.c | 7 ++----- drivers/net/wireless/ath/ath9k/hw.h | 1 + 3 files changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index cf36f6467914..17b98a3f33bc 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -555,6 +555,18 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah) } } +/* + * We don't enable WEP aggregation on mac80211 but we keep this + * around for HAL unification purposes. + */ +void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah) +{ + if (AR_SREV_9287_12_OR_LATER(ah)) { + REG_SET_BIT(ah, AR_PCU_MISC_MODE2, + AR_PCU_MISC_MODE2_ENABLE_AGGWEP); + } +} + /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */ void ar9002_hw_attach_ops(struct ath_hw *ah) { diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 1dc1b485c3c3..a6f8032e54d6 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1265,12 +1265,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_init_global_settings(ah); - if (!AR_SREV_9300_20_OR_LATER(ah)) + if (!AR_SREV_9300_20_OR_LATER(ah)) { ar9002_hw_enable_async_fifo(ah); - - if (AR_SREV_9287_12_OR_LATER(ah)) { - REG_SET_BIT(ah, AR_PCU_MISC_MODE2, - AR_PCU_MISC_MODE2_ENABLE_AGGWEP); + ar9002_hw_enable_wep_aggregation(ah); } REG_WRITE(ah, AR_STA_ID1, diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e4eacdd4c810..affb848a2b98 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -851,6 +851,7 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, void ar9002_hw_cck_chan14_spread(struct ath_hw *ah); int ar9002_hw_rf_claim(struct ath_hw *ah); void ar9002_hw_enable_async_fifo(struct ath_hw *ah); +void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah); /* * Code specifric to AR9003, we stuff these here to avoid callbacks -- cgit v1.2.3 From d8903a5361817bd96ceed212ad27a380e7ef4d8e Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:25 -0400 Subject: ath9k: Load SW filtered NF values and start NF cal during full reset for AR9003 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index a6f8032e54d6..824dd9e72564 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1324,6 +1324,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (ah->btcoex_hw.enabled) ath9k_hw_btcoex_enable(ah); + if (AR_SREV_9300_20_OR_LATER(ah)) { + ath9k_hw_loadnf(ah, curchan); + ath9k_hw_start_nfcal(ah); + } + return 0; } EXPORT_SYMBOL(ath9k_hw_reset); -- cgit v1.2.3 From cc610ac0557b0ad0dcffdff1230cef28a970d755 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:26 -0400 Subject: ath9k_hw: Define abstraction for tx desc access Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 73 ++++ drivers/net/wireless/ath/ath9k/beacon.c | 3 +- drivers/net/wireless/ath/ath9k/hw-ops.h | 71 ++++ drivers/net/wireless/ath/ath9k/hw.h | 27 ++ drivers/net/wireless/ath/ath9k/mac.c | 508 ++++++++++++++-------------- drivers/net/wireless/ath/ath9k/mac.h | 27 +- drivers/net/wireless/ath/ath9k/xmit.c | 3 +- 7 files changed, 431 insertions(+), 281 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 2319456f2f0e..c270bbe25168 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -167,6 +167,69 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) return true; } +static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, + bool is_firstseg, bool is_lastseg, + const void *ds0, dma_addr_t buf_addr, + unsigned int qcu) +{ +} + +static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, + struct ath_tx_status *ts) +{ + return 0; +} +static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, + u32 pktLen, enum ath9k_pkt_type type, u32 txPower, + u32 keyIx, enum ath9k_key_type keyType, u32 flags) +{ + +} + +static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, + void *lastds, + u32 durUpdateEn, u32 rtsctsRate, + u32 rtsctsDuration, + struct ath9k_11n_rate_series series[], + u32 nseries, u32 flags) +{ + +} + +static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, + u32 aggrLen) +{ + +} + +static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, + u32 numDelims) +{ + +} + +static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) +{ + +} + +static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds) +{ + +} + +static void ar9003_hw_set11n_burstduration(struct ath_hw *ah, void *ds, + u32 burstDuration) +{ + +} + +static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, + u32 vmf) +{ + +} + void ar9003_hw_attach_mac_ops(struct ath_hw *hw) { struct ath_hw_ops *ops = ath9k_hw_ops(hw); @@ -175,6 +238,16 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) ops->set_desc_link = ar9003_hw_set_desc_link; ops->get_desc_link = ar9003_hw_get_desc_link; ops->get_isr = ar9003_hw_get_isr; + ops->fill_txdesc = ar9003_hw_fill_txdesc; + ops->proc_txdesc = ar9003_hw_proc_txdesc; + ops->set11n_txdesc = ar9003_hw_set11n_txdesc; + ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario; + ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first; + ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle; + ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; + ops->clr11n_aggr = ar9003_hw_clr11n_aggr; + ops->set11n_burstduration = ar9003_hw_set11n_burstduration; + ops->set11n_virtualmorefrag = ar9003_hw_set11n_virtualmorefrag; } void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 268b598746f6..c8a4558f79ba 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -107,7 +107,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, /* NB: beacon's BufLen must be a multiple of 4 bytes */ ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4), - true, true, ds, bf->bf_buf_addr); + true, true, ds, bf->bf_buf_addr, + sc->beacon.beaconq); memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); series[0].Tries = 1; diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index b444ce5f09f8..624422a8169e 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -57,6 +57,77 @@ static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) return ath9k_hw_ops(ah)->get_isr(ah, masked); } +static inline void ath9k_hw_filltxdesc(struct ath_hw *ah, void *ds, u32 seglen, + bool is_firstseg, bool is_lastseg, + const void *ds0, dma_addr_t buf_addr, + unsigned int qcu) +{ + ath9k_hw_ops(ah)->fill_txdesc(ah, ds, seglen, is_firstseg, is_lastseg, + ds0, buf_addr, qcu); +} + +static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds, + struct ath_tx_status *ts) +{ + return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts); +} + +static inline void ath9k_hw_set11n_txdesc(struct ath_hw *ah, void *ds, + u32 pktLen, enum ath9k_pkt_type type, + u32 txPower, u32 keyIx, + enum ath9k_key_type keyType, + u32 flags) +{ + ath9k_hw_ops(ah)->set11n_txdesc(ah, ds, pktLen, type, txPower, keyIx, + keyType, flags); +} + +static inline void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, + void *lastds, + u32 durUpdateEn, u32 rtsctsRate, + u32 rtsctsDuration, + struct ath9k_11n_rate_series series[], + u32 nseries, u32 flags) +{ + ath9k_hw_ops(ah)->set11n_ratescenario(ah, ds, lastds, durUpdateEn, + rtsctsRate, rtsctsDuration, series, + nseries, flags); +} + +static inline void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, + u32 aggrLen) +{ + ath9k_hw_ops(ah)->set11n_aggr_first(ah, ds, aggrLen); +} + +static inline void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, + u32 numDelims) +{ + ath9k_hw_ops(ah)->set11n_aggr_middle(ah, ds, numDelims); +} + +static inline void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) +{ + ath9k_hw_ops(ah)->set11n_aggr_last(ah, ds); +} + +static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds) +{ + ath9k_hw_ops(ah)->clr11n_aggr(ah, ds); +} + +static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds, + u32 burstDuration) +{ + ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration); +} + +static inline void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, + u32 vmf) +{ + ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf); +} + /* Private hardware call ops */ /* PHY ops */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index affb848a2b98..457d8ddebf83 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -556,6 +556,33 @@ struct ath_hw_ops { u8 rxchainmask, bool longcal); bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked); + void (*fill_txdesc)(struct ath_hw *ah, void *ds, u32 seglen, + bool is_firstseg, bool is_is_lastseg, + const void *ds0, dma_addr_t buf_addr, + unsigned int qcu); + int (*proc_txdesc)(struct ath_hw *ah, void *ds, + struct ath_tx_status *ts); + void (*set11n_txdesc)(struct ath_hw *ah, void *ds, + u32 pktLen, enum ath9k_pkt_type type, + u32 txPower, u32 keyIx, + enum ath9k_key_type keyType, + u32 flags); + void (*set11n_ratescenario)(struct ath_hw *ah, void *ds, + void *lastds, + u32 durUpdateEn, u32 rtsctsRate, + u32 rtsctsDuration, + struct ath9k_11n_rate_series series[], + u32 nseries, u32 flags); + void (*set11n_aggr_first)(struct ath_hw *ah, void *ds, + u32 aggrLen); + void (*set11n_aggr_middle)(struct ath_hw *ah, void *ds, + u32 numDelims); + void (*set11n_aggr_last)(struct ath_hw *ah, void *ds); + void (*clr11n_aggr)(struct ath_hw *ah, void *ds); + void (*set11n_burstduration)(struct ath_hw *ah, void *ds, + u32 burstDuration); + void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds, + u32 vmf); }; struct ath_hw { diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 4a36ec53f732..22fa5125abff 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -183,226 +183,25 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) return true; } -void ar9002_hw_attach_mac_ops(struct ath_hw *ah) -{ - struct ath_hw_ops *ops = ath9k_hw_ops(ah); - - ops->rx_enable = ar9002_hw_rx_enable; - ops->set_desc_link = ar9002_hw_set_desc_link; - ops->get_desc_link = ar9002_hw_get_desc_link; - ops->get_isr = ar9002_hw_get_isr; -} - -static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, - struct ath9k_tx_queue_info *qi) -{ - ath_print(ath9k_hw_common(ah), ATH_DBG_INTERRUPT, - "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", - ah->txok_interrupt_mask, ah->txerr_interrupt_mask, - ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, - ah->txurn_interrupt_mask); - - REG_WRITE(ah, AR_IMR_S0, - SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK) - | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC)); - REG_WRITE(ah, AR_IMR_S1, - SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR) - | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL)); - - ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN; - ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN); - REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); -} - -u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) -{ - return REG_READ(ah, AR_QTXDP(q)); -} -EXPORT_SYMBOL(ath9k_hw_gettxbuf); - -void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) -{ - REG_WRITE(ah, AR_QTXDP(q), txdp); -} -EXPORT_SYMBOL(ath9k_hw_puttxbuf); - -void ath9k_hw_txstart(struct ath_hw *ah, u32 q) -{ - ath_print(ath9k_hw_common(ah), ATH_DBG_QUEUE, - "Enable TXE on queue: %u\n", q); - REG_WRITE(ah, AR_Q_TXE, 1 << q); -} -EXPORT_SYMBOL(ath9k_hw_txstart); - -u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) -{ - u32 npend; - - npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT; - if (npend == 0) { - - if (REG_READ(ah, AR_Q_TXE) & (1 << q)) - npend = 1; - } - - return npend; -} -EXPORT_SYMBOL(ath9k_hw_numtxpending); - -/** - * ath9k_hw_updatetxtriglevel - adjusts the frame trigger level - * - * @ah: atheros hardware struct - * @bIncTrigLevel: whether or not the frame trigger level should be updated - * - * The frame trigger level specifies the minimum number of bytes, - * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO - * before the PCU will initiate sending the frame on the air. This can - * mean we initiate transmit before a full frame is on the PCU TX FIFO. - * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs - * first) - * - * Caution must be taken to ensure to set the frame trigger level based - * on the DMA request size. For example if the DMA request size is set to - * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because - * there need to be enough space in the tx FIFO for the requested transfer - * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set - * the threshold to a value beyond 6, then the transmit will hang. - * - * Current dual stream devices have a PCU TX FIFO size of 8 KB. - * Current single stream devices have a PCU TX FIFO size of 4 KB, however, - * there is a hardware issue which forces us to use 2 KB instead so the - * frame trigger level must not exceed 2 KB for these chipsets. - */ -bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) -{ - u32 txcfg, curLevel, newLevel; - enum ath9k_int omask; - - if (ah->tx_trig_level >= ah->config.max_txtrig_level) - return false; - - omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL); - - txcfg = REG_READ(ah, AR_TXCFG); - curLevel = MS(txcfg, AR_FTRIG); - newLevel = curLevel; - if (bIncTrigLevel) { - if (curLevel < ah->config.max_txtrig_level) - newLevel++; - } else if (curLevel > MIN_TX_FIFO_THRESHOLD) - newLevel--; - if (newLevel != curLevel) - REG_WRITE(ah, AR_TXCFG, - (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); - - ath9k_hw_set_interrupts(ah, omask); - - ah->tx_trig_level = newLevel; - - return newLevel != curLevel; -} -EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel); - -bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) -{ -#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ -#define ATH9K_TIME_QUANTUM 100 /* usec */ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath9k_tx_queue_info *qi; - u32 tsfLow, j, wait; - u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; - - if (q >= pCap->total_queues) { - ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " - "invalid queue: %u\n", q); - return false; - } - - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " - "inactive queue: %u\n", q); - return false; - } - - REG_WRITE(ah, AR_Q_TXD, 1 << q); - - for (wait = wait_time; wait != 0; wait--) { - if (ath9k_hw_numtxpending(ah, q) == 0) - break; - udelay(ATH9K_TIME_QUANTUM); - } - - if (ath9k_hw_numtxpending(ah, q)) { - ath_print(common, ATH_DBG_QUEUE, - "%s: Num of pending TX Frames %d on Q %d\n", - __func__, ath9k_hw_numtxpending(ah, q), q); - - for (j = 0; j < 2; j++) { - tsfLow = REG_READ(ah, AR_TSF_L32); - REG_WRITE(ah, AR_QUIET2, - SM(10, AR_QUIET2_QUIET_DUR)); - REG_WRITE(ah, AR_QUIET_PERIOD, 100); - REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10); - REG_SET_BIT(ah, AR_TIMER_MODE, - AR_QUIET_TIMER_EN); - - if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) - break; - - ath_print(common, ATH_DBG_QUEUE, - "TSF has moved while trying to set " - "quiet time TSF: 0x%08x\n", tsfLow); - } - - REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); - - udelay(200); - REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); - - wait = wait_time; - while (ath9k_hw_numtxpending(ah, q)) { - if ((--wait) == 0) { - ath_print(common, ATH_DBG_FATAL, - "Failed to stop TX DMA in 100 " - "msec after killing last frame\n"); - break; - } - udelay(ATH9K_TIME_QUANTUM); - } - - REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); - } - - REG_WRITE(ah, AR_Q_TXD, 0); - return wait != 0; - -#undef ATH9K_TX_STOP_DMA_TIMEOUT -#undef ATH9K_TIME_QUANTUM -} -EXPORT_SYMBOL(ath9k_hw_stoptxdma); - -void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 segLen, bool firstSeg, - bool lastSeg, const struct ath_desc *ds0, - dma_addr_t buf_addr) +static void ar9002_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, + bool is_firstseg, bool is_lastseg, + const void *ds0, dma_addr_t buf_addr, + unsigned int qcu) { struct ar5416_desc *ads = AR5416DESC(ds); ads->ds_data = buf_addr; - if (firstSeg) { - ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore); - } else if (lastSeg) { + if (is_firstseg) { + ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore); + } else if (is_lastseg) { ads->ds_ctl0 = 0; - ads->ds_ctl1 = segLen; + ads->ds_ctl1 = seglen; ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; } else { ads->ds_ctl0 = 0; - ads->ds_ctl1 = segLen | AR_TxMore; + ads->ds_ctl1 = seglen | AR_TxMore; ads->ds_ctl2 = 0; ads->ds_ctl3 = 0; } @@ -412,22 +211,9 @@ void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, ads->ds_txstatus6 = ads->ds_txstatus7 = 0; ads->ds_txstatus8 = ads->ds_txstatus9 = 0; } -EXPORT_SYMBOL(ath9k_hw_filltxdesc); -void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_txstatus0 = ads->ds_txstatus1 = 0; - ads->ds_txstatus2 = ads->ds_txstatus3 = 0; - ads->ds_txstatus4 = ads->ds_txstatus5 = 0; - ads->ds_txstatus6 = ads->ds_txstatus7 = 0; - ads->ds_txstatus8 = ads->ds_txstatus9 = 0; -} -EXPORT_SYMBOL(ath9k_hw_cleartxdesc); - -int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, - struct ath_tx_status *ts) +static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, + struct ath_tx_status *ts) { struct ar5416_desc *ads = AR5416DESC(ds); @@ -503,11 +289,11 @@ int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, return 0; } -EXPORT_SYMBOL(ath9k_hw_txprocdesc); -void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 pktLen, enum ath9k_pkt_type type, u32 txPower, - u32 keyIx, enum ath9k_key_type keyType, u32 flags) +static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, + u32 pktLen, enum ath9k_pkt_type type, + u32 txPower, u32 keyIx, + enum ath9k_key_type keyType, u32 flags) { struct ar5416_desc *ads = AR5416DESC(ds); @@ -539,14 +325,13 @@ void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, ads->ds_ctl11 = 0; } } -EXPORT_SYMBOL(ath9k_hw_set11n_txdesc); - -void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, - struct ath_desc *lastds, - u32 durUpdateEn, u32 rtsctsRate, - u32 rtsctsDuration, - struct ath9k_11n_rate_series series[], - u32 nseries, u32 flags) + +static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, + void *lastds, + u32 durUpdateEn, u32 rtsctsRate, + u32 rtsctsDuration, + struct ath9k_11n_rate_series series[], + u32 nseries, u32 flags) { struct ar5416_desc *ads = AR5416DESC(ds); struct ar5416_desc *last_ads = AR5416DESC(lastds); @@ -595,10 +380,9 @@ void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, last_ads->ds_ctl2 = ads->ds_ctl2; last_ads->ds_ctl3 = ads->ds_ctl3; } -EXPORT_SYMBOL(ath9k_hw_set11n_ratescenario); -void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, - u32 aggrLen) +static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, + u32 aggrLen) { struct ar5416_desc *ads = AR5416DESC(ds); @@ -606,10 +390,9 @@ void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, ads->ds_ctl6 &= ~AR_AggrLen; ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); } -EXPORT_SYMBOL(ath9k_hw_set11n_aggr_first); -void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, - u32 numDelims) +static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, + u32 numDelims) { struct ar5416_desc *ads = AR5416DESC(ds); unsigned int ctl6; @@ -621,9 +404,8 @@ void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, ctl6 |= SM(numDelims, AR_PadDelim); ads->ds_ctl6 = ctl6; } -EXPORT_SYMBOL(ath9k_hw_set11n_aggr_middle); -void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) +static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) { struct ar5416_desc *ads = AR5416DESC(ds); @@ -631,28 +413,25 @@ void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) ads->ds_ctl1 &= ~AR_MoreAggr; ads->ds_ctl6 &= ~AR_PadDelim; } -EXPORT_SYMBOL(ath9k_hw_set11n_aggr_last); -void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds) +static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds) { struct ar5416_desc *ads = AR5416DESC(ds); ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); } -EXPORT_SYMBOL(ath9k_hw_clr11n_aggr); -void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, - u32 burstDuration) +static void ar9002_hw_set11n_burstduration(struct ath_hw *ah, void *ds, + u32 burstDuration) { struct ar5416_desc *ads = AR5416DESC(ds); ads->ds_ctl2 &= ~AR_BurstDur; ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); } -EXPORT_SYMBOL(ath9k_hw_set11n_burstduration); -void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, - u32 vmf) +static void ar9002_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, + u32 vmf) { struct ar5416_desc *ads = AR5416DESC(ds); @@ -662,6 +441,229 @@ void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, ads->ds_ctl0 &= ~AR_VirtMoreFrag; } +void ar9002_hw_attach_mac_ops(struct ath_hw *ah) +{ + struct ath_hw_ops *ops = ath9k_hw_ops(ah); + + ops->rx_enable = ar9002_hw_rx_enable; + ops->set_desc_link = ar9002_hw_set_desc_link; + ops->get_desc_link = ar9002_hw_get_desc_link; + ops->get_isr = ar9002_hw_get_isr; + ops->fill_txdesc = ar9002_hw_fill_txdesc; + ops->proc_txdesc = ar9002_hw_proc_txdesc; + ops->set11n_txdesc = ar9002_hw_set11n_txdesc; + ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario; + ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first; + ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle; + ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; + ops->clr11n_aggr = ar9002_hw_clr11n_aggr; + ops->set11n_burstduration = ar9002_hw_set11n_burstduration; + ops->set11n_virtualmorefrag = ar9002_hw_set11n_virtualmorefrag; +} + +static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, + struct ath9k_tx_queue_info *qi) +{ + ath_print(ath9k_hw_common(ah), ATH_DBG_INTERRUPT, + "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", + ah->txok_interrupt_mask, ah->txerr_interrupt_mask, + ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, + ah->txurn_interrupt_mask); + + REG_WRITE(ah, AR_IMR_S0, + SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK) + | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC)); + REG_WRITE(ah, AR_IMR_S1, + SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR) + | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL)); + + ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN; + ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN); + REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); +} + +u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) +{ + return REG_READ(ah, AR_QTXDP(q)); +} +EXPORT_SYMBOL(ath9k_hw_gettxbuf); + +void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) +{ + REG_WRITE(ah, AR_QTXDP(q), txdp); +} +EXPORT_SYMBOL(ath9k_hw_puttxbuf); + +void ath9k_hw_txstart(struct ath_hw *ah, u32 q) +{ + ath_print(ath9k_hw_common(ah), ATH_DBG_QUEUE, + "Enable TXE on queue: %u\n", q); + REG_WRITE(ah, AR_Q_TXE, 1 << q); +} +EXPORT_SYMBOL(ath9k_hw_txstart); + +void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_txstatus0 = ads->ds_txstatus1 = 0; + ads->ds_txstatus2 = ads->ds_txstatus3 = 0; + ads->ds_txstatus4 = ads->ds_txstatus5 = 0; + ads->ds_txstatus6 = ads->ds_txstatus7 = 0; + ads->ds_txstatus8 = ads->ds_txstatus9 = 0; +} +EXPORT_SYMBOL(ath9k_hw_cleartxdesc); + +u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) +{ + u32 npend; + + npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT; + if (npend == 0) { + + if (REG_READ(ah, AR_Q_TXE) & (1 << q)) + npend = 1; + } + + return npend; +} +EXPORT_SYMBOL(ath9k_hw_numtxpending); + +/** + * ath9k_hw_updatetxtriglevel - adjusts the frame trigger level + * + * @ah: atheros hardware struct + * @bIncTrigLevel: whether or not the frame trigger level should be updated + * + * The frame trigger level specifies the minimum number of bytes, + * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO + * before the PCU will initiate sending the frame on the air. This can + * mean we initiate transmit before a full frame is on the PCU TX FIFO. + * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs + * first) + * + * Caution must be taken to ensure to set the frame trigger level based + * on the DMA request size. For example if the DMA request size is set to + * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because + * there need to be enough space in the tx FIFO for the requested transfer + * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set + * the threshold to a value beyond 6, then the transmit will hang. + * + * Current dual stream devices have a PCU TX FIFO size of 8 KB. + * Current single stream devices have a PCU TX FIFO size of 4 KB, however, + * there is a hardware issue which forces us to use 2 KB instead so the + * frame trigger level must not exceed 2 KB for these chipsets. + */ +bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) +{ + u32 txcfg, curLevel, newLevel; + enum ath9k_int omask; + + if (ah->tx_trig_level >= ah->config.max_txtrig_level) + return false; + + omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL); + + txcfg = REG_READ(ah, AR_TXCFG); + curLevel = MS(txcfg, AR_FTRIG); + newLevel = curLevel; + if (bIncTrigLevel) { + if (curLevel < ah->config.max_txtrig_level) + newLevel++; + } else if (curLevel > MIN_TX_FIFO_THRESHOLD) + newLevel--; + if (newLevel != curLevel) + REG_WRITE(ah, AR_TXCFG, + (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); + + ath9k_hw_set_interrupts(ah, omask); + + ah->tx_trig_level = newLevel; + + return newLevel != curLevel; +} +EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel); + +bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) +{ +#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ +#define ATH9K_TIME_QUANTUM 100 /* usec */ + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_hw_capabilities *pCap = &ah->caps; + struct ath9k_tx_queue_info *qi; + u32 tsfLow, j, wait; + u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; + + if (q >= pCap->total_queues) { + ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " + "invalid queue: %u\n", q); + return false; + } + + qi = &ah->txq[q]; + if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { + ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " + "inactive queue: %u\n", q); + return false; + } + + REG_WRITE(ah, AR_Q_TXD, 1 << q); + + for (wait = wait_time; wait != 0; wait--) { + if (ath9k_hw_numtxpending(ah, q) == 0) + break; + udelay(ATH9K_TIME_QUANTUM); + } + + if (ath9k_hw_numtxpending(ah, q)) { + ath_print(common, ATH_DBG_QUEUE, + "%s: Num of pending TX Frames %d on Q %d\n", + __func__, ath9k_hw_numtxpending(ah, q), q); + + for (j = 0; j < 2; j++) { + tsfLow = REG_READ(ah, AR_TSF_L32); + REG_WRITE(ah, AR_QUIET2, + SM(10, AR_QUIET2_QUIET_DUR)); + REG_WRITE(ah, AR_QUIET_PERIOD, 100); + REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10); + REG_SET_BIT(ah, AR_TIMER_MODE, + AR_QUIET_TIMER_EN); + + if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) + break; + + ath_print(common, ATH_DBG_QUEUE, + "TSF has moved while trying to set " + "quiet time TSF: 0x%08x\n", tsfLow); + } + + REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); + + udelay(200); + REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); + + wait = wait_time; + while (ath9k_hw_numtxpending(ah, q)) { + if ((--wait) == 0) { + ath_print(common, ATH_DBG_FATAL, + "Failed to stop TX DMA in 100 " + "msec after killing last frame\n"); + break; + } + udelay(ATH9K_TIME_QUANTUM); + } + + REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); + } + + REG_WRITE(ah, AR_Q_TXD, 0); + return wait != 0; + +#undef ATH9K_TX_STOP_DMA_TIMEOUT +#undef ATH9K_TIME_QUANTUM +} +EXPORT_SYMBOL(ath9k_hw_stoptxdma); + void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) { *txqs &= ah->intr_txqs; diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 7c0d75490211..0d492192de94 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -687,35 +687,10 @@ struct ath9k_channel; u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); void ath9k_hw_txstart(struct ath_hw *ah, u32 q); +void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds); u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); -void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 segLen, bool firstSeg, - bool lastSeg, const struct ath_desc *ds0, - dma_addr_t buf_addr); -void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); -int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, - struct ath_tx_status *ts); -void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 pktLen, enum ath9k_pkt_type type, u32 txPower, - u32 keyIx, enum ath9k_key_type keyType, u32 flags); -void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, - struct ath_desc *lastds, - u32 durUpdateEn, u32 rtsctsRate, - u32 rtsctsDuration, - struct ath9k_11n_rate_series series[], - u32 nseries, u32 flags); -void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, - u32 aggrLen); -void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, - u32 numDelims); -void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds); -void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds); -void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, - u32 burstDuration); -void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, - u32 vmf); void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs); bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, const struct ath9k_tx_queue_info *qinfo); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 6ab20992ba30..550253fe61fb 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1669,7 +1669,8 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, true, /* first segment */ true, /* last segment */ ds, /* first descriptor */ - bf->bf_buf_addr); + bf->bf_buf_addr, + txctl->txq->axq_qnum); spin_lock_bh(&txctl->txq->axq_lock); -- cgit v1.2.3 From 744d402580f959072f6b805a98745837f185c8e0 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:27 -0400 Subject: ath9k_hw: Add function to configure tx status ring buffer Also reset tx status ring suring chip reset. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 30 +++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_mac.h | 17 +++++++++++++++- drivers/net/wireless/ath/ath9k/hw.c | 3 +++ drivers/net/wireless/ath/ath9k/hw.h | 7 +++++++ drivers/net/wireless/ath/ath9k/reg.h | 3 +++ 5 files changed, 59 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index c270bbe25168..81ad09a7ddff 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -347,3 +347,33 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, return 0; } EXPORT_SYMBOL(ath9k_hw_process_rxdesc_edma); + +void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah) +{ + ah->ts_tail = 0; + + memset((void *) ah->ts_ring, 0, + ah->ts_size * sizeof(struct ar9003_txs)); + + ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT, + "TS Start 0x%x End 0x%x Virt %p, Size %d\n", + ah->ts_paddr_start, ah->ts_paddr_end, + ah->ts_ring, ah->ts_size); + + REG_WRITE(ah, AR_Q_STATUS_RING_START, ah->ts_paddr_start); + REG_WRITE(ah, AR_Q_STATUS_RING_END, ah->ts_paddr_end); +} + +void ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start, + u32 ts_paddr_start, + u8 size) +{ + + ah->ts_paddr_start = ts_paddr_start; + ah->ts_paddr_end = ts_paddr_start + (size * sizeof(struct ar9003_txs)); + ah->ts_size = size; + ah->ts_ring = (struct ar9003_txs *) ts_start; + + ath9k_hw_reset_txstatus_ring(ah); +} +EXPORT_SYMBOL(ath9k_hw_setup_statusring); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index 2ba06d7674e8..ef7999636ea0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h @@ -73,6 +73,18 @@ struct ar9003_txc { u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */ } __packed; +struct ar9003_txs { + u32 ds_info; + u32 status1; + u32 status2; + u32 status3; + u32 status4; + u32 status5; + u32 status6; + u32 status7; + u32 status8; +} __packed; + void ar9003_hw_attach_mac_ops(struct ath_hw *hw); void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size); void ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp, @@ -81,5 +93,8 @@ void ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp, int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, void *buf_addr); - +void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah); +void ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start, + u32 ts_paddr_start, + u8 size); #endif diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 824dd9e72564..19e2c3cd1473 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -895,6 +895,9 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) REG_WRITE(ah, AR_PCU_TXBUF_CTRL, AR_PCU_TXBUF_CTRL_USABLE_SIZE); } + + if (AR_SREV_9300_20_OR_LATER(ah)) + ath9k_hw_reset_txstatus_ring(ah); } static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 457d8ddebf83..6dbbab95df59 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -761,6 +761,13 @@ struct ath_hw { u32 intr_gen_timer_trigger; u32 intr_gen_timer_thresh; struct ath_gen_timer_table hw_gen_timers; + + struct ar9003_txs *ts_ring; + void *ts_start; + u32 ts_paddr_start; + u32 ts_paddr_end; + u16 ts_tail; + u8 ts_size; }; static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 2ca478c802c4..ff8914049c53 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -383,6 +383,9 @@ #define AR_Q9_TXDP 0x0824 #define AR_QTXDP(_i) (AR_Q0_TXDP + ((_i)<<2)) +#define AR_Q_STATUS_RING_START 0x830 +#define AR_Q_STATUS_RING_END 0x834 + #define AR_Q_TXE 0x0840 #define AR_Q_TXE_M 0x000003FF -- cgit v1.2.3 From b622a720b45def8dce816244a83b82992da4fe20 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:28 -0400 Subject: ath9k_hw: move AR9002 mac ops to its own file Signed-off-by: Luis R. Rodriguez Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Makefile | 1 + drivers/net/wireless/ath/ath9k/ar9002_mac.c | 480 ++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_hw.c | 1 + drivers/net/wireless/ath/ath9k/ar9003_mac.c | 1 + drivers/net/wireless/ath/ath9k/hw.c | 1 + drivers/net/wireless/ath/ath9k/hw.h | 1 - drivers/net/wireless/ath/ath9k/mac.c | 461 -------------------------- drivers/net/wireless/ath/ath9k/mac.h | 2 - drivers/net/wireless/ath/ath9k/recv.c | 1 + drivers/net/wireless/ath/ath9k/xmit.c | 1 + 10 files changed, 486 insertions(+), 464 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/ar9002_mac.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index b0702fc84651..dd112be218ab 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -30,6 +30,7 @@ ath9k_hw-y:= \ ani.o \ btcoex.o \ mac.o \ + ar9002_mac.o \ ar9003_mac.o \ ar9003_eeprom.o diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c new file mode 100644 index 000000000000..2be20d2070c4 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2008-2009 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" + +#define AR_BufLen 0x00000fff + +static void ar9002_hw_rx_enable(struct ath_hw *ah) +{ + REG_WRITE(ah, AR_CR, AR_CR_RXE); +} + +static void ar9002_hw_set_desc_link(void *ds, u32 ds_link) +{ + ((struct ath_desc*) ds)->ds_link = ds_link; +} + +static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link) +{ + *ds_link = &((struct ath_desc *)ds)->ds_link; +} + +static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) +{ + u32 isr = 0; + u32 mask2 = 0; + struct ath9k_hw_capabilities *pCap = &ah->caps; + u32 sync_cause = 0; + bool fatal_int = false; + struct ath_common *common = ath9k_hw_common(ah); + + if (!AR_SREV_9100(ah)) { + if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { + if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) + == AR_RTC_STATUS_ON) { + isr = REG_READ(ah, AR_ISR); + } + } + + sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & + AR_INTR_SYNC_DEFAULT; + + *masked = 0; + + if (!isr && !sync_cause) + return false; + } else { + *masked = 0; + isr = REG_READ(ah, AR_ISR); + } + + if (isr) { + if (isr & AR_ISR_BCNMISC) { + u32 isr2; + isr2 = REG_READ(ah, AR_ISR_S2); + if (isr2 & AR_ISR_S2_TIM) + mask2 |= ATH9K_INT_TIM; + if (isr2 & AR_ISR_S2_DTIM) + mask2 |= ATH9K_INT_DTIM; + if (isr2 & AR_ISR_S2_DTIMSYNC) + mask2 |= ATH9K_INT_DTIMSYNC; + if (isr2 & (AR_ISR_S2_CABEND)) + mask2 |= ATH9K_INT_CABEND; + if (isr2 & AR_ISR_S2_GTT) + mask2 |= ATH9K_INT_GTT; + if (isr2 & AR_ISR_S2_CST) + mask2 |= ATH9K_INT_CST; + if (isr2 & AR_ISR_S2_TSFOOR) + mask2 |= ATH9K_INT_TSFOOR; + } + + isr = REG_READ(ah, AR_ISR_RAC); + if (isr == 0xffffffff) { + *masked = 0; + return false; + } + + *masked = isr & ATH9K_INT_COMMON; + + if (ah->config.rx_intr_mitigation) { + if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) + *masked |= ATH9K_INT_RX; + } + + if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) + *masked |= ATH9K_INT_RX; + if (isr & + (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | + AR_ISR_TXEOL)) { + u32 s0_s, s1_s; + + *masked |= ATH9K_INT_TX; + + s0_s = REG_READ(ah, AR_ISR_S0_S); + ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); + ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); + + s1_s = REG_READ(ah, AR_ISR_S1_S); + ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); + ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); + } + + if (isr & AR_ISR_RXORN) { + ath_print(common, ATH_DBG_INTERRUPT, + "receive FIFO overrun interrupt\n"); + } + + if (!AR_SREV_9100(ah)) { + if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { + u32 isr5 = REG_READ(ah, AR_ISR_S5_S); + if (isr5 & AR_ISR_S5_TIM_TIMER) + *masked |= ATH9K_INT_TIM_TIMER; + } + } + + *masked |= mask2; + } + + if (AR_SREV_9100(ah)) + return true; + + if (isr & AR_ISR_GENTMR) { + u32 s5_s; + + s5_s = REG_READ(ah, AR_ISR_S5_S); + if (isr & AR_ISR_GENTMR) { + ah->intr_gen_timer_trigger = + MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); + + ah->intr_gen_timer_thresh = + MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); + + if (ah->intr_gen_timer_trigger) + *masked |= ATH9K_INT_GENTIMER; + + } + } + + if (sync_cause) { + fatal_int = + (sync_cause & + (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) + ? true : false; + + if (fatal_int) { + if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { + ath_print(common, ATH_DBG_ANY, + "received PCI FATAL interrupt\n"); + } + if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { + ath_print(common, ATH_DBG_ANY, + "received PCI PERR interrupt\n"); + } + *masked |= ATH9K_INT_FATAL; + } + if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { + ath_print(common, ATH_DBG_INTERRUPT, + "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); + REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); + REG_WRITE(ah, AR_RC, 0); + *masked |= ATH9K_INT_FATAL; + } + if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { + ath_print(common, ATH_DBG_INTERRUPT, + "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); + } + + REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); + (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); + } + + return true; +} + +static void ar9002_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, + bool is_firstseg, bool is_lastseg, + const void *ds0, dma_addr_t buf_addr, + unsigned int qcu) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_data = buf_addr; + + if (is_firstseg) { + ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore); + } else if (is_lastseg) { + ads->ds_ctl0 = 0; + ads->ds_ctl1 = seglen; + ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; + ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; + } else { + ads->ds_ctl0 = 0; + ads->ds_ctl1 = seglen | AR_TxMore; + ads->ds_ctl2 = 0; + ads->ds_ctl3 = 0; + } + ads->ds_txstatus0 = ads->ds_txstatus1 = 0; + ads->ds_txstatus2 = ads->ds_txstatus3 = 0; + ads->ds_txstatus4 = ads->ds_txstatus5 = 0; + ads->ds_txstatus6 = ads->ds_txstatus7 = 0; + ads->ds_txstatus8 = ads->ds_txstatus9 = 0; +} + +static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, + struct ath_tx_status *ts) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + if ((ads->ds_txstatus9 & AR_TxDone) == 0) + return -EINPROGRESS; + + ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); + ts->ts_tstamp = ads->AR_SendTimestamp; + ts->ts_status = 0; + ts->ts_flags = 0; + + if (ads->ds_txstatus1 & AR_FrmXmitOK) + ts->ts_status |= ATH9K_TX_ACKED; + if (ads->ds_txstatus1 & AR_ExcessiveRetries) + ts->ts_status |= ATH9K_TXERR_XRETRY; + if (ads->ds_txstatus1 & AR_Filtered) + ts->ts_status |= ATH9K_TXERR_FILT; + if (ads->ds_txstatus1 & AR_FIFOUnderrun) { + ts->ts_status |= ATH9K_TXERR_FIFO; + ath9k_hw_updatetxtriglevel(ah, true); + } + if (ads->ds_txstatus9 & AR_TxOpExceeded) + ts->ts_status |= ATH9K_TXERR_XTXOP; + if (ads->ds_txstatus1 & AR_TxTimerExpired) + ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; + + if (ads->ds_txstatus1 & AR_DescCfgErr) + ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; + if (ads->ds_txstatus1 & AR_TxDataUnderrun) { + ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; + ath9k_hw_updatetxtriglevel(ah, true); + } + if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { + ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; + ath9k_hw_updatetxtriglevel(ah, true); + } + if (ads->ds_txstatus0 & AR_TxBaStatus) { + ts->ts_flags |= ATH9K_TX_BA; + ts->ba_low = ads->AR_BaBitmapLow; + ts->ba_high = ads->AR_BaBitmapHigh; + } + + ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); + switch (ts->ts_rateindex) { + case 0: + ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); + break; + case 1: + ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); + break; + case 2: + ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); + break; + case 3: + ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); + break; + } + + ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); + ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); + ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); + ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); + ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); + ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); + ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); + ts->evm0 = ads->AR_TxEVM0; + ts->evm1 = ads->AR_TxEVM1; + ts->evm2 = ads->AR_TxEVM2; + ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); + ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); + ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); + ts->ts_antenna = 0; + + return 0; +} + +static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, + u32 pktLen, enum ath9k_pkt_type type, + u32 txPower, u32 keyIx, + enum ath9k_key_type keyType, u32 flags) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + txPower += ah->txpower_indexoffset; + if (txPower > 63) + txPower = 63; + + ads->ds_ctl0 = (pktLen & AR_FrameLen) + | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) + | SM(txPower, AR_XmitPower) + | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) + | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) + | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) + | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); + + ads->ds_ctl1 = + (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) + | SM(type, AR_FrameType) + | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) + | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) + | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); + + ads->ds_ctl6 = SM(keyType, AR_EncrType); + + if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) { + ads->ds_ctl8 = 0; + ads->ds_ctl9 = 0; + ads->ds_ctl10 = 0; + ads->ds_ctl11 = 0; + } +} + +static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, + void *lastds, + u32 durUpdateEn, u32 rtsctsRate, + u32 rtsctsDuration, + struct ath9k_11n_rate_series series[], + u32 nseries, u32 flags) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + struct ar5416_desc *last_ads = AR5416DESC(lastds); + u32 ds_ctl0; + + if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { + ds_ctl0 = ads->ds_ctl0; + + if (flags & ATH9K_TXDESC_RTSENA) { + ds_ctl0 &= ~AR_CTSEnable; + ds_ctl0 |= AR_RTSEnable; + } else { + ds_ctl0 &= ~AR_RTSEnable; + ds_ctl0 |= AR_CTSEnable; + } + + ads->ds_ctl0 = ds_ctl0; + } else { + ads->ds_ctl0 = + (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable)); + } + + ads->ds_ctl2 = set11nTries(series, 0) + | set11nTries(series, 1) + | set11nTries(series, 2) + | set11nTries(series, 3) + | (durUpdateEn ? AR_DurUpdateEna : 0) + | SM(0, AR_BurstDur); + + ads->ds_ctl3 = set11nRate(series, 0) + | set11nRate(series, 1) + | set11nRate(series, 2) + | set11nRate(series, 3); + + ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) + | set11nPktDurRTSCTS(series, 1); + + ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) + | set11nPktDurRTSCTS(series, 3); + + ads->ds_ctl7 = set11nRateFlags(series, 0) + | set11nRateFlags(series, 1) + | set11nRateFlags(series, 2) + | set11nRateFlags(series, 3) + | SM(rtsctsRate, AR_RTSCTSRate); + last_ads->ds_ctl2 = ads->ds_ctl2; + last_ads->ds_ctl3 = ads->ds_ctl3; +} + +static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, + u32 aggrLen) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); + ads->ds_ctl6 &= ~AR_AggrLen; + ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); +} + +static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, + u32 numDelims) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + unsigned int ctl6; + + ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); + + ctl6 = ads->ds_ctl6; + ctl6 &= ~AR_PadDelim; + ctl6 |= SM(numDelims, AR_PadDelim); + ads->ds_ctl6 = ctl6; +} + +static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_ctl1 |= AR_IsAggr; + ads->ds_ctl1 &= ~AR_MoreAggr; + ads->ds_ctl6 &= ~AR_PadDelim; +} + +static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); +} + +static void ar9002_hw_set11n_burstduration(struct ath_hw *ah, void *ds, + u32 burstDuration) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_ctl2 &= ~AR_BurstDur; + ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); +} + +static void ar9002_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, + u32 vmf) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + if (vmf) + ads->ds_ctl0 |= AR_VirtMoreFrag; + else + ads->ds_ctl0 &= ~AR_VirtMoreFrag; +} + +void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, + u32 size, u32 flags) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + struct ath9k_hw_capabilities *pCap = &ah->caps; + + ads->ds_ctl1 = size & AR_BufLen; + if (flags & ATH9K_RXDESC_INTREQ) + ads->ds_ctl1 |= AR_RxIntrReq; + + ads->ds_rxstatus8 &= ~AR_RxDone; + if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) + memset(&(ads->u), 0, sizeof(ads->u)); +} +EXPORT_SYMBOL(ath9k_hw_setuprxdesc); + +void ar9002_hw_attach_mac_ops(struct ath_hw *ah) +{ + struct ath_hw_ops *ops = ath9k_hw_ops(ah); + + ops->rx_enable = ar9002_hw_rx_enable; + ops->set_desc_link = ar9002_hw_set_desc_link; + ops->get_desc_link = ar9002_hw_get_desc_link; + ops->get_isr = ar9002_hw_get_isr; + ops->fill_txdesc = ar9002_hw_fill_txdesc; + ops->proc_txdesc = ar9002_hw_proc_txdesc; + ops->set11n_txdesc = ar9002_hw_set11n_txdesc; + ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario; + ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first; + ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle; + ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; + ops->clr11n_aggr = ar9002_hw_clr11n_aggr; + ops->set11n_burstduration = ar9002_hw_set11n_burstduration; + ops->set11n_virtualmorefrag = ar9002_hw_set11n_virtualmorefrag; +} diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index f32665d9ec0a..b15309caf1da 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -15,6 +15,7 @@ */ #include "hw.h" +#include "ar9003_mac.h" #include "ar9003_initvals.h" /* General hardware code for the AR9003 hadware family */ diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 81ad09a7ddff..cb93d2375e8d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -14,6 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "hw.h" +#include "ar9003_mac.h" static void ar9003_hw_rx_enable(struct ath_hw *hw) { diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 19e2c3cd1473..1a7cf20d31ea 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -20,6 +20,7 @@ #include "hw.h" #include "hw-ops.h" #include "rc.h" +#include "ar9003_mac.h" #define ATH9K_CLOCK_RATE_CCK 22 #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 6dbbab95df59..b711ec212abd 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -28,7 +28,6 @@ #include "reg.h" #include "phy.h" #include "btcoex.h" -#include "ar9003_mac.h" #include "../regd.h" #include "../debug.h" diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 22fa5125abff..05159584a544 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -16,451 +16,6 @@ #include "hw.h" -static void ar9002_hw_rx_enable(struct ath_hw *ah) -{ - REG_WRITE(ah, AR_CR, AR_CR_RXE); -} - -static void ar9002_hw_set_desc_link(void *ds, u32 ds_link) -{ - ((struct ath_desc *) ds)->ds_link = ds_link; -} - -static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link) -{ - *ds_link = &((struct ath_desc *)ds)->ds_link; -} - -static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) -{ - u32 isr = 0; - u32 mask2 = 0; - struct ath9k_hw_capabilities *pCap = &ah->caps; - u32 sync_cause = 0; - bool fatal_int = false; - struct ath_common *common = ath9k_hw_common(ah); - - if (!AR_SREV_9100(ah)) { - if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { - if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) - == AR_RTC_STATUS_ON) { - isr = REG_READ(ah, AR_ISR); - } - } - - sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & - AR_INTR_SYNC_DEFAULT; - - *masked = 0; - - if (!isr && !sync_cause) - return false; - } else { - *masked = 0; - isr = REG_READ(ah, AR_ISR); - } - - if (isr) { - if (isr & AR_ISR_BCNMISC) { - u32 isr2; - isr2 = REG_READ(ah, AR_ISR_S2); - if (isr2 & AR_ISR_S2_TIM) - mask2 |= ATH9K_INT_TIM; - if (isr2 & AR_ISR_S2_DTIM) - mask2 |= ATH9K_INT_DTIM; - if (isr2 & AR_ISR_S2_DTIMSYNC) - mask2 |= ATH9K_INT_DTIMSYNC; - if (isr2 & (AR_ISR_S2_CABEND)) - mask2 |= ATH9K_INT_CABEND; - if (isr2 & AR_ISR_S2_GTT) - mask2 |= ATH9K_INT_GTT; - if (isr2 & AR_ISR_S2_CST) - mask2 |= ATH9K_INT_CST; - if (isr2 & AR_ISR_S2_TSFOOR) - mask2 |= ATH9K_INT_TSFOOR; - } - - isr = REG_READ(ah, AR_ISR_RAC); - if (isr == 0xffffffff) { - *masked = 0; - return false; - } - - *masked = isr & ATH9K_INT_COMMON; - - if (ah->config.rx_intr_mitigation) { - if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) - *masked |= ATH9K_INT_RX; - } - - if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) - *masked |= ATH9K_INT_RX; - if (isr & - (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | - AR_ISR_TXEOL)) { - u32 s0_s, s1_s; - - *masked |= ATH9K_INT_TX; - - s0_s = REG_READ(ah, AR_ISR_S0_S); - ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); - ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); - - s1_s = REG_READ(ah, AR_ISR_S1_S); - ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); - ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); - } - - if (isr & AR_ISR_RXORN) { - ath_print(common, ATH_DBG_INTERRUPT, - "receive FIFO overrun interrupt\n"); - } - - if (!AR_SREV_9100(ah)) { - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - u32 isr5 = REG_READ(ah, AR_ISR_S5_S); - if (isr5 & AR_ISR_S5_TIM_TIMER) - *masked |= ATH9K_INT_TIM_TIMER; - } - } - - *masked |= mask2; - } - - if (AR_SREV_9100(ah)) - return true; - - if (isr & AR_ISR_GENTMR) { - u32 s5_s; - - s5_s = REG_READ(ah, AR_ISR_S5_S); - if (isr & AR_ISR_GENTMR) { - ah->intr_gen_timer_trigger = - MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); - - ah->intr_gen_timer_thresh = - MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); - - if (ah->intr_gen_timer_trigger) - *masked |= ATH9K_INT_GENTIMER; - - } - } - - if (sync_cause) { - fatal_int = - (sync_cause & - (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) - ? true : false; - - if (fatal_int) { - if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { - ath_print(common, ATH_DBG_ANY, - "received PCI FATAL interrupt\n"); - } - if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { - ath_print(common, ATH_DBG_ANY, - "received PCI PERR interrupt\n"); - } - *masked |= ATH9K_INT_FATAL; - } - if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { - ath_print(common, ATH_DBG_INTERRUPT, - "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); - REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); - REG_WRITE(ah, AR_RC, 0); - *masked |= ATH9K_INT_FATAL; - } - if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { - ath_print(common, ATH_DBG_INTERRUPT, - "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); - } - - REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); - (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); - } - - return true; -} - -static void ar9002_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, - bool is_firstseg, bool is_lastseg, - const void *ds0, dma_addr_t buf_addr, - unsigned int qcu) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_data = buf_addr; - - if (is_firstseg) { - ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore); - } else if (is_lastseg) { - ads->ds_ctl0 = 0; - ads->ds_ctl1 = seglen; - ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; - ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; - } else { - ads->ds_ctl0 = 0; - ads->ds_ctl1 = seglen | AR_TxMore; - ads->ds_ctl2 = 0; - ads->ds_ctl3 = 0; - } - ads->ds_txstatus0 = ads->ds_txstatus1 = 0; - ads->ds_txstatus2 = ads->ds_txstatus3 = 0; - ads->ds_txstatus4 = ads->ds_txstatus5 = 0; - ads->ds_txstatus6 = ads->ds_txstatus7 = 0; - ads->ds_txstatus8 = ads->ds_txstatus9 = 0; -} - -static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, - struct ath_tx_status *ts) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - if ((ads->ds_txstatus9 & AR_TxDone) == 0) - return -EINPROGRESS; - - ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); - ts->ts_tstamp = ads->AR_SendTimestamp; - ts->ts_status = 0; - ts->ts_flags = 0; - - if (ads->ds_txstatus1 & AR_FrmXmitOK) - ts->ts_status |= ATH9K_TX_ACKED; - if (ads->ds_txstatus1 & AR_ExcessiveRetries) - ts->ts_status |= ATH9K_TXERR_XRETRY; - if (ads->ds_txstatus1 & AR_Filtered) - ts->ts_status |= ATH9K_TXERR_FILT; - if (ads->ds_txstatus1 & AR_FIFOUnderrun) { - ts->ts_status |= ATH9K_TXERR_FIFO; - ath9k_hw_updatetxtriglevel(ah, true); - } - if (ads->ds_txstatus9 & AR_TxOpExceeded) - ts->ts_status |= ATH9K_TXERR_XTXOP; - if (ads->ds_txstatus1 & AR_TxTimerExpired) - ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; - - if (ads->ds_txstatus1 & AR_DescCfgErr) - ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; - if (ads->ds_txstatus1 & AR_TxDataUnderrun) { - ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; - ath9k_hw_updatetxtriglevel(ah, true); - } - if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { - ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; - ath9k_hw_updatetxtriglevel(ah, true); - } - if (ads->ds_txstatus0 & AR_TxBaStatus) { - ts->ts_flags |= ATH9K_TX_BA; - ts->ba_low = ads->AR_BaBitmapLow; - ts->ba_high = ads->AR_BaBitmapHigh; - } - - ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); - switch (ts->ts_rateindex) { - case 0: - ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); - break; - case 1: - ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); - break; - case 2: - ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); - break; - case 3: - ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); - break; - } - - ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); - ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); - ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); - ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); - ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); - ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); - ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); - ts->evm0 = ads->AR_TxEVM0; - ts->evm1 = ads->AR_TxEVM1; - ts->evm2 = ads->AR_TxEVM2; - ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); - ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); - ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); - ts->ts_antenna = 0; - - return 0; -} - -static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, - u32 pktLen, enum ath9k_pkt_type type, - u32 txPower, u32 keyIx, - enum ath9k_key_type keyType, u32 flags) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - txPower += ah->txpower_indexoffset; - if (txPower > 63) - txPower = 63; - - ads->ds_ctl0 = (pktLen & AR_FrameLen) - | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) - | SM(txPower, AR_XmitPower) - | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) - | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) - | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) - | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); - - ads->ds_ctl1 = - (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) - | SM(type, AR_FrameType) - | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) - | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) - | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); - - ads->ds_ctl6 = SM(keyType, AR_EncrType); - - if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) { - ads->ds_ctl8 = 0; - ads->ds_ctl9 = 0; - ads->ds_ctl10 = 0; - ads->ds_ctl11 = 0; - } -} - -static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, - void *lastds, - u32 durUpdateEn, u32 rtsctsRate, - u32 rtsctsDuration, - struct ath9k_11n_rate_series series[], - u32 nseries, u32 flags) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - struct ar5416_desc *last_ads = AR5416DESC(lastds); - u32 ds_ctl0; - - if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { - ds_ctl0 = ads->ds_ctl0; - - if (flags & ATH9K_TXDESC_RTSENA) { - ds_ctl0 &= ~AR_CTSEnable; - ds_ctl0 |= AR_RTSEnable; - } else { - ds_ctl0 &= ~AR_RTSEnable; - ds_ctl0 |= AR_CTSEnable; - } - - ads->ds_ctl0 = ds_ctl0; - } else { - ads->ds_ctl0 = - (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable)); - } - - ads->ds_ctl2 = set11nTries(series, 0) - | set11nTries(series, 1) - | set11nTries(series, 2) - | set11nTries(series, 3) - | (durUpdateEn ? AR_DurUpdateEna : 0) - | SM(0, AR_BurstDur); - - ads->ds_ctl3 = set11nRate(series, 0) - | set11nRate(series, 1) - | set11nRate(series, 2) - | set11nRate(series, 3); - - ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) - | set11nPktDurRTSCTS(series, 1); - - ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) - | set11nPktDurRTSCTS(series, 3); - - ads->ds_ctl7 = set11nRateFlags(series, 0) - | set11nRateFlags(series, 1) - | set11nRateFlags(series, 2) - | set11nRateFlags(series, 3) - | SM(rtsctsRate, AR_RTSCTSRate); - last_ads->ds_ctl2 = ads->ds_ctl2; - last_ads->ds_ctl3 = ads->ds_ctl3; -} - -static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, - u32 aggrLen) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); - ads->ds_ctl6 &= ~AR_AggrLen; - ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); -} - -static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, - u32 numDelims) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - unsigned int ctl6; - - ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); - - ctl6 = ads->ds_ctl6; - ctl6 &= ~AR_PadDelim; - ctl6 |= SM(numDelims, AR_PadDelim); - ads->ds_ctl6 = ctl6; -} - -static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_ctl1 |= AR_IsAggr; - ads->ds_ctl1 &= ~AR_MoreAggr; - ads->ds_ctl6 &= ~AR_PadDelim; -} - -static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); -} - -static void ar9002_hw_set11n_burstduration(struct ath_hw *ah, void *ds, - u32 burstDuration) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_ctl2 &= ~AR_BurstDur; - ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); -} - -static void ar9002_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, - u32 vmf) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - if (vmf) - ads->ds_ctl0 |= AR_VirtMoreFrag; - else - ads->ds_ctl0 &= ~AR_VirtMoreFrag; -} - -void ar9002_hw_attach_mac_ops(struct ath_hw *ah) -{ - struct ath_hw_ops *ops = ath9k_hw_ops(ah); - - ops->rx_enable = ar9002_hw_rx_enable; - ops->set_desc_link = ar9002_hw_set_desc_link; - ops->get_desc_link = ar9002_hw_get_desc_link; - ops->get_isr = ar9002_hw_get_isr; - ops->fill_txdesc = ar9002_hw_fill_txdesc; - ops->proc_txdesc = ar9002_hw_proc_txdesc; - ops->set11n_txdesc = ar9002_hw_set11n_txdesc; - ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario; - ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first; - ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle; - ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; - ops->clr11n_aggr = ar9002_hw_clr11n_aggr; - ops->set11n_burstduration = ar9002_hw_set11n_burstduration; - ops->set11n_virtualmorefrag = ar9002_hw_set11n_virtualmorefrag; -} - static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, struct ath9k_tx_queue_info *qi) { @@ -1122,22 +677,6 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, } EXPORT_SYMBOL(ath9k_hw_rxprocdesc); -void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 size, u32 flags) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - struct ath9k_hw_capabilities *pCap = &ah->caps; - - ads->ds_ctl1 = size & AR_BufLen; - if (flags & ATH9K_RXDESC_INTREQ) - ads->ds_ctl1 |= AR_RxIntrReq; - - ads->ds_rxstatus8 &= ~AR_RxDone; - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) - memset(&(ads->u), 0, sizeof(ads->u)); -} -EXPORT_SYMBOL(ath9k_hw_setuprxdesc); - /* * This can stop or re-enables RX. * diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 0d492192de94..eb430c471c5c 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -354,7 +354,6 @@ struct ar5416_desc { #define AR_DestIdxValid 0x40000000 #define AR_CTSEnable 0x80000000 -#define AR_BufLen 0x00000fff #define AR_TxMore 0x00001000 #define AR_DestIdx 0x000fe000 #define AR_DestIdx_S 13 @@ -494,7 +493,6 @@ struct ar5416_desc { #define AR_RxCTLRsvd00 0xffffffff -#define AR_BufLen 0x00000fff #define AR_RxCtlRsvd00 0x00001000 #define AR_RxIntrReq 0x00002000 #define AR_RxCtlRsvd01 0xffffc000 diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index ffb599c49185..cb4995ccbc14 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -15,6 +15,7 @@ */ #include "ath9k.h" +#include "ar9003_mac.h" #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 550253fe61fb..7dae199361bf 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -15,6 +15,7 @@ */ #include "ath9k.h" +#include "ar9003_mac.h" #define BITS_PER_BYTE 8 #define OFDM_PLCP_BITS 22 -- cgit v1.2.3 From 994089db034059f4b545ddef9fab466091894071 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:29 -0400 Subject: ath9k_hw: Fill descriptor abstrations for AR9003 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 234 +++++++++++++++++++++++++++- drivers/net/wireless/ath/ath9k/ar9003_mac.h | 20 +++ drivers/net/wireless/ath/ath9k/mac.h | 7 +- 3 files changed, 254 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index cb93d2375e8d..1a8c1ba538b4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -168,23 +168,169 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) return true; } +static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) +{ + int checksum; + + checksum = ads->info + ads->link + + ads->data0 + ads->ctl3 + + ads->data1 + ads->ctl5 + + ads->data2 + ads->ctl7 + + ads->data3 + ads->ctl9; + + return ((checksum & 0xffff) + (checksum >> 16)) & AR_TxPtrChkSum; +} + static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, bool is_firstseg, bool is_lastseg, const void *ds0, dma_addr_t buf_addr, unsigned int qcu) { + struct ar9003_txc *ads = (struct ar9003_txc *) ds; + unsigned int descid = 0; + + ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) | + (1 << AR_TxRxDesc_S) | + (1 << AR_CtrlStat_S) | + (qcu << AR_TxQcuNum_S) | 0x17; + + ads->data0 = buf_addr; + ads->data1 = 0; + ads->data2 = 0; + ads->data3 = 0; + + ads->ctl3 = (seglen << AR_BufLen_S); + ads->ctl3 &= AR_BufLen; + + /* Fill in pointer checksum and descriptor id */ + ads->ctl10 = ar9003_calc_ptr_chksum(ads); + ads->ctl10 |= (descid << AR_TxDescId_S); + + if (is_firstseg) { + ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore); + } else if (is_lastseg) { + ads->ctl11 = 0; + ads->ctl12 = 0; + ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13; + ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14; + } else { + /* XXX Intermediate descriptor in a multi-descriptor frame.*/ + ads->ctl11 = 0; + ads->ctl12 = AR_TxMore; + ads->ctl13 = 0; + ads->ctl14 = 0; + } } static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_status *ts) { + struct ar9003_txs *ads; + + ads = &ah->ts_ring[ah->ts_tail]; + + if ((ads->status8 & AR_TxDone) == 0) + return -EINPROGRESS; + + ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; + + if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) || + (MS(ads->ds_info, AR_TxRxDesc) != 1)) { + ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT, + "Tx Descriptor error %x\n", ads->ds_info); + memset(ads, 0, sizeof(*ads)); + return -EIO; + } + + ts->qid = MS(ads->ds_info, AR_TxQcuNum); + ts->desc_id = MS(ads->status1, AR_TxDescId); + ts->ts_seqnum = MS(ads->status8, AR_SeqNum); + ts->ts_tstamp = ads->status4; + ts->ts_status = 0; + ts->ts_flags = 0; + + if (ads->status3 & AR_ExcessiveRetries) + ts->ts_status |= ATH9K_TXERR_XRETRY; + if (ads->status3 & AR_Filtered) + ts->ts_status |= ATH9K_TXERR_FILT; + if (ads->status3 & AR_FIFOUnderrun) { + ts->ts_status |= ATH9K_TXERR_FIFO; + ath9k_hw_updatetxtriglevel(ah, true); + } + if (ads->status8 & AR_TxOpExceeded) + ts->ts_status |= ATH9K_TXERR_XTXOP; + if (ads->status3 & AR_TxTimerExpired) + ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; + + if (ads->status3 & AR_DescCfgErr) + ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; + if (ads->status3 & AR_TxDataUnderrun) { + ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; + ath9k_hw_updatetxtriglevel(ah, true); + } + if (ads->status3 & AR_TxDelimUnderrun) { + ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; + ath9k_hw_updatetxtriglevel(ah, true); + } + if (ads->status2 & AR_TxBaStatus) { + ts->ts_flags |= ATH9K_TX_BA; + ts->ba_low = ads->status5; + ts->ba_high = ads->status6; + } + + ts->ts_rateindex = MS(ads->status8, AR_FinalTxIdx); + + ts->ts_rssi = MS(ads->status7, AR_TxRSSICombined); + ts->ts_rssi_ctl0 = MS(ads->status2, AR_TxRSSIAnt00); + ts->ts_rssi_ctl1 = MS(ads->status2, AR_TxRSSIAnt01); + ts->ts_rssi_ctl2 = MS(ads->status2, AR_TxRSSIAnt02); + ts->ts_rssi_ext0 = MS(ads->status7, AR_TxRSSIAnt10); + ts->ts_rssi_ext1 = MS(ads->status7, AR_TxRSSIAnt11); + ts->ts_rssi_ext2 = MS(ads->status7, AR_TxRSSIAnt12); + ts->ts_shortretry = MS(ads->status3, AR_RTSFailCnt); + ts->ts_longretry = MS(ads->status3, AR_DataFailCnt); + ts->ts_virtcol = MS(ads->status3, AR_VirtRetryCnt); + ts->ts_antenna = 0; + + ts->tid = MS(ads->status8, AR_TxTid); + + memset(ads, 0, sizeof(*ads)); + return 0; } + static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, - u32 pktLen, enum ath9k_pkt_type type, u32 txPower, - u32 keyIx, enum ath9k_key_type keyType, u32 flags) + u32 pktlen, enum ath9k_pkt_type type, u32 txpower, + u32 keyIx, enum ath9k_key_type keyType, u32 flags) { - + struct ar9003_txc *ads = (struct ar9003_txc *) ds; + + txpower += ah->txpower_indexoffset; + if (txpower > 63) + txpower = 63; + + ads->ctl11 = (pktlen & AR_FrameLen) + | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) + | SM(txpower, AR_XmitPower) + | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) + | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) + | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) + | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0); + + ads->ctl12 = + (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) + | SM(type, AR_FrameType) + | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) + | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) + | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); + + ads->ctl17 = SM(keyType, AR_EncrType); + ads->ctl18 = 0; + ads->ctl19 = AR_Not_Sounding; + + ads->ctl20 = 0; + ads->ctl21 = 0; + ads->ctl22 = 0; } static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, @@ -194,41 +340,119 @@ static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, struct ath9k_11n_rate_series series[], u32 nseries, u32 flags) { + struct ar9003_txc *ads = (struct ar9003_txc *) ds; + struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds; + u_int32_t ctl11; + + if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { + ctl11 = ads->ctl11; + + if (flags & ATH9K_TXDESC_RTSENA) { + ctl11 &= ~AR_CTSEnable; + ctl11 |= AR_RTSEnable; + } else { + ctl11 &= ~AR_RTSEnable; + ctl11 |= AR_CTSEnable; + } + + ads->ctl11 = ctl11; + } else { + ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable)); + } + ads->ctl13 = set11nTries(series, 0) + | set11nTries(series, 1) + | set11nTries(series, 2) + | set11nTries(series, 3) + | (durUpdateEn ? AR_DurUpdateEna : 0) + | SM(0, AR_BurstDur); + + ads->ctl14 = set11nRate(series, 0) + | set11nRate(series, 1) + | set11nRate(series, 2) + | set11nRate(series, 3); + + ads->ctl15 = set11nPktDurRTSCTS(series, 0) + | set11nPktDurRTSCTS(series, 1); + + ads->ctl16 = set11nPktDurRTSCTS(series, 2) + | set11nPktDurRTSCTS(series, 3); + + ads->ctl18 = set11nRateFlags(series, 0) + | set11nRateFlags(series, 1) + | set11nRateFlags(series, 2) + | set11nRateFlags(series, 3) + | SM(rtsctsRate, AR_RTSCTSRate); + ads->ctl19 = AR_Not_Sounding; + + last_ads->ctl13 = ads->ctl13; + last_ads->ctl14 = ads->ctl14; } static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, u32 aggrLen) { + struct ar9003_txc *ads = (struct ar9003_txc *) ds; + + ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); + ads->ctl17 &= ~AR_AggrLen; + ads->ctl17 |= SM(aggrLen, AR_AggrLen); } static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, u32 numDelims) { - + struct ar9003_txc *ads = (struct ar9003_txc *) ds; + unsigned int ctl17; + + ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); + + /* + * We use a stack variable to manipulate ctl6 to reduce uncached + * read modify, modfiy, write. + */ + ctl17 = ads->ctl17; + ctl17 &= ~AR_PadDelim; + ctl17 |= SM(numDelims, AR_PadDelim); + ads->ctl17 = ctl17; } static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) { + struct ar9003_txc *ads = (struct ar9003_txc *) ds; + ads->ctl12 |= AR_IsAggr; + ads->ctl12 &= ~AR_MoreAggr; + ads->ctl17 &= ~AR_PadDelim; } static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds) { + struct ar9003_txc *ads = (struct ar9003_txc *) ds; + ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr); } static void ar9003_hw_set11n_burstduration(struct ath_hw *ah, void *ds, u32 burstDuration) { + struct ar9003_txc *ads = (struct ar9003_txc *) ds; + + ads->ctl13 &= ~AR_BurstDur; + ads->ctl13 |= SM(burstDuration, AR_BurstDur); } static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, - u32 vmf) + u32 vmf) { + struct ar9003_txc *ads = (struct ar9003_txc *) ds; + if (vmf) + ads->ctl11 |= AR_VirtMoreFrag; + else + ads->ctl11 &= ~AR_VirtMoreFrag; } void ar9003_hw_attach_mac_ops(struct ath_hw *hw) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index ef7999636ea0..f17558b14539 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h @@ -20,7 +20,25 @@ #define AR_DescId 0xffff0000 #define AR_DescId_S 16 #define AR_CtrlStat 0x00004000 +#define AR_CtrlStat_S 14 #define AR_TxRxDesc 0x00008000 +#define AR_TxRxDesc_S 15 +#define AR_TxQcuNum 0x00000f00 +#define AR_TxQcuNum_S 8 + +#define AR_BufLen 0x0fff0000 +#define AR_BufLen_S 16 + +#define AR_TxDescId 0xffff0000 +#define AR_TxDescId_S 16 +#define AR_TxPtrChkSum 0x0000ffff + +#define AR_TxTid 0xf0000000 +#define AR_TxTid_S 28 + +#define AR_LowRxChain 0x00004000 + +#define AR_Not_Sounding 0x20000000 #define MAP_ISR_S2_CST 6 #define MAP_ISR_S2_GTT 6 @@ -30,6 +48,8 @@ #define MAP_ISR_S2_DTIM 7 #define MAP_ISR_S2_TSFOOR 4 +#define AR9003TXC_CONST(_ds) ((const struct ar9003_txc *) _ds) + struct ar9003_rxs { u32 ds_info; u32 status1; diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index eb430c471c5c..b591dc27c325 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -116,7 +116,10 @@ struct ath_tx_status { int8_t ts_rssi_ext0; int8_t ts_rssi_ext1; int8_t ts_rssi_ext2; - u8 pad[3]; + u8 qid; + u16 desc_id; + u8 tid; + u8 pad[2]; u32 ba_low; u32 ba_high; u32 evm0; @@ -260,7 +263,7 @@ struct ath_desc { #define ATH9K_TXDESC_EXT_AND_CTL 0x0080 #define ATH9K_TXDESC_VMF 0x0100 #define ATH9K_TXDESC_FRAG_IS_ON 0x0200 -#define ATH9K_TXDESC_CAB 0x0400 +#define ATH9K_TXDESC_LOWRXCHAIN 0x0400 #define ATH9K_RXDESC_INTREQ 0x0020 -- cgit v1.2.3 From a9616f417eb0e529023c44dac61420f3df39d8f7 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:30 -0400 Subject: ath9k: add RXLP and RXHP to debugfs counters Signed-off-by: Luis R. Rodriguez Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 22 ++++++++++++++++++---- drivers/net/wireless/ath/ath9k/debug.h | 4 ++++ 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index b22d46509b67..ab59e2ec18c6 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -179,8 +179,15 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) { if (status) sc->debug.stats.istats.total++; - if (status & ATH9K_INT_RX) - sc->debug.stats.istats.rxok++; + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { + if (status & ATH9K_INT_RXLP) + sc->debug.stats.istats.rxlp++; + if (status & ATH9K_INT_RXHP) + sc->debug.stats.istats.rxhp++; + } else { + if (status & ATH9K_INT_RX) + sc->debug.stats.istats.rxok++; + } if (status & ATH9K_INT_RXEOL) sc->debug.stats.istats.rxeol++; if (status & ATH9K_INT_RXORN) @@ -222,8 +229,15 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, char buf[512]; unsigned int len = 0; - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok); + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "RXLP", sc->debug.stats.istats.rxlp); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "RXHP", sc->debug.stats.istats.rxhp); + } else { + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok); + } len += snprintf(buf + len, sizeof(buf) - len, "%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol); len += snprintf(buf + len, sizeof(buf) - len, diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index b2af9de755e6..c545960e7ec5 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -35,6 +35,8 @@ struct ath_buf; * struct ath_interrupt_stats - Contains statistics about interrupts * @total: Total no. of interrupts generated so far * @rxok: RX with no errors + * @rxlp: RX with low priority RX + * @rxhp: RX with high priority, uapsd only * @rxeol: RX with no more RXDESC available * @rxorn: RX FIFO overrun * @txok: TX completed at the requested rate @@ -55,6 +57,8 @@ struct ath_buf; struct ath_interrupt_stats { u32 total; u32 rxok; + u32 rxlp; + u32 rxhp; u32 rxeol; u32 rxorn; u32 txok; -- cgit v1.2.3 From 79de23751a79a1270e45559296256ecb3dd35e12 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:31 -0400 Subject: ath9k_hw: enable CRC check of descriptors for AR9003 Enable CRC check on the descriptor fetched from host on AR9003 upon reseting the TX queue. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/mac.c | 3 +++ drivers/net/wireless/ath/ath9k/reg.h | 4 ++++ 2 files changed, 7 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 05159584a544..44ea43a143d8 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -569,6 +569,9 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) AR_D_MISC_POST_FR_BKOFF_DIS); } + if (AR_SREV_9300_20_OR_LATER(ah)) + REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN); + if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE) ah->txok_interrupt_mask |= 1 << q; else diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index ff8914049c53..d4371a43bdaa 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -478,6 +478,10 @@ #define AR_Q_RDYTIMESHDN 0x0a40 #define AR_Q_RDYTIMESHDN_M 0x000003FF +/* MAC Descriptor CRC check */ +#define AR_Q_DESC_CRCCHK 0xa44 +/* Enable CRC check on the descriptor fetched from host */ +#define AR_Q_DESC_CRCCHK_EN 1 #define AR_NUM_DCU 10 #define AR_DCU_0 0x0001 -- cgit v1.2.3 From 3deb4da554c3ad9b059f51d19eebadf8525da4a4 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:32 -0400 Subject: ath9k_hw: set cwmin and cwmax to 0 for for AR9003 upon txq reset Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/mac.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 44ea43a143d8..c003baf2e937 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -533,6 +533,12 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) AR_D_MISC_ARB_LOCKOUT_CNTRL_S) | AR_D_MISC_BEACON_USE | AR_D_MISC_POST_FR_BKOFF_DIS); + /* cwmin and cwmax should be 0 for beacon queue */ + if (AR_SREV_9300_20_OR_LATER(ah)) { + REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN) + | SM(0, AR_D_LCL_IFS_CWMAX) + | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); + } break; case ATH9K_TX_QUEUE_CAB: REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) -- cgit v1.2.3 From 4adfcdedd4e0c05c1b659da5f2b8bc4e2d4a86df Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:33 -0400 Subject: ath9k: Setup appropriate tx desc for regular dma and edma Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 +- drivers/net/wireless/ath/ath9k/init.c | 26 ++++++++++++++++---------- drivers/net/wireless/ath/ath9k/recv.c | 2 +- drivers/net/wireless/ath/ath9k/xmit.c | 4 ++-- 4 files changed, 20 insertions(+), 14 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index a11d830d76a9..f67be52591d5 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -123,7 +123,7 @@ struct ath_descdma { int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, struct list_head *head, const char *name, - int nbuf, int ndesc); + int nbuf, int ndesc, bool is_tx); void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, struct list_head *head); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 1956c611503e..58a87f7931df 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -233,31 +233,37 @@ static int ath9k_reg_notifier(struct wiphy *wiphy, */ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, struct list_head *head, const char *name, - int nbuf, int ndesc) + int nbuf, int ndesc, bool is_tx) { #define DS2PHYS(_dd, _ds) \ ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_desc *ds; + u8 *ds; struct ath_buf *bf; - int i, bsize, error; + int i, bsize, error, desc_len; ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", name, nbuf, ndesc); INIT_LIST_HEAD(head); + + if (is_tx) + desc_len = sc->sc_ah->caps.tx_desc_len; + else + desc_len = sizeof(struct ath_desc); + /* ath_desc must be a multiple of DWORDs */ - if ((sizeof(struct ath_desc) % 4) != 0) { + if ((desc_len % 4) != 0) { ath_print(common, ATH_DBG_FATAL, "ath_desc not DWORD aligned\n"); - BUG_ON((sizeof(struct ath_desc) % 4) != 0); + BUG_ON((desc_len % 4) != 0); error = -ENOMEM; goto fail; } - dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; + dd->dd_desc_len = desc_len * nbuf * ndesc; /* * Need additional DMA memory because we can't use @@ -270,7 +276,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, u32 dma_len; while (ndesc_skipped) { - dma_len = ndesc_skipped * sizeof(struct ath_desc); + dma_len = ndesc_skipped * desc_len; dd->dd_desc_len += dma_len; ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); @@ -284,7 +290,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, error = -ENOMEM; goto fail; } - ds = dd->dd_desc; + ds = (u8 *) dd->dd_desc; ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", name, ds, (u32) dd->dd_desc_len, ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); @@ -298,7 +304,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, } dd->dd_bufptr = bf; - for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { + for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { bf->bf_desc = ds; bf->bf_daddr = DS2PHYS(dd, ds); @@ -314,7 +320,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, ((caddr_t) dd->dd_desc + dd->dd_desc_len)); - ds += ndesc; + ds += (desc_len * ndesc); bf->bf_desc = ds; bf->bf_daddr = DS2PHYS(dd, ds); } diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index cb4995ccbc14..ac60c4ee62d3 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -325,7 +325,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) /* Initialize rx descriptors */ error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, - "rx", nbufs, 1); + "rx", nbufs, 1, 0); if (error != 0) { ath_print(common, ATH_DBG_FATAL, "failed to allocate rx descriptors: %d\n", diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 7dae199361bf..c32da053c6ed 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2152,7 +2152,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) spin_lock_init(&sc->tx.txbuflock); error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, - "tx", nbufs, 1); + "tx", nbufs, 1, 1); if (error != 0) { ath_print(common, ATH_DBG_FATAL, "Failed to allocate tx descriptors: %d\n", error); @@ -2160,7 +2160,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) } error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, - "beacon", ATH_BCBUF, 1); + "beacon", ATH_BCBUF, 1, 0); if (error != 0) { ath_print(common, ATH_DBG_FATAL, "Failed to allocate beacon descriptors: %d\n", error); -- cgit v1.2.3 From 5088c2f1a2475546d9a79b515bde6d65b8681e51 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:34 -0400 Subject: ath9k: Initialize and configure tx status for EDMA Also add a function to clean up tx status ring. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 6 ++++- drivers/net/wireless/ath/ath9k/hw.c | 1 + drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/xmit.c | 46 +++++++++++++++++++++++++++++++++- 4 files changed, 52 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index f67be52591d5..2d3e42ad3b05 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -114,8 +114,10 @@ enum buffer_type { #define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY) #define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY) +#define ATH_TXSTATUS_RING_SIZE 64 + struct ath_descdma { - struct ath_desc *dd_desc; + void *dd_desc; dma_addr_t dd_desc_paddr; u32 dd_desc_len; struct ath_buf *dd_bufptr; @@ -515,6 +517,8 @@ struct ath_softc { struct ath_beacon_config cur_beacon_conf; struct delayed_work tx_complete_work; struct ath_btcoex btcoex; + + struct ath_descdma txsdma; }; struct ath_wiphy { diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 1a7cf20d31ea..55f79f5712d4 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2093,6 +2093,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH; pCap->rx_status_len = sizeof(struct ar9003_rxs); pCap->tx_desc_len = sizeof(struct ar9003_txc); + pCap->txs_len = sizeof(struct ar9003_txs); } else { pCap->tx_desc_len = sizeof(struct ath_desc); } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index b711ec212abd..9d3796a68920 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -209,6 +209,7 @@ struct ath9k_hw_capabilities { u8 rx_lp_qdepth; u8 rx_status_len; u8 tx_desc_len; + u8 txs_len; }; struct ath9k_ops_config { diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index c32da053c6ed..f9f7445f6652 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2144,6 +2144,41 @@ void ath_tx_tasklet(struct ath_softc *sc) /* Init, Cleanup */ /*****************/ +static int ath_txstatus_setup(struct ath_softc *sc, int size) +{ + struct ath_descdma *dd = &sc->txsdma; + u8 txs_len = sc->sc_ah->caps.txs_len; + + dd->dd_desc_len = size * txs_len; + dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, + &dd->dd_desc_paddr, GFP_KERNEL); + if (!dd->dd_desc) + return -ENOMEM; + + return 0; +} + +static int ath_tx_edma_init(struct ath_softc *sc) +{ + int err; + + err = ath_txstatus_setup(sc, ATH_TXSTATUS_RING_SIZE); + if (!err) + ath9k_hw_setup_statusring(sc->sc_ah, sc->txsdma.dd_desc, + sc->txsdma.dd_desc_paddr, + ATH_TXSTATUS_RING_SIZE); + + return err; +} + +static void ath_tx_edma_cleanup(struct ath_softc *sc) +{ + struct ath_descdma *dd = &sc->txsdma; + + dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, + dd->dd_desc_paddr); +} + int ath_tx_init(struct ath_softc *sc, int nbufs) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); @@ -2160,7 +2195,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) } error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, - "beacon", ATH_BCBUF, 1, 0); + "beacon", ATH_BCBUF, 1, 1); if (error != 0) { ath_print(common, ATH_DBG_FATAL, "Failed to allocate beacon descriptors: %d\n", error); @@ -2169,6 +2204,12 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work); + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { + error = ath_tx_edma_init(sc); + if (error) + goto err; + } + err: if (error != 0) ath_tx_cleanup(sc); @@ -2183,6 +2224,9 @@ void ath_tx_cleanup(struct ath_softc *sc) if (sc->tx.txdma.dd_desc_len != 0) ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf); + + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) + ath_tx_edma_cleanup(sc); } void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) -- cgit v1.2.3 From eb8232535bbeaf51f7c4826265ad96bf966829f3 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:35 -0400 Subject: ath9k_hw: Compute pointer checksum over the link descriptor Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 36 +++++++++++++++++------------ 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 1a8c1ba538b4..582c88050664 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -21,14 +21,33 @@ static void ar9003_hw_rx_enable(struct ath_hw *hw) REG_WRITE(hw, AR_CR, 0); } +static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) +{ + int checksum; + + checksum = ads->info + ads->link + + ads->data0 + ads->ctl3 + + ads->data1 + ads->ctl5 + + ads->data2 + ads->ctl7 + + ads->data3 + ads->ctl9; + + return ((checksum & 0xffff) + (checksum >> 16)) & AR_TxPtrChkSum; +} + static void ar9003_hw_set_desc_link(void *ds, u32 ds_link) { - ((struct ar9003_txc *) ds)->link = ds_link; + struct ar9003_txc *ads = ds; + + ads->link = ds_link; + ads->ctl10 &= ~AR_TxPtrChkSum; + ads->ctl10 |= ar9003_calc_ptr_chksum(ads); } static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link) { - *ds_link = &((struct ar9003_txc *) ds)->link; + struct ar9003_txc *ads = ds; + + *ds_link = &ads->link; } static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) @@ -168,19 +187,6 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) return true; } -static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) -{ - int checksum; - - checksum = ads->info + ads->link - + ads->data0 + ads->ctl3 - + ads->data1 + ads->ctl5 - + ads->data2 + ads->ctl7 - + ads->data3 + ads->ctl9; - - return ((checksum & 0xffff) + (checksum >> 16)) & AR_TxPtrChkSum; -} - static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, bool is_firstseg, bool is_lastseg, const void *ds0, dma_addr_t buf_addr, -- cgit v1.2.3 From e5003249ae7165654e13fd4809caa346820547f5 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:36 -0400 Subject: ath9k: Add Tx EDMA support Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 6 + drivers/net/wireless/ath/ath9k/main.c | 8 +- drivers/net/wireless/ath/ath9k/xmit.c | 264 +++++++++++++++++++++++++-------- 3 files changed, 218 insertions(+), 60 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 2d3e42ad3b05..fbb7dec6ddeb 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -190,6 +190,7 @@ enum ATH_AGGR_STATUS { ATH_AGGR_LIMITED, }; +#define ATH_TXFIFO_DEPTH 8 struct ath_txq { u32 axq_qnum; u32 *axq_link; @@ -199,6 +200,10 @@ struct ath_txq { bool stopped; bool axq_tx_inprogress; struct list_head axq_acq; + struct list_head txq_fifo[ATH_TXFIFO_DEPTH]; + struct list_head txq_fifo_pending; + u8 txq_headidx; + u8 txq_tailidx; }; #define AGGR_CLEANUP BIT(1) @@ -268,6 +273,7 @@ int ath_txq_update(struct ath_softc *sc, int qnum, int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath_tx_control *txctl); void ath_tx_tasklet(struct ath_softc *sc); +void ath_tx_edma_tasklet(struct ath_softc *sc); void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb); bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno); void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 92f6fdc30076..1f4ea74bf4ca 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -429,8 +429,12 @@ void ath9k_tasklet(unsigned long data) spin_unlock_bh(&sc->rx.rxflushlock); } - if (status & ATH9K_INT_TX) - ath_tx_tasklet(sc); + if (status & ATH9K_INT_TX) { + if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) + ath_tx_edma_tasklet(sc); + else + ath_tx_tasklet(sc); + } if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { /* diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index f9f7445f6652..c2b45030d0b4 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -92,7 +92,6 @@ static int ath_max_4ms_framelen[3][16] = { } }; - /*********************/ /* Aggregation logic */ /*********************/ @@ -379,7 +378,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, } } - if (bf_next == NULL) { + if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && + bf_next == NULL) { /* * Make sure the last desc is reclaimed if it * not a holding desc. @@ -413,36 +413,43 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, !txfail, sendbar); } else { /* retry the un-acked ones */ - if (bf->bf_next == NULL && bf_last->bf_stale) { - struct ath_buf *tbf; - - tbf = ath_clone_txbuf(sc, bf_last); - /* - * Update tx baw and complete the frame with - * failed status if we run out of tx buf - */ - if (!tbf) { - spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, - bf->bf_seqno); - spin_unlock_bh(&txq->axq_lock); - - bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, ts, nbad, - 0, false); - ath_tx_complete_buf(sc, bf, txq, - &bf_head, ts, 0, 0); - break; + if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { + if (bf->bf_next == NULL && bf_last->bf_stale) { + struct ath_buf *tbf; + + tbf = ath_clone_txbuf(sc, bf_last); + /* + * Update tx baw and complete the + * frame with failed status if we + * run out of tx buf. + */ + if (!tbf) { + spin_lock_bh(&txq->axq_lock); + ath_tx_update_baw(sc, tid, + bf->bf_seqno); + spin_unlock_bh(&txq->axq_lock); + + bf->bf_state.bf_type |= + BUF_XRETRY; + ath_tx_rc_status(bf, ts, nbad, + 0, false); + ath_tx_complete_buf(sc, bf, txq, + &bf_head, + ts, 0, 0); + break; + } + + ath9k_hw_cleartxdesc(sc->sc_ah, + tbf->bf_desc); + list_add_tail(&tbf->list, &bf_head); + } else { + /* + * Clear descriptor status words for + * software retry + */ + ath9k_hw_cleartxdesc(sc->sc_ah, + bf->bf_desc); } - - ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc); - list_add_tail(&tbf->list, &bf_head); - } else { - /* - * Clear descriptor status words for - * software retry - */ - ath9k_hw_cleartxdesc(sc->sc_ah, bf->bf_desc); } /* @@ -855,7 +862,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_tx_queue_info qi; - int qnum; + int qnum, i; memset(&qi, 0, sizeof(qi)); qi.tqi_subtype = subtype; @@ -910,6 +917,11 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) txq->axq_depth = 0; txq->axq_tx_inprogress = false; sc->tx.txqsetup |= 1<txq_headidx = txq->txq_tailidx = 0; + for (i = 0; i < ATH_TXFIFO_DEPTH; i++) + INIT_LIST_HEAD(&txq->txq_fifo[i]); + INIT_LIST_HEAD(&txq->txq_fifo_pending); } return &sc->tx.txq[qnum]; } @@ -1042,30 +1054,49 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) for (;;) { spin_lock_bh(&txq->axq_lock); - if (list_empty(&txq->axq_q)) { - txq->axq_link = NULL; - spin_unlock_bh(&txq->axq_lock); - break; - } - - bf = list_first_entry(&txq->axq_q, struct ath_buf, list); + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { + if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) { + txq->txq_headidx = txq->txq_tailidx = 0; + spin_unlock_bh(&txq->axq_lock); + break; + } else { + bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx], + struct ath_buf, list); + } + } else { + if (list_empty(&txq->axq_q)) { + txq->axq_link = NULL; + spin_unlock_bh(&txq->axq_lock); + break; + } + bf = list_first_entry(&txq->axq_q, struct ath_buf, + list); - if (bf->bf_stale) { - list_del(&bf->list); - spin_unlock_bh(&txq->axq_lock); + if (bf->bf_stale) { + list_del(&bf->list); + spin_unlock_bh(&txq->axq_lock); - spin_lock_bh(&sc->tx.txbuflock); - list_add_tail(&bf->list, &sc->tx.txbuf); - spin_unlock_bh(&sc->tx.txbuflock); - continue; + spin_lock_bh(&sc->tx.txbuflock); + list_add_tail(&bf->list, &sc->tx.txbuf); + spin_unlock_bh(&sc->tx.txbuflock); + continue; + } } lastbf = bf->bf_lastbf; if (!retry_tx) lastbf->bf_tx_aborted = true; - /* remove ath_buf's of the same mpdu from txq */ - list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { + list_cut_position(&bf_head, + &txq->txq_fifo[txq->txq_tailidx], + &lastbf->list); + INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); + } else { + /* remove ath_buf's of the same mpdu from txq */ + list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); + } + txq->axq_depth--; spin_unlock_bh(&txq->axq_lock); @@ -1088,6 +1119,27 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) spin_unlock_bh(&txq->axq_lock); } } + + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { + spin_lock_bh(&txq->axq_lock); + while (!list_empty(&txq->txq_fifo_pending)) { + bf = list_first_entry(&txq->txq_fifo_pending, + struct ath_buf, list); + list_cut_position(&bf_head, + &txq->txq_fifo_pending, + &bf->bf_lastbf->list); + spin_unlock_bh(&txq->axq_lock); + + if (bf_isampdu(bf)) + ath_tx_complete_aggr(sc, txq, bf, &bf_head, + &ts, 0); + else + ath_tx_complete_buf(sc, bf, txq, &bf_head, + &ts, 0, 0); + spin_lock_bh(&txq->axq_lock); + } + spin_unlock_bh(&txq->axq_lock); + } } void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) @@ -1225,25 +1277,47 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, bf = list_first_entry(head, struct ath_buf, list); - list_splice_tail_init(head, &txq->axq_q); - txq->axq_depth++; - ath_print(common, ATH_DBG_QUEUE, "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); - if (txq->axq_link == NULL) { + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { + if (txq->axq_depth >= ATH_TXFIFO_DEPTH) { + list_splice_tail_init(head, &txq->txq_fifo_pending); + return; + } + if (!list_empty(&txq->txq_fifo[txq->txq_headidx])) + ath_print(common, ATH_DBG_XMIT, + "Initializing tx fifo %d which " + "is non-empty\n", + txq->txq_headidx); + INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]); + list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]); + INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH); ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); ath_print(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n", txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); } else { - *txq->axq_link = bf->bf_daddr; - ath_print(common, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n", - txq->axq_qnum, txq->axq_link, - ito64(bf->bf_daddr), bf->bf_desc); + list_splice_tail_init(head, &txq->axq_q); + + if (txq->axq_link == NULL) { + ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); + ath_print(common, ATH_DBG_XMIT, + "TXDP[%u] = %llx (%p)\n", + txq->axq_qnum, ito64(bf->bf_daddr), + bf->bf_desc); + } else { + *txq->axq_link = bf->bf_daddr; + ath_print(common, ATH_DBG_XMIT, + "link[%u] (%p)=%llx (%p)\n", + txq->axq_qnum, txq->axq_link, + ito64(bf->bf_daddr), bf->bf_desc); + } + ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc, + &txq->axq_link); + ath9k_hw_txstart(ah, txq->axq_qnum); } - ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc, &txq->axq_link); - ath9k_hw_txstart(ah, txq->axq_qnum); + txq->axq_depth++; } static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) @@ -2140,6 +2214,80 @@ void ath_tx_tasklet(struct ath_softc *sc) } } +void ath_tx_edma_tasklet(struct ath_softc *sc) +{ + struct ath_tx_status txs; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_hw *ah = sc->sc_ah; + struct ath_txq *txq; + struct ath_buf *bf, *lastbf; + struct list_head bf_head; + int status; + int txok; + + for (;;) { + status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs); + if (status == -EINPROGRESS) + break; + if (status == -EIO) { + ath_print(common, ATH_DBG_XMIT, + "Error processing tx status\n"); + break; + } + + /* Skip beacon completions */ + if (txs.qid == sc->beacon.beaconq) + continue; + + txq = &sc->tx.txq[txs.qid]; + + spin_lock_bh(&txq->axq_lock); + if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) { + spin_unlock_bh(&txq->axq_lock); + return; + } + + bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx], + struct ath_buf, list); + lastbf = bf->bf_lastbf; + + INIT_LIST_HEAD(&bf_head); + list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx], + &lastbf->list); + INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); + txq->axq_depth--; + txq->axq_tx_inprogress = false; + spin_unlock_bh(&txq->axq_lock); + + txok = !(txs.ts_status & ATH9K_TXERR_MASK); + + if (!bf_isampdu(bf)) { + bf->bf_retries = txs.ts_longretry; + if (txs.ts_status & ATH9K_TXERR_XRETRY) + bf->bf_state.bf_type |= BUF_XRETRY; + ath_tx_rc_status(bf, &txs, 0, txok, true); + } + + if (bf_isampdu(bf)) + ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok); + else + ath_tx_complete_buf(sc, bf, txq, &bf_head, + &txs, txok, 0); + + spin_lock_bh(&txq->axq_lock); + if (!list_empty(&txq->txq_fifo_pending)) { + INIT_LIST_HEAD(&bf_head); + bf = list_first_entry(&txq->txq_fifo_pending, + struct ath_buf, list); + list_cut_position(&bf_head, &txq->txq_fifo_pending, + &bf->bf_lastbf->list); + ath_tx_txqaddbuf(sc, txq, &bf_head); + } else if (sc->sc_flags & SC_OP_TXAGGR) + ath_txq_schedule(sc, txq); + spin_unlock_bh(&txq->axq_lock); + } +} + /*****************/ /* Init, Cleanup */ /*****************/ -- cgit v1.2.3 From ce01805a226328228a885b4a6e4b632b4e73f8ee Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:38 -0400 Subject: ath9k_hw: add LDPC support for AR9003 Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 3 ++- drivers/net/wireless/ath/ath9k/hw.c | 2 +- drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/mac.h | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 582c88050664..7d111fbf8bc5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -330,7 +330,8 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); - ads->ctl17 = SM(keyType, AR_EncrType); + ads->ctl17 = SM(keyType, AR_EncrType) | + (flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0); ads->ctl18 = 0; ads->ctl19 = AR_Not_Sounding; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 55f79f5712d4..e07dd1c11dba 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2088,7 +2088,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) } if (AR_SREV_9300_20_OR_LATER(ah)) { - pCap->hw_caps |= ATH9K_HW_CAP_EDMA; + pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_LDPC; pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH; pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH; pCap->rx_status_len = sizeof(struct ar9003_rxs); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 9d3796a68920..7ce5420966a4 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -179,6 +179,7 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16), ATH9K_HW_CAP_EDMA = BIT(17), ATH9K_HW_CAP_RAC_SUPPORTED = BIT(18), + ATH9K_HW_CAP_LDPC = BIT(19), }; enum ath9k_capability_type { diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index b591dc27c325..346d84a7b937 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -264,6 +264,7 @@ struct ath_desc { #define ATH9K_TXDESC_VMF 0x0100 #define ATH9K_TXDESC_FRAG_IS_ON 0x0200 #define ATH9K_TXDESC_LOWRXCHAIN 0x0400 +#define ATH9K_TXDESC_LDPC 0x00010000 #define ATH9K_RXDESC_INTREQ 0x0020 @@ -413,6 +414,7 @@ struct ar5416_desc { #define AR_EncrType 0x0c000000 #define AR_EncrType_S 26 #define AR_TxCtlRsvd61 0xf0000000 +#define AR_LDPC 0x80000000 #define AR_2040_0 0x00000001 #define AR_GI0 0x00000002 -- cgit v1.2.3 From b0a3344834fcaf30e472ccc661c8842281453402 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:39 -0400 Subject: ath9k: add LDPC support LDPC is enabled by the rate control if the its determined that the target peer supports LDPC. We would have already intersected the HT capabilities so if our peer supports LDPC so do we. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 3 +++ drivers/net/wireless/ath/ath9k/rc.c | 9 +++++++++ drivers/net/wireless/ath/ath9k/xmit.c | 14 ++++++++++---- 3 files changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 58a87f7931df..5adc2e335cff 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -189,6 +189,9 @@ static void setup_ht_cap(struct ath_softc *sc, IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_DSSSCCK40; + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC) + ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; + ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 3c4b5d2d9e16..f10bd06dc218 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -689,6 +689,15 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, rate_table = sc->cur_rate_table; rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); + /* + * If we're in HT mode and both us and our peer supports LDPC. + * We don't need to check our own device's capabilities as our own + * ht capabilities would have already been intersected with our peer's. + */ + if (conf_is_ht(&sc->hw->conf) && + (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) + tx_info->flags |= IEEE80211_TX_CTL_LDPC; + if (is_probe) { /* set one try for probe rates. For the * probes don't enable rts */ diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index c2b45030d0b4..90e629f276f3 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1483,8 +1483,7 @@ static void assign_aggr_tid_seqno(struct sk_buff *skb, INCR(tid->seq_next, IEEE80211_SEQ_MAX); } -static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb, - struct ath_txq *txq) +static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); int flags = 0; @@ -1495,6 +1494,9 @@ static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb, if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) flags |= ATH9K_TXDESC_NOACK; + if (use_ldpc) + flags |= ATH9K_TXDESC_LDPC; + return flags; } @@ -1646,6 +1648,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, int hdrlen; __le16 fc; int padpos, padsize; + bool use_ldpc = false; tx_info->pad[0] = 0; switch (txctl->frame_type) { @@ -1672,10 +1675,13 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, bf->bf_frmlen -= padsize; } - if (conf_is_ht(&hw->conf)) + if (conf_is_ht(&hw->conf)) { bf->bf_state.bf_type |= BUF_HT; + if (tx_info->flags & IEEE80211_TX_CTL_LDPC) + use_ldpc = true; + } - bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq); + bf->bf_flags = setup_tx_flags(skb, use_ldpc); bf->bf_keytype = get_hw_crypto_keytype(skb); if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { -- cgit v1.2.3 From afe754d66fbde0a0c07d954d5f1ad36d10136c72 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:40 -0400 Subject: ath9k: Enable TXOK and TXERR interrupts for TX EDMA Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 90e629f276f3..cac178a6bd9b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -886,11 +886,16 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) * The UAPSD queue is an exception, since we take a desc- * based intr on the EOSP frames. */ - if (qtype == ATH9K_TX_QUEUE_UAPSD) - qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE; - else - qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | - TXQ_FLAG_TXDESCINT_ENABLE; + if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { + qi.tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE | + TXQ_FLAG_TXERRINT_ENABLE; + } else { + if (qtype == ATH9K_TX_QUEUE_UAPSD) + qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE; + else + qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | + TXQ_FLAG_TXDESCINT_ENABLE; + } qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi); if (qnum == -1) { /* -- cgit v1.2.3 From 9b9cc61c46822ced22bc09d9aaa9f0f1859719cb Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:41 -0400 Subject: ath9k_hw: Abort rx if hw is not coming out of full sleep in reset Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 7 +++++++ drivers/net/wireless/ath/ath9k/mac.c | 8 ++++++++ drivers/net/wireless/ath/ath9k/mac.h | 1 + 3 files changed, 16 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index e07dd1c11dba..35f5cf40a990 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1137,6 +1137,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ah->txchainmask = common->tx_chainmask; ah->rxchainmask = common->rx_chainmask; + if (!ah->chip_fullsleep) { + ath9k_hw_abortpcurecv(ah); + if (!ath9k_hw_stopdmarecv(ah)) + ath_print(common, ATH_DBG_XMIT, + "Failed to stop receive dma\n"); + } + if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) return -EIO; diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index c003baf2e937..b54e857c0310 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -747,6 +747,14 @@ void ath9k_hw_stoppcurecv(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_stoppcurecv); +void ath9k_hw_abortpcurecv(struct ath_hw *ah) +{ + REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); + + ath9k_hw_disable_mib_counters(ah); +} +EXPORT_SYMBOL(ath9k_hw_abortpcurecv); + bool ath9k_hw_stopdmarecv(struct ath_hw *ah) { #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 346d84a7b937..68eb8d0b92eb 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -711,6 +711,7 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); void ath9k_hw_startpcureceive(struct ath_hw *ah); void ath9k_hw_stoppcurecv(struct ath_hw *ah); +void ath9k_hw_abortpcurecv(struct ath_hw *ah); bool ath9k_hw_stopdmarecv(struct ath_hw *ah); int ath9k_hw_beaconq_setup(struct ath_hw *ah); -- cgit v1.2.3 From 733f0ea4498a24db5b8ac048ef99983600f1eff9 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:42 -0400 Subject: ath9k_hw: add the PCI ID for the first AR9300 device The first AR9003 hardware family device supported is the AR9300, which has the vendor:device id 168c:0030 Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 1ec836cf1c0d..257b10ba6f57 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -28,6 +28,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ + { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ { 0 } }; -- cgit v1.2.3 From 1c0fc65e6de4e941ff483df445e721d6edb1f84b Mon Sep 17 00:00:00 2001 From: Benoit Papillault Date: Fri, 16 Apr 2010 00:07:26 +0200 Subject: ath5k/ath9k: Fix 64 bits TSF reads According to tests, both TSF lower and upper registers kept counting, so the higher part could have been updated after the lower part has been read, as shown in the following log where the upper part is read first and the lower part next. tsf = {00000003-fffffffd} tsf = {00000003-00000001} tsf = {00000004-0000000b} This patch corrects this by checking that the upper part has not been changed while the lower part was read. It has been tested in an IBSS network where artifical IBSS merges have been done in order to trigger hundreds of rollover for the TSF lower part. It follows the logic mentionned by Derek, with only 2 register reads needed at each additional steps instead of 3 (the minimum number of register reads is still 3). Signed-off-by: Benoit Papillault Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/pcu.c | 31 +++++++++++++++++++++++++++++-- drivers/net/wireless/ath/ath9k/hw.c | 19 +++++++++++++++---- 2 files changed, 44 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 174412fc81f8..5212e275f1c7 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -496,6 +496,8 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) * Beacon control * \****************/ +#define ATH5K_MAX_TSF_READ 10 + /** * ath5k_hw_get_tsf64 - Get the full 64bit TSF * @@ -505,10 +507,35 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) */ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) { - u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32); + u32 tsf_lower, tsf_upper1, tsf_upper2; + int i; + + /* + * While reading TSF upper and then lower part, the clock is still + * counting (or jumping in case of IBSS merge) so we might get + * inconsistent values. To avoid this, we read the upper part again + * and check it has not been changed. We make the hypothesis that a + * maximum of 3 changes can happens in a row (we use 10 as a safe + * value). + * + * Impact on performance is pretty small, since in most cases, only + * 3 register reads are needed. + */ + + tsf_upper1 = ath5k_hw_reg_read(ah, AR5K_TSF_U32); + for (i = 0; i < ATH5K_MAX_TSF_READ; i++) { + tsf_lower = ath5k_hw_reg_read(ah, AR5K_TSF_L32); + tsf_upper2 = ath5k_hw_reg_read(ah, AR5K_TSF_U32); + if (tsf_upper2 == tsf_upper1) + break; + tsf_upper1 = tsf_upper2; + } + + WARN_ON( i == ATH5K_MAX_TSF_READ ); + ATH5K_TRACE(ah->ah_sc); - return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32); + return (((u64)tsf_upper1 << 32) | tsf_lower); } /** diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 35f5cf40a990..894f5fc7489e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2420,14 +2420,25 @@ void ath9k_hw_write_associd(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_write_associd); +#define ATH9K_MAX_TSF_READ 10 + u64 ath9k_hw_gettsf64(struct ath_hw *ah) { - u64 tsf; + u32 tsf_lower, tsf_upper1, tsf_upper2; + int i; + + tsf_upper1 = REG_READ(ah, AR_TSF_U32); + for (i = 0; i < ATH9K_MAX_TSF_READ; i++) { + tsf_lower = REG_READ(ah, AR_TSF_L32); + tsf_upper2 = REG_READ(ah, AR_TSF_U32); + if (tsf_upper2 == tsf_upper1) + break; + tsf_upper1 = tsf_upper2; + } - tsf = REG_READ(ah, AR_TSF_U32); - tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32); + WARN_ON( i == ATH9K_MAX_TSF_READ ); - return tsf; + return (((u64)tsf_upper1 << 32) | tsf_lower); } EXPORT_SYMBOL(ath9k_hw_gettsf64); -- cgit v1.2.3 From 3c997e8849c5b982662f2a9b3e8cb64260382faa Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 16 Apr 2010 09:28:43 +0800 Subject: iwmc3200wifi: Fix sparse warnings Signed-off-by: Samuel Ortiz Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/rx.c | 3 ++- drivers/net/wireless/iwmc3200wifi/trace.h | 4 ++-- drivers/net/wireless/iwmc3200wifi/tx.c | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 5090a8a61887..d754c3bc323a 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -430,7 +430,8 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf, return PTR_ERR(ticket_node); IWM_DBG_RX(iwm, DBG, "TICKET %s(%d)\n", - ticket->action == IWM_RX_TICKET_RELEASE ? + __le16_to_cpu(ticket->action) == + IWM_RX_TICKET_RELEASE ? "RELEASE" : "DROP", ticket->id); spin_lock(&iwm->ticket_lock); diff --git a/drivers/net/wireless/iwmc3200wifi/trace.h b/drivers/net/wireless/iwmc3200wifi/trace.h index 320e54fbb38c..abb4805fa8df 100644 --- a/drivers/net/wireless/iwmc3200wifi/trace.h +++ b/drivers/net/wireless/iwmc3200wifi/trace.h @@ -76,7 +76,7 @@ TRACE_EVENT(iwm_tx_wifi_cmd, IWM_ASSIGN; __entry->opcode = hdr->sw_hdr.cmd.cmd; __entry->lmac = 0; - __entry->seq = hdr->sw_hdr.cmd.seq_num; + __entry->seq = __le16_to_cpu(hdr->sw_hdr.cmd.seq_num); __entry->resp = GET_VAL8(hdr->sw_hdr.cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ); __entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR); __entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT); @@ -123,7 +123,7 @@ TRACE_EVENT(iwm_tx_packets, __entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID); __entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP); __entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR); - __entry->seq = hdr->sw_hdr.cmd.seq_num; + __entry->seq = __le16_to_cpu(hdr->sw_hdr.cmd.seq_num); __entry->npkt = 1; __entry->bytes = len; diff --git a/drivers/net/wireless/iwmc3200wifi/tx.c b/drivers/net/wireless/iwmc3200wifi/tx.c index a20b936ae21f..3cfa7b81fef2 100644 --- a/drivers/net/wireless/iwmc3200wifi/tx.c +++ b/drivers/net/wireless/iwmc3200wifi/tx.c @@ -301,8 +301,8 @@ void iwm_tx_credit_init_pools(struct iwm_priv *iwm, #define IWM_UDMA_HDR_LEN sizeof(struct iwm_umac_wifi_out_hdr) -static int iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb, - int pool_id, u8 *buf) +static __le16 iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb, + int pool_id, u8 *buf) { struct iwm_umac_wifi_out_hdr *hdr = (struct iwm_umac_wifi_out_hdr *)buf; struct iwm_udma_wifi_cmd udma_cmd; -- cgit v1.2.3 From e88402fbdd9c5dbbae7b16c575d4e0b9e9b6fd40 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 16 Apr 2010 09:28:44 +0800 Subject: iwmc3200wifi: check sparse endianness annotations Add -D__CHECK_ENDIAN__ to driver ccflags so that sparse will always check endianness by default. Signed-off-by: Samuel Ortiz Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/Makefile | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwmc3200wifi/Makefile b/drivers/net/wireless/iwmc3200wifi/Makefile index aeed5cd80819..cdc7e07ba113 100644 --- a/drivers/net/wireless/iwmc3200wifi/Makefile +++ b/drivers/net/wireless/iwmc3200wifi/Makefile @@ -6,3 +6,5 @@ iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o iwmc3200wifi-$(CONFIG_IWM_TRACING) += trace.o CFLAGS_trace.o := -I$(src) + +ccflags-y += -D__CHECK_ENDIAN__ -- cgit v1.2.3 From fcb9392ff7ccb010818f3609420fd5416f6ca22e Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Apr 2010 11:53:48 +0530 Subject: ath9k_htc: Cleanup beacon configuration This patch cleans up beacon configuration, removing a redundant interface type check and updating beacon interval in the correct place. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 23 +++++++++-------------- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +- 2 files changed, 10 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 5e21f4d92ff5..d10402864b76 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -244,25 +244,20 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif) { struct ath_common *common = ath9k_hw_common(priv->ah); - enum nl80211_iftype iftype; struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - if (vif) { - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - iftype = vif->type; - cur_conf->beacon_interval = bss_conf->beacon_int; - cur_conf->dtim_period = bss_conf->dtim_period; - cur_conf->listen_interval = 1; - cur_conf->dtim_count = 1; - cur_conf->bmiss_timeout = - ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; - } else - iftype = priv->ah->opmode; - + cur_conf->beacon_interval = bss_conf->beacon_int; if (cur_conf->beacon_interval == 0) cur_conf->beacon_interval = 100; - switch (iftype) { + cur_conf->dtim_period = bss_conf->dtim_period; + cur_conf->listen_interval = 1; + cur_conf->dtim_count = 1; + cur_conf->bmiss_timeout = + ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; + + switch (vif->type) { case NL80211_IFTYPE_STATION: ath9k_htc_beacon_config_sta(priv, cur_conf); break; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index eb7722b2cfcc..08a4a58a4180 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1687,7 +1687,7 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) spin_unlock_bh(&priv->beacon_lock); priv->op_flags |= OP_FULL_RESET; if (priv->op_flags & OP_ASSOCIATED) - ath9k_htc_beacon_config(priv, NULL); + ath9k_htc_beacon_config(priv, priv->vif); ath_start_ani(priv); mutex_unlock(&priv->mutex); ath9k_htc_ps_restore(priv); -- cgit v1.2.3 From 50f56316aed044e42c1bcd7572926e80aac9af46 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Apr 2010 11:53:50 +0530 Subject: ath: Add buffered register write operations This is required to implement delayed/buffered register writes in ath9k_htc. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 1fbf6b1f9a7e..d32f2828b098 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -71,9 +71,21 @@ struct ath_regulatory { struct reg_dmn_pair_mapping *regpair; }; +/** + * struct ath_ops - Register read/write operations + * + * @read: Register read + * @write: Register write + * @enable_write_buffer: Enable multiple register writes + * @disable_write_buffer: Disable multiple register writes + * @write_flush: Flush buffered register writes + */ struct ath_ops { unsigned int (*read)(void *, u32 reg_offset); - void (*write)(void *, u32 val, u32 reg_offset); + void (*write)(void *, u32 val, u32 reg_offset); + void (*enable_write_buffer)(void *); + void (*disable_write_buffer)(void *); + void (*write_flush) (void *); }; struct ath_common; -- cgit v1.2.3 From 4a22fe108e62367c10c3abeb469d6972ba3299f5 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Apr 2010 11:53:53 +0530 Subject: ath9k_htc: Implement multiple register write support This patch adds support for writing multiple registers in a single USB command. Specific calls from the HW code that performs multiple register writes would be modified to make use of this in subsequent patches. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 104 +++++++++++++++++++++++++- drivers/net/wireless/ath/ath9k/wmi.c | 1 + drivers/net/wireless/ath/ath9k/wmi.h | 12 +++ 3 files changed, 113 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index aed53573c547..a86189629d92 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -213,7 +213,7 @@ static int ath9k_reg_notifier(struct wiphy *wiphy, ath9k_hw_regulatory(priv->ah)); } -static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) +static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset) { struct ath_hw *ah = (struct ath_hw *) hw_priv; struct ath_common *common = ath9k_hw_common(ah); @@ -235,7 +235,7 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) return be32_to_cpu(val); } -static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) +static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset) { struct ath_hw *ah = (struct ath_hw *) hw_priv; struct ath_common *common = ath9k_hw_common(ah); @@ -257,9 +257,105 @@ static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) } } +static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset) +{ + struct ath_hw *ah = (struct ath_hw *) hw_priv; + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + u32 rsp_status; + int r; + + mutex_lock(&priv->wmi->multi_write_mutex); + + /* Store the register/value */ + priv->wmi->multi_write[priv->wmi->multi_write_idx].reg = + cpu_to_be32(reg_offset); + priv->wmi->multi_write[priv->wmi->multi_write_idx].val = + cpu_to_be32(val); + + priv->wmi->multi_write_idx++; + + /* If the buffer is full, send it out. */ + if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) { + r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, + (u8 *) &priv->wmi->multi_write, + sizeof(struct register_write) * priv->wmi->multi_write_idx, + (u8 *) &rsp_status, sizeof(rsp_status), + 100); + if (unlikely(r)) { + ath_print(common, ATH_DBG_WMI, + "REGISTER WRITE FAILED, multi len: %d\n", + priv->wmi->multi_write_idx); + } + priv->wmi->multi_write_idx = 0; + } + + mutex_unlock(&priv->wmi->multi_write_mutex); +} + +static void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset) +{ + struct ath_hw *ah = (struct ath_hw *) hw_priv; + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + + if (atomic_read(&priv->wmi->mwrite_cnt)) + ath9k_regwrite_buffer(hw_priv, val, reg_offset); + else + ath9k_regwrite_single(hw_priv, val, reg_offset); +} + +static void ath9k_enable_regwrite_buffer(void *hw_priv) +{ + struct ath_hw *ah = (struct ath_hw *) hw_priv; + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + + atomic_inc(&priv->wmi->mwrite_cnt); +} + +static void ath9k_disable_regwrite_buffer(void *hw_priv) +{ + struct ath_hw *ah = (struct ath_hw *) hw_priv; + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + + atomic_dec(&priv->wmi->mwrite_cnt); +} + +static void ath9k_regwrite_flush(void *hw_priv) +{ + struct ath_hw *ah = (struct ath_hw *) hw_priv; + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + u32 rsp_status; + int r; + + mutex_lock(&priv->wmi->multi_write_mutex); + + if (priv->wmi->multi_write_idx) { + r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, + (u8 *) &priv->wmi->multi_write, + sizeof(struct register_write) * priv->wmi->multi_write_idx, + (u8 *) &rsp_status, sizeof(rsp_status), + 100); + if (unlikely(r)) { + ath_print(common, ATH_DBG_WMI, + "REGISTER WRITE FAILED, multi len: %d\n", + priv->wmi->multi_write_idx); + } + priv->wmi->multi_write_idx = 0; + } + + mutex_unlock(&priv->wmi->multi_write_mutex); +} + static const struct ath_ops ath9k_common_ops = { - .read = ath9k_ioread32, - .write = ath9k_iowrite32, + .read = ath9k_regread, + .write = ath9k_regwrite, + .enable_write_buffer = ath9k_enable_regwrite_buffer, + .disable_write_buffer = ath9k_disable_regwrite_buffer, + .write_flush = ath9k_regwrite_flush, }; static void ath_usb_read_cachesize(struct ath_common *common, int *csz) diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index f2ff18cf3e60..355e0dbf3c66 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -101,6 +101,7 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv) wmi->drv_priv = priv; wmi->stopped = false; mutex_init(&wmi->op_mutex); + mutex_init(&wmi->multi_write_mutex); init_completion(&wmi->cmd_wait); return wmi; diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 39ef926f27c2..fd8c9c5f4a05 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -84,6 +84,13 @@ enum wmi_event_id { WMI_TXRATE_EVENTID, }; +#define MAX_CMD_NUMBER 62 + +struct register_write { + u32 reg; + u32 val; +}; + struct wmi { struct ath9k_htc_priv *drv_priv; struct htc_target *htc; @@ -97,6 +104,11 @@ struct wmi { struct sk_buff *wmi_skb; spinlock_t wmi_lock; + + atomic_t mwrite_cnt; + struct register_write multi_write[MAX_CMD_NUMBER]; + u32 multi_write_idx; + struct mutex multi_write_mutex; }; struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv); -- cgit v1.2.3 From 20b3efd979c0d5d9fdf497a98668a806266a63e4 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Apr 2010 11:53:55 +0530 Subject: ath9k_hw: Add macros for multiple register writes Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7ce5420966a4..8158e8e6a53d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -68,6 +68,24 @@ #define REG_READ(_ah, _reg) \ ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) +#define ENABLE_REGWRITE_BUFFER(_ah) \ + do { \ + if (AR_SREV_9271(_ah)) \ + ath9k_hw_common(_ah)->ops->enable_write_buffer((_ah)); \ + } while (0) + +#define DISABLE_REGWRITE_BUFFER(_ah) \ + do { \ + if (AR_SREV_9271(_ah)) \ + ath9k_hw_common(_ah)->ops->disable_write_buffer((_ah)); \ + } while (0) + +#define REGWRITE_BUFFER_FLUSH(_ah) \ + do { \ + if (AR_SREV_9271(_ah)) \ + ath9k_hw_common(_ah)->ops->write_flush((_ah)); \ + } while (0) + #define SM(_v, _f) (((_v) << _f##_S) & _f) #define MS(_v, _f) (((_v) & _f) >> _f##_S) #define REG_RMW(_a, _r, _set, _clr) \ -- cgit v1.2.3 From 6819d57f07440a8f9540967d9212a70e9c98eceb Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Apr 2010 11:53:56 +0530 Subject: ath9k_hw: Relocate Opmode initialization Programming the opmode in the HW can be done before the assoc_id and STA_ID registers are setup. This helps ath9k_htc when multiple register writes are used. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 894f5fc7489e..35fe58f5675b 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1238,6 +1238,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_spur_mitigate_freq(ah, chan); ah->eep_ops->set_board_values(ah, chan); + ath9k_hw_set_operating_mode(ah, ah->opmode); + REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) | macStaId1 @@ -1245,16 +1247,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | (ah->config. ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) | ah->sta_id1_defaults); - ath9k_hw_set_operating_mode(ah, ah->opmode); - ath_hw_setbssidmask(common); - REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); - ath9k_hw_write_associd(ah); - REG_WRITE(ah, AR_ISR, ~0); - REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); r = ath9k_hw_rf_set_freq(ah, chan); -- cgit v1.2.3 From 7d0d0df0eca695c83a08dc386824a9d1d7c526a4 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Apr 2010 11:53:57 +0530 Subject: ath9k_hw: Use buffered register writes This patch adds macros at certain places which could be optimized for multiple register writes. The performance of ath9k_htc improves considerably, especially reducing the latency involved in a scan run. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 23 +++++++++ drivers/net/wireless/ath/ath9k/ar5008_phy.c | 28 +++++++++++ drivers/net/wireless/ath/ath9k/ar9002_calib.c | 5 ++ drivers/net/wireless/ath/ath9k/ar9002_hw.c | 7 ++- drivers/net/wireless/ath/ath9k/ar9002_phy.c | 5 ++ drivers/net/wireless/ath/ath9k/eeprom_4k.c | 10 ++++ drivers/net/wireless/ath/ath9k/hw.c | 71 +++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/mac.c | 27 ++++++++++ 8 files changed, 175 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 5a2d867a4e92..cec62d311c78 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -79,11 +79,17 @@ static void ath9k_ani_restart(struct ath_hw *ah) "Writing ofdmbase=%u cckbase=%u\n", aniState->ofdmPhyErrBase, aniState->cckPhyErrBase); + + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); aniState->ofdmPhyErrCount = 0; @@ -357,8 +363,14 @@ void ath9k_ani_reset(struct ath_hw *ah) ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & ~ATH9K_RX_FILTER_PHYERR); ath9k_ani_restart(ah); + + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); } void ath9k_hw_ani_monitor(struct ath_hw *ah, @@ -456,6 +468,8 @@ void ath9k_enable_mib_counters(struct ath_hw *ah) ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_FILT_OFDM, 0); REG_WRITE(ah, AR_FILT_CCK, 0); REG_WRITE(ah, AR_MIBC, @@ -463,6 +477,9 @@ void ath9k_enable_mib_counters(struct ath_hw *ah) & 0x0f); REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); } /* Freeze the MIB counters, get the stats and then clear them */ @@ -626,8 +643,14 @@ void ath9k_hw_ani_init(struct ath_hw *ah) ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n", ah->ani[0].cckPhyErrBase); + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase); REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + ath9k_enable_mib_counters(ah); ah->aniperiod = ATH9K_ANI_PERIOD; diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 94eb069b5ae3..de8ce1291a46 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -590,10 +590,14 @@ static void ar5008_hw_init_chain_masks(struct ath_hw *ah) rx_chainmask = ah->rxchainmask; tx_chainmask = ah->txchainmask; + ENABLE_REGWRITE_BUFFER(ah); + switch (rx_chainmask) { case 0x5: + DISABLE_REGWRITE_BUFFER(ah); REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); + ENABLE_REGWRITE_BUFFER(ah); case 0x3: if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) { REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); @@ -611,6 +615,10 @@ static void ar5008_hw_init_chain_masks(struct ath_hw *ah) } REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + if (tx_chainmask == 0x5) { REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); @@ -689,8 +697,13 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah, ath9k_hw_set11nmac2040(ah); + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); } @@ -773,6 +786,8 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); + ENABLE_REGWRITE_BUFFER(ah); + for (i = 0; i < ah->iniModes.ia_rows; i++) { u32 reg = INI_RA(&ah->iniModes, i, 0); u32 val = INI_RA(&ah->iniModes, i, modesIndex); @@ -790,6 +805,9 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, DO_DELAY(regWrites); } + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah)) REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); @@ -801,6 +819,8 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only, modesIndex, regWrites); + ENABLE_REGWRITE_BUFFER(ah); + /* Write common array parameters */ for (i = 0; i < ah->iniCommon.ia_rows; i++) { u32 reg = INI_RA(&ah->iniCommon, i, 0); @@ -816,6 +836,9 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, DO_DELAY(regWrites); } + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + if (AR_SREV_9271(ah)) { if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1) REG_WRITE_ARRAY(&ah->iniModes_high_power_tx_gain_9271, @@ -1303,6 +1326,8 @@ static void ar5008_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) udelay(50); } + ENABLE_REGWRITE_BUFFER(ah); + for (i = 0; i < NUM_NF_READINGS; i++) { if (chainmask & (1 << i)) { val = REG_READ(ah, ar5416_cca_regs[i]); @@ -1311,6 +1336,9 @@ static void ar5008_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) REG_WRITE(ah, ar5416_cca_regs[i], val); } } + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); } void ar5008_hw_attach_phy_ops(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 968529b3988f..5fdbb53b47e0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -527,6 +527,8 @@ static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) ah->pacal_info.prev_offset = regVal; } + ENABLE_REGWRITE_BUFFER(ah); + regVal = REG_READ(ah, 0x7834); regVal |= 0x1; REG_WRITE(ah, 0x7834, regVal); @@ -536,6 +538,9 @@ static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) for (i = 0; i < ARRAY_SIZE(regList); i++) REG_WRITE(ah, regList[i][0], regList[i][1]); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); } static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 17b98a3f33bc..adb33b34a56d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -488,10 +488,15 @@ static int ar9002_hw_get_radiorev(struct ath_hw *ah) u32 val; int i; - REG_WRITE(ah, AR_PHY(0x36), 0x00007058); + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_PHY(0x36), 0x00007058); for (i = 0; i < 8; i++) REG_WRITE(ah, AR_PHY(0x20), 0x00010000); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index a0a2f58db29c..18cfe1a9781c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -236,6 +236,8 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah, tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); + ENABLE_REGWRITE_BUFFER(ah); + newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | @@ -411,6 +413,9 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah, | (mask_p[47] << 2) | (mask_p[46] << 0); REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); } static void ar9002_olc_init(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 2384a9f4f5fb..41a77d1bd439 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -454,6 +454,8 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, &tMinCalPower, gainBoundaries, pdadcValues, numXpdGain); + ENABLE_REGWRITE_BUFFER(ah); + if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, SM(pdGainOverlap_t2, @@ -494,6 +496,9 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, regOffset += 4; } + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); } } @@ -759,6 +764,8 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; } + ENABLE_REGWRITE_BUFFER(ah); + /* OFDM power per rate */ REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, ATH9K_POW_SM(ratesArray[rate18mb], 24) @@ -821,6 +828,9 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); } + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); } static void ath9k_hw_4k_set_addac(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 35fe58f5675b..0b85f68d516f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -274,6 +274,8 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah) if (AR_SREV_9100(ah)) return; + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029); @@ -285,6 +287,9 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah) REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007); REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); } /* This should work for all families including legacy */ @@ -638,6 +643,8 @@ EXPORT_SYMBOL(ath9k_hw_init); static void ath9k_hw_init_qos(struct ath_hw *ah) { + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa); REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210); @@ -651,6 +658,9 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF); REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF); REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); } static void ath9k_hw_init_pll(struct ath_hw *ah, @@ -702,6 +712,8 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, if (opmode == NL80211_IFTYPE_AP) imr_reg |= AR_IMR_MIB; + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_IMR, imr_reg); ah->imrs2_reg |= AR_IMR_S2_GTT; REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); @@ -712,6 +724,9 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, REG_WRITE(ah, AR_INTR_SYNC_MASK, 0); } + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + if (AR_SREV_9300_20_OR_LATER(ah)) { REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0); REG_WRITE(ah, AR_INTR_PRIO_ASYNC_MASK, 0); @@ -840,6 +855,8 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); u32 regval; + ENABLE_REGWRITE_BUFFER(ah); + /* * set AHB_MODE not to do cacheline prefetches */ @@ -854,6 +871,9 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK; REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + /* * Restore TX Trigger Level to its pre-reset value. * The initial value depends on whether aggregation is enabled, and is @@ -862,6 +882,8 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) if (!AR_SREV_9300_20_OR_LATER(ah)) REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level); + ENABLE_REGWRITE_BUFFER(ah); + /* * let mac dma writes be in 128 byte chunks */ @@ -897,6 +919,9 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) AR_PCU_TXBUF_CTRL_USABLE_SIZE); } + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + if (AR_SREV_9300_20_OR_LATER(ah)) ath9k_hw_reset_txstatus_ring(ah); } @@ -956,6 +981,8 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) (void)REG_READ(ah, AR_RTC_DERIVED_CLK); } + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); @@ -984,6 +1011,10 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) } REG_WRITE(ah, AR_RTC_RC, rst_flags); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + udelay(50); REG_WRITE(ah, AR_RTC_RC, 0); @@ -1004,6 +1035,8 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) { + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); @@ -1012,6 +1045,9 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) REG_WRITE(ah, AR_RTC_RESET, 0); + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + if (!AR_SREV_9300_20_OR_LATER(ah)) udelay(2); @@ -1240,6 +1276,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_set_operating_mode(ah, ah->opmode); + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) | macStaId1 @@ -1253,13 +1291,21 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REG_WRITE(ah, AR_ISR, ~0); REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + r = ath9k_hw_rf_set_freq(ah, chan); if (r) return r; + ENABLE_REGWRITE_BUFFER(ah); + for (i = 0; i < AR_NUM_DCU; i++) REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + ah->intr_txqs = 0; for (i = 0; i < ah->caps.total_queues; i++) ath9k_hw_resettxqueue(ah, i); @@ -1299,9 +1345,14 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (!ath9k_hw_init_cal(ah, chan)) return -EIO; + ENABLE_REGWRITE_BUFFER(ah); + ath9k_hw_restore_chainmask(ah); REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + /* * For big endian systems turn on swapping for descriptors */ @@ -1765,6 +1816,8 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) ah->beacon_interval = beacon_period; + ENABLE_REGWRITE_BUFFER(ah); + switch (ah->opmode) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_MONITOR: @@ -1808,6 +1861,9 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period)); REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + beacon_period &= ~ATH9K_BEACON_ENA; if (beacon_period & ATH9K_BEACON_RESET_TSF) { ath9k_hw_reset_tsf(ah); @@ -1824,6 +1880,8 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_common *common = ath9k_hw_common(ah); + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt)); REG_WRITE(ah, AR_BEACON_PERIOD, @@ -1831,6 +1889,9 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); @@ -1853,6 +1914,8 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, ath_print(common, ATH_DBG_BEACON, "beacon period %d\n", beaconintval); ath_print(common, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod); + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_NEXT_DTIM, TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP)); @@ -1872,6 +1935,9 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval)); REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + REG_SET_BIT(ah, AR_TIMER_MODE, AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN | AR_DTIM_TIMER_EN); @@ -2329,6 +2395,8 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) { u32 phybits; + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_RX_FILTER, bits); phybits = 0; @@ -2344,6 +2412,9 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) else REG_WRITE(ah, AR_RXCFG, REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); } EXPORT_SYMBOL(ath9k_hw_setrxfilter); diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index b54e857c0310..7bbf502563bc 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -25,6 +25,8 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, ah->txurn_interrupt_mask); + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_IMR_S0, SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK) | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC)); @@ -35,6 +37,9 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN; ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN); REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); } u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) @@ -470,6 +475,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) } else cwMin = qi->tqi_cwmin; + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_DLCL_IFS(q), SM(cwMin, AR_D_LCL_IFS_CWMIN) | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) | @@ -484,6 +491,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) REG_WRITE(ah, AR_DMISC(q), AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); + REGWRITE_BUFFER_FLUSH(ah); + if (qi->tqi_cbrPeriod) { REG_WRITE(ah, AR_QCBRCFG(q), SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | @@ -499,6 +508,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) AR_Q_RDYTIMECFG_EN); } + REGWRITE_BUFFER_FLUSH(ah); + REG_WRITE(ah, AR_DCHNTIME(q), SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); @@ -516,6 +527,10 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) REG_READ(ah, AR_DMISC(q)) | AR_D_MISC_POST_FR_BKOFF_DIS); } + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | @@ -523,6 +538,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) } switch (qi->tqi_type) { case ATH9K_TX_QUEUE_BEACON: + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_DBA_GATED | AR_Q_MISC_BEACON_USE @@ -533,6 +550,10 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) AR_D_MISC_ARB_LOCKOUT_CNTRL_S) | AR_D_MISC_BEACON_USE | AR_D_MISC_POST_FR_BKOFF_DIS); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + /* cwmin and cwmax should be 0 for beacon queue */ if (AR_SREV_9300_20_OR_LATER(ah)) { REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN) @@ -541,6 +562,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) } break; case ATH9K_TX_QUEUE_CAB: + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_DBA_GATED | AR_Q_MISC_CBR_INCR_DIS1 @@ -554,6 +577,10 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + break; case ATH9K_TX_QUEUE_PSPOLL: REG_WRITE(ah, AR_QMISC(q), -- cgit v1.2.3 From 0daa3e3a7d85d70cdd4d9cc8e589e79a4a37a5ef Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Apr 2010 11:53:58 +0530 Subject: ath9k_htc: Remove GPIO set on unload There is no point in trying to set the LED pin when the module is being unloaded. The target would be reset anyway. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 08a4a58a4180..2cea577f884d 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -960,7 +960,6 @@ void ath9k_deinit_leds(struct ath9k_htc_priv *priv) ath9k_unregister_led(&priv->tx_led); ath9k_unregister_led(&priv->rx_led); ath9k_unregister_led(&priv->radio_led); - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); } void ath9k_init_leds(struct ath9k_htc_priv *priv) -- cgit v1.2.3 From eac8e385e9446e591aacbc9ef2c2a3b0836dd2d4 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Apr 2010 11:54:00 +0530 Subject: ath9k_htc: Add dropped SKB count to debugfs Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 13 +++++++++---- drivers/net/wireless/ath/ath9k/htc.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_main.c | 3 +++ 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index fe994e229898..3091bb3cef9b 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -129,6 +129,7 @@ static void hif_usb_tx_cb(struct urb *urb) TX_STAT_INC(skb_completed); } else { dev_kfree_skb_any(skb); + TX_STAT_INC(skb_dropped); } } @@ -149,11 +150,15 @@ static void hif_usb_tx_cb(struct urb *urb) } } -static inline void ath9k_skb_queue_purge(struct sk_buff_head *list) +static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, + struct sk_buff_head *list) { struct sk_buff *skb; - while ((skb = __skb_dequeue(list)) != NULL) + + while ((skb = __skb_dequeue(list)) != NULL) { dev_kfree_skb_any(skb); + TX_STAT_INC(skb_dropped); + } } /* TX lock has to be taken */ @@ -214,7 +219,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC); if (ret) { tx_buf->len = tx_buf->offset = 0; - ath9k_skb_queue_purge(&tx_buf->skb_queue); + ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); __skb_queue_head_init(&tx_buf->skb_queue); list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); hif_dev->tx.tx_buf_cnt++; @@ -281,7 +286,7 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id) unsigned long flags; spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); - ath9k_skb_queue_purge(&hif_dev->tx.tx_skb_queue); + ath9k_skb_queue_purge(hif_dev, &hif_dev->tx.tx_skb_queue); hif_dev->tx.tx_skb_cnt = 0; hif_dev->tx.flags |= HIF_USB_TX_STOP; spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 78213fc71b09..6a4614a8701b 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -261,6 +261,7 @@ struct ath_tx_stats { u32 buf_completed; u32 skb_queued; u32 skb_completed; + u32 skb_dropped; }; struct ath_rx_stats { diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 2cea577f884d..081f44504285 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -609,6 +609,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "SKBs completed", priv->debug.tx_stats.skb_completed); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs dropped", + priv->debug.tx_stats.skb_dropped); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } -- cgit v1.2.3 From 6ce34ec11c6297562e70e27c57a24cd27d4cd2b1 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Apr 2010 11:54:01 +0530 Subject: ath9k_htc: Handle WMI timeouts properly If a WMI command has timed out for some reason, a late WMI response would end up updating the response region of a new WMI request that has been issued in the meantime. Fix this race condition by dropping a WMI response if a new WMI command has been issued. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/wmi.c | 13 +++++++++++++ drivers/net/wireless/ath/ath9k/wmi.h | 1 + 2 files changed, 14 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 355e0dbf3c66..afbf63daf551 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -204,6 +204,14 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, return; } + /* Check if there has been a timeout. */ + spin_lock(&wmi->wmi_lock); + if (cmd_id != wmi->last_cmd_id) { + spin_unlock(&wmi->wmi_lock); + goto free_skb; + } + spin_unlock(&wmi->wmi_lock); + /* WMI command response */ ath9k_wmi_rsp_callback(wmi, skb); @@ -266,6 +274,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, struct sk_buff *skb; u8 *data; int time_left, ret = 0; + unsigned long flags; if (!wmi) return -EINVAL; @@ -297,6 +306,10 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, if (ret) goto out; + spin_lock_irqsave(&wmi->wmi_lock, flags); + wmi->last_cmd_id = cmd_id; + spin_unlock_irqrestore(&wmi->wmi_lock, flags); + time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout); if (!time_left) { ath_print(common, ATH_DBG_WMI, diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index fd8c9c5f4a05..611357158ecf 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -97,6 +97,7 @@ struct wmi { enum htc_endpoint_id ctrl_epid; struct mutex op_mutex; struct completion cmd_wait; + enum wmi_cmd_id last_cmd_id; u16 tx_seq_id; u8 *cmd_rsp_buf; u32 cmd_rsp_len; -- cgit v1.2.3 From 7f1f5a0060e377ff6a15903487b39223e12b8568 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Apr 2010 11:54:03 +0530 Subject: ath9k_htc: Fix sparse endian warnings This patch fixes a bunch of endian issues that were exposed by sparse. It's a miracle that the driver worked at all till now. The Lord be praised. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 18 +++++++++--------- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 6 ++++-- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 14 ++++++++------ drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 11 +++-------- drivers/net/wireless/ath/ath9k/htc_hst.c | 8 ++++---- drivers/net/wireless/ath/ath9k/htc_hst.h | 24 ++++++++++++------------ drivers/net/wireless/ath/ath9k/mac.h | 10 +++++----- drivers/net/wireless/ath/ath9k/wmi.c | 2 +- drivers/net/wireless/ath/ath9k/wmi.h | 10 +++++----- 9 files changed, 51 insertions(+), 52 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 6a4614a8701b..c765ff4a505c 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -124,13 +124,13 @@ struct ath9k_htc_cap_target { struct ath9k_htc_target_vif { u8 index; u8 des_bssid[ETH_ALEN]; - enum htc_opmode opmode; + __be32 opmode; u8 myaddr[ETH_ALEN]; u8 bssid[ETH_ALEN]; u32 flags; u32 flags_ext; u16 ps_sta; - u16 rtsthreshold; + __be16 rtsthreshold; u8 ath_cap; u8 node; s8 mcast_rate; @@ -151,7 +151,7 @@ struct ath9k_htc_target_sta { u8 sta_index; u8 vif_index; u8 vif_sta; - u16 flags; /* ATH_HTC_STA_* */ + __be16 flags; /* ATH_HTC_STA_* */ u16 htcap; u8 valid; u16 capinfo; @@ -191,16 +191,16 @@ struct ath9k_htc_rate { struct ath9k_htc_target_rate { u8 sta_index; u8 isnew; - u32 capflags; + __be32 capflags; struct ath9k_htc_rate rates; }; struct ath9k_htc_target_stats { - u32 tx_shortretry; - u32 tx_longretry; - u32 tx_xretries; - u32 ht_txunaggr_xretry; - u32 ht_tx_xretries; + __be32 tx_shortretry; + __be32 tx_longretry; + __be32 tx_xretries; + __be32 ht_txunaggr_xretry; + __be32 ht_tx_xretries; } __packed; struct ath9k_htc_vif { diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index d10402864b76..7cb55f5b071c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -26,7 +26,8 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, enum ath9k_int imask = 0; int dtimperiod, dtimcount, sleepduration; int cfpperiod, cfpcount, bmiss_timeout; - u32 nexttbtt = 0, intval, tsftu, htc_imask = 0; + u32 nexttbtt = 0, intval, tsftu; + __be32 htc_imask = 0; u64 tsf; int num_beacons, offset, dtim_dec_count, cfp_dec_count; int ret; @@ -142,7 +143,8 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, { struct ath_common *common = ath9k_hw_common(priv->ah); enum ath9k_int imask = 0; - u32 nexttbtt, intval, htc_imask = 0; + u32 nexttbtt, intval; + __be32 htc_imask = 0; int ret; u8 cmd_rsp; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 081f44504285..ec7bcc8696ec 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -125,7 +125,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, bool fastcc = true; struct ieee80211_channel *channel = hw->conf.channel; enum htc_phymode mode; - u16 htc_mode; + __be16 htc_mode; u8 cmd_rsp; int ret; @@ -378,7 +378,7 @@ static int ath9k_htc_init_rate(struct ath9k_htc_priv *priv, priv->tgt_rate.sta_index = ista->index; priv->tgt_rate.isnew = 1; trate = priv->tgt_rate; - priv->tgt_rate.capflags = caps; + priv->tgt_rate.capflags = cpu_to_be32(caps); trate.capflags = cpu_to_be32(caps); WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate); @@ -426,6 +426,7 @@ static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40) struct ath9k_htc_target_rate trate; struct ath_common *common = ath9k_hw_common(priv->ah); int ret; + u32 caps = be32_to_cpu(priv->tgt_rate.capflags); u8 cmd_rsp; memset(&trate, 0, sizeof(trate)); @@ -433,11 +434,12 @@ static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40) trate = priv->tgt_rate; if (is_cw40) - priv->tgt_rate.capflags |= WLAN_RC_40_FLAG; + caps |= WLAN_RC_40_FLAG; else - priv->tgt_rate.capflags &= ~WLAN_RC_40_FLAG; + caps &= ~WLAN_RC_40_FLAG; - trate.capflags = cpu_to_be32(priv->tgt_rate.capflags); + priv->tgt_rate.capflags = cpu_to_be32(caps); + trate.capflags = cpu_to_be32(caps); WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate); if (ret) { @@ -1104,7 +1106,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) struct ath9k_channel *init_channel; int ret = 0; enum htc_phymode mode; - u16 htc_mode; + __be16 htc_mode; u8 cmd_rsp; ath_print(common, ATH_DBG_CONFIG, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 0a7cb30af5b4..2c3c51007dd3 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -530,7 +530,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi; } - rx_status->mactime = rxbuf->rxstatus.rs_tstamp; + rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); rx_status->band = hw->conf.channel->band; rx_status->freq = hw->conf.channel->center_freq; rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR; @@ -634,13 +634,8 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, rxstatus = (struct ath_htc_rx_status *)skb->data; - rxstatus->rs_tstamp = be64_to_cpu(rxstatus->rs_tstamp); - rxstatus->rs_datalen = be16_to_cpu(rxstatus->rs_datalen); - rxstatus->evm0 = be32_to_cpu(rxstatus->evm0); - rxstatus->evm1 = be32_to_cpu(rxstatus->evm1); - rxstatus->evm2 = be32_to_cpu(rxstatus->evm2); - - if (rxstatus->rs_datalen - (len - HTC_RX_FRAME_HEADER_SIZE) != 0) { + if (be16_to_cpu(rxstatus->rs_datalen) - + (len - HTC_RX_FRAME_HEADER_SIZE) != 0) { ath_print(common, ATH_DBG_FATAL, "Corrupted RX data len, dropping " "(epid: %d, dlen: %d, skblen: %d)\n", diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 587d98ed0989..f2dca258bdc2 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -368,7 +368,7 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, struct htc_frame_hdr *htc_hdr; enum htc_endpoint_id epid; struct htc_endpoint *endpoint; - u16 *msg_id; + __be16 *msg_id; if (!htc_handle || !skb) return; @@ -388,14 +388,14 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, /* Handle trailer */ if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) { - if (be32_to_cpu(*(u32 *) skb->data) == 0x00C60000) + if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000) /* Move past the Watchdog pattern */ htc_hdr = (struct htc_frame_hdr *)(skb->data + 4); } /* Get the message ID */ - msg_id = (u16 *) ((void *) htc_hdr + - sizeof(struct htc_frame_hdr)); + msg_id = (__be16 *) ((void *) htc_hdr + + sizeof(struct htc_frame_hdr)); /* Now process HTC messages */ switch (be16_to_cpu(*msg_id)) { diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index cd7048ffd239..ea50ab032d20 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -59,20 +59,20 @@ enum htc_endpoint_id { struct htc_frame_hdr { u8 endpoint_id; u8 flags; - u16 payload_len; + __be16 payload_len; u8 control[4]; } __packed; struct htc_ready_msg { - u16 message_id; - u16 credits; - u16 credit_size; + __be16 message_id; + __be16 credits; + __be16 credit_size; u8 max_endpoints; u8 pad; } __packed; struct htc_config_pipe_msg { - u16 message_id; + __be16 message_id; u8 pipe_id; u8 credits; } __packed; @@ -192,9 +192,9 @@ enum htc_service_group_ids{ #define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 8) struct htc_conn_svc_msg { - u16 msg_id; - u16 service_id; - u16 con_flags; + __be16 msg_id; + __be16 service_id; + __be16 con_flags; u8 dl_pipeid; u8 ul_pipeid; u8 svc_meta_len; @@ -209,17 +209,17 @@ struct htc_conn_svc_msg { #define HTC_SERVICE_NO_MORE_EP 4 struct htc_conn_svc_rspmsg { - u16 msg_id; - u16 service_id; + __be16 msg_id; + __be16 service_id; u8 status; u8 endpoint_id; - u16 max_msg_len; + __be16 max_msg_len; u8 svc_meta_len; u8 pad; } __packed; struct htc_comp_msg { - u16 msg_id; + __be16 msg_id; } __packed; int htc_init(struct htc_target *target); diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 68eb8d0b92eb..66d0d5e56149 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -155,8 +155,8 @@ struct ath_rx_status { }; struct ath_htc_rx_status { - u64 rs_tstamp; - u16 rs_datalen; + __be64 rs_tstamp; + __be16 rs_datalen; u8 rs_status; u8 rs_phyerr; int8_t rs_rssi; @@ -175,9 +175,9 @@ struct ath_htc_rx_status { u8 rs_num_delims; u8 rs_flags; u8 rs_dummy; - u32 evm0; - u32 evm1; - u32 evm2; + __be32 evm0; + __be32 evm1; + __be32 evm2; }; #define ATH9K_RXERR_CRC 0x01 diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index afbf63daf551..dc6c6fc2e095 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -129,7 +129,7 @@ void ath9k_wmi_tasklet(unsigned long data) void *wmi_event; unsigned long flags; #ifdef CONFIG_ATH9K_HTC_DEBUGFS - u32 txrate; + __be32 txrate; #endif spin_lock_irqsave(&priv->wmi->wmi_lock, flags); diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 611357158ecf..167e15c50062 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -19,7 +19,7 @@ struct wmi_event_txrate { - u32 txrate; + __be32 txrate; struct { u8 rssi_thresh; u8 per; @@ -27,8 +27,8 @@ struct wmi_event_txrate { } __packed; struct wmi_cmd_hdr { - u16 command_id; - u16 seq_no; + __be16 command_id; + __be16 seq_no; } __packed; struct wmi_swba { @@ -87,8 +87,8 @@ enum wmi_event_id { #define MAX_CMD_NUMBER 62 struct register_write { - u32 reg; - u32 val; + __be32 reg; + __be32 val; }; struct wmi { -- cgit v1.2.3 From a02a2956809d88b42b9a1f8003d60a343353b5ea Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Fri, 16 Apr 2010 13:22:12 +0300 Subject: wl1251: add support for dedicated IRQ line wl1251 has WLAN_IRQ pin for generating interrupts to host processor, which is mandatory in SPI mode and optional in SDIO mode (which can use SDIO interrupts instead). However TI recommends using deditated IRQ line for SDIO too. Add support for using dedicated interrupt line with SDIO, but also leave ability to switch to SDIO interrupts in case it's needed. Signed-off-by: Grazvydas Ignotas Reviewed-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_sdio.c | 56 ++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c index 7409c3468e25..d234285c2c81 100644 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "wl1251.h" @@ -134,18 +135,36 @@ static void wl1251_sdio_disable_irq(struct wl1251 *wl) sdio_release_host(func); } +/* Interrupts when using dedicated WLAN_IRQ pin */ +static irqreturn_t wl1251_line_irq(int irq, void *cookie) +{ + struct wl1251 *wl = cookie; + + ieee80211_queue_work(wl->hw, &wl->irq_work); + + return IRQ_HANDLED; +} + +static void wl1251_enable_line_irq(struct wl1251 *wl) +{ + return enable_irq(wl->irq); +} + +static void wl1251_disable_line_irq(struct wl1251 *wl) +{ + return disable_irq(wl->irq); +} + static void wl1251_sdio_set_power(bool enable) { } -static const struct wl1251_if_operations wl1251_sdio_ops = { +static struct wl1251_if_operations wl1251_sdio_ops = { .read = wl1251_sdio_read, .write = wl1251_sdio_write, .write_elp = wl1251_sdio_write_elp, .read_elp = wl1251_sdio_read_elp, .reset = wl1251_sdio_reset, - .enable_irq = wl1251_sdio_enable_irq, - .disable_irq = wl1251_sdio_disable_irq, }; static int wl1251_platform_probe(struct platform_device *pdev) @@ -191,6 +210,7 @@ static int wl1251_sdio_probe(struct sdio_func *func, goto release; sdio_set_block_size(func, 512); + sdio_release_host(func); SET_IEEE80211_DEV(hw, &func->dev); wl->if_priv = func; @@ -199,17 +219,41 @@ static int wl1251_sdio_probe(struct sdio_func *func, if (wl12xx_board_data != NULL) { wl->set_power = wl12xx_board_data->set_power; + wl->irq = wl12xx_board_data->irq; wl->use_eeprom = wl12xx_board_data->use_eeprom; } - sdio_release_host(func); + if (wl->irq) { + ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl); + if (ret < 0) { + wl1251_error("request_irq() failed: %d", ret); + goto disable; + } + + set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); + disable_irq(wl->irq); + + wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq; + wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq; + + wl1251_info("using dedicated interrupt line"); + } else { + wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq; + wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq; + + wl1251_info("using SDIO interrupt"); + } + ret = wl1251_init_ieee80211(wl); if (ret) - goto disable; + goto out_free_irq; sdio_set_drvdata(func, wl); return ret; +out_free_irq: + if (wl->irq) + free_irq(wl->irq, wl); disable: sdio_claim_host(func); sdio_disable_func(func); @@ -222,6 +266,8 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func) { struct wl1251 *wl = sdio_get_drvdata(func); + if (wl->irq) + free_irq(wl->irq, wl); wl1251_free_hw(wl); sdio_claim_host(func); -- cgit v1.2.3 From eb2ec0fb3c2fe85d42b2d5131e526daa0e298b9e Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 16 Apr 2010 15:46:41 +0200 Subject: iwlwifi: check scan request ie_len In mac80211 we always check both scan_req->ie and scan_req->ie_len against zero before usage, in iwlwifi we should do the same. Remove not needed "left -= ie_len" while at it. Signed-off-by: Stanislaw Gruszka Acked-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-scan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index d817c9c184a5..83e62917e0bf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -644,10 +644,10 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, if (WARN_ON(left < ie_len)) return len; - if (ies) + if (ies && ie_len) { memcpy(pos, ies, ie_len); - len += ie_len; - left -= ie_len; + len += ie_len; + } return (u16)len; } -- cgit v1.2.3 From 317a929dcd39bceff93974dac5fbdafa9b2a33ac Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 16 Apr 2010 15:47:56 +0200 Subject: iwlwifi: initialize iwl_wimax_coex_cmd.flags iwl_wimax_coex_cmd.flags can be really uninitialized, so fix that. Signed-off-by: Stanislaw Gruszka Acked-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index f09bff823ab6..2e489cd7b203 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2382,11 +2382,11 @@ EXPORT_SYMBOL(iwl_free_txq_mem); int iwl_send_wimax_coex(struct iwl_priv *priv) { - struct iwl_wimax_coex_cmd uninitialized_var(coex_cmd); + struct iwl_wimax_coex_cmd coex_cmd; if (priv->cfg->support_wimax_coexist) { /* UnMask wake up src at associated sleep */ - coex_cmd.flags |= COEX_FLAGS_ASSOC_WA_UNMASK_MSK; + coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK; /* UnMask wake up src at unassociated sleep */ coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK; -- cgit v1.2.3 From 3a23d69582fa4bfcb443631bcd3d0d2afcc19208 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 3 Apr 2010 16:44:39 -0700 Subject: iwlwifi: set correct single/dual stream mask Even the initial single/dual stream values will be overridden later when issue link quality command; but still make sense not to use hard-code value during initialization. Single/Dual stream mask are used to indicate the best antenna for SISO/MIMO; different NIC has different tx antenna configuration; so the parameter need to based on the valid tx antenna. 1x2 device: single tx antenna available, only SISO is valid configuration, but still need to set up MIMO configuration, so set it up with antenna A & B as default. 2x2 device: two tx antenna available, dual_stream will use both valid antenna. 3x3 device: three tx antenna available, skip the first antenna and choice the second and third antenna for dual_stream. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 13 +++++++++++-- drivers/net/wireless/iwlwifi/iwl-sta.c | 12 +++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 3c1cd417bbc5..5bc406c5c793 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2557,8 +2557,17 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i lq_sta->active_mimo3_rate); /* These values will be overridden later */ - lq_sta->lq.general_params.single_stream_ant_msk = ANT_A; - lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; + lq_sta->lq.general_params.single_stream_ant_msk = + first_antenna(priv->hw_params.valid_tx_ant); + lq_sta->lq.general_params.dual_stream_ant_msk = + priv->hw_params.valid_tx_ant & + ~first_antenna(priv->hw_params.valid_tx_ant); + if (!lq_sta->lq.general_params.dual_stream_ant_msk) { + lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; + } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { + lq_sta->lq.general_params.dual_stream_ant_msk = + priv->hw_params.valid_tx_ant; + } /* as default allow aggregation for all tids */ lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index d86ecd2f9ec2..09d9c4d56450 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -451,7 +451,17 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) link_cmd.general_params.single_stream_ant_msk = first_antenna(priv->hw_params.valid_tx_ant); - link_cmd.general_params.dual_stream_ant_msk = 3; + + link_cmd.general_params.dual_stream_ant_msk = + priv->hw_params.valid_tx_ant & + ~first_antenna(priv->hw_params.valid_tx_ant); + if (!link_cmd.general_params.dual_stream_ant_msk) { + link_cmd.general_params.dual_stream_ant_msk = ANT_AB; + } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { + link_cmd.general_params.dual_stream_ant_msk = + priv->hw_params.valid_tx_ant; + } + link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; link_cmd.agg_params.agg_time_limit = cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); -- cgit v1.2.3 From 00700ee007cf842ef2eb20201080ceddcfdaf9ad Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Apr 2010 04:12:37 -0700 Subject: iwlwifi: remove scan_bands logic Since mac80211 will now never request scanning multiple bands, we can remove all the associated logic and scan a single band only in each scan. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 59 +++++++++-------------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 16 ++++---- 3 files changed, 25 insertions(+), 52 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b2d94c7c6457..ee4cb028e138 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1054,7 +1054,7 @@ struct iwl_priv { unsigned long scan_pass_start; unsigned long scan_start_tsf; void *scan; - int scan_bands; + enum ieee80211_band scan_band; struct cfg80211_scan_request *scan_request; bool is_internal_short_scan; u8 scan_tx_ant[IEEE80211_NUM_BANDS]; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index c3b06c4b6f3e..3904bb45ca61 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -223,29 +223,16 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, clear_bit(STATUS_SCAN_HW, &priv->status); IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n", - (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ? - "2.4" : "5.2", + (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", jiffies_to_msecs(elapsed_jiffies (priv->scan_pass_start, jiffies))); - /* Remove this scanned band from the list of pending - * bands to scan, band G precedes A in order of scanning - * as seen in iwl_bg_request_scan */ - if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) - priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ); - else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) - priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ); - /* If a request to abort was given, or the scan did not succeed * then we reset the scan state machine and terminate, * re-queuing another scan if one has been requested */ if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { IWL_DEBUG_INFO(priv, "Aborted scan completed.\n"); clear_bit(STATUS_SCAN_ABORTING, &priv->status); - } else { - /* If there are more bands on this scan pass reschedule */ - if (priv->scan_bands) - goto reschedule; } if (!priv->is_internal_short_scan) @@ -259,12 +246,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies))); queue_work(priv->workqueue, &priv->scan_completed); - - return; - -reschedule: - priv->scan_pass_start = jiffies; - queue_work(priv->workqueue, &priv->request_scan); } void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) @@ -489,10 +470,13 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, { unsigned long flags; struct iwl_priv *priv = hw->priv; - int ret, i; + int ret; IWL_DEBUG_MAC80211(priv, "enter\n"); + if (req->n_channels == 0) + return -EINVAL; + mutex_lock(&priv->mutex); spin_lock_irqsave(&priv->lock, flags); @@ -526,10 +510,8 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, goto out_unlock; } - priv->scan_bands = 0; - for (i = 0; i < req->n_channels; i++) - priv->scan_bands |= BIT(req->channels[i]->band); - + /* mac80211 will only ask for one band at a time */ + priv->scan_band = req->channels[0]->band; priv->scan_request = req; ret = iwl_scan_initiate(priv); @@ -575,11 +557,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) goto unlock; } - priv->scan_bands = 0; - if (priv->band == IEEE80211_BAND_5GHZ) - priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ); - else - priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ); + priv->scan_band = priv->band; IWL_DEBUG_SCAN(priv, "Start internal short scan...\n"); set_bit(STATUS_SCANNING, &priv->status); @@ -727,11 +705,6 @@ static void iwl_bg_request_scan(struct work_struct *data) goto done; } - if (!priv->scan_bands) { - IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n"); - goto done; - } - if (!priv->scan) { priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE, GFP_KERNEL); @@ -798,9 +771,8 @@ static void iwl_bg_request_scan(struct work_struct *data) scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - - if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { - band = IEEE80211_BAND_2GHZ; + switch (priv->scan_band) { + case IEEE80211_BAND_2GHZ: scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK) >> RXON_FLG_CHANNEL_MODE_POS; @@ -811,8 +783,8 @@ static void iwl_bg_request_scan(struct work_struct *data) rate_flags = RATE_MCS_CCK_MSK; } scan->good_CRC_th = 0; - } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { - band = IEEE80211_BAND_5GHZ; + break; + case IEEE80211_BAND_5GHZ: rate = IWL_RATE_6M_PLCP; /* * If active scaning is requested but a certain channel @@ -827,13 +799,16 @@ static void iwl_bg_request_scan(struct work_struct *data) */ if (priv->cfg->off_channel_workaround) rx_ant = ANT_BC; - } else { + break; + default: IWL_WARN(priv, "Invalid scan band count\n"); goto done; } + band = priv->scan_band; + priv->scan_tx_ant[band] = - iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]); + iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]); rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 24e969440b31..e26669558fc2 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2852,11 +2852,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) goto done; } - if (!priv->scan_bands) { - IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n"); - goto done; - } - if (!priv->scan) { priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE, GFP_KERNEL); @@ -2934,12 +2929,14 @@ static void iwl3945_bg_request_scan(struct work_struct *data) /* flags + rate selection */ - if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { + switch (priv->scan_band) { + case IEEE80211_BAND_2GHZ: scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; scan->tx_cmd.rate = IWL_RATE_1M_PLCP; scan->good_CRC_th = 0; band = IEEE80211_BAND_2GHZ; - } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { + break; + case IEEE80211_BAND_5GHZ: scan->tx_cmd.rate = IWL_RATE_6M_PLCP; /* * If active scaning is requested but a certain channel @@ -2948,8 +2945,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data) */ scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; band = IEEE80211_BAND_5GHZ; - } else { - IWL_WARN(priv, "Invalid scan band count\n"); + break; + default: + IWL_WARN(priv, "Invalid scan band\n"); goto done; } -- cgit v1.2.3 From 6708dc863880777ffe5fc55c86bfd80f886f53d6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Apr 2010 04:12:38 -0700 Subject: iwlwifi: correct atomic bitops usage With atomic bitops, test_and_{set,clear}_bit should be used instead of separate test_bit and set_bit/clear_bit. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-scan.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 3904bb45ca61..7982b1930763 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -68,9 +68,8 @@ int iwl_scan_cancel(struct iwl_priv *priv) } if (test_bit(STATUS_SCANNING, &priv->status)) { - if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) { + if (!test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n"); - set_bit(STATUS_SCAN_ABORTING, &priv->status); queue_work(priv->workqueue, &priv->abort_scan); } else @@ -227,13 +226,13 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, jiffies_to_msecs(elapsed_jiffies (priv->scan_pass_start, jiffies))); - /* If a request to abort was given, or the scan did not succeed + /* + * If a request to abort was given, or the scan did not succeed * then we reset the scan state machine and terminate, - * re-queuing another scan if one has been requested */ - if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { + * re-queuing another scan if one has been requested + */ + if (test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status)) IWL_DEBUG_INFO(priv, "Aborted scan completed.\n"); - clear_bit(STATUS_SCAN_ABORTING, &priv->status); - } if (!priv->is_internal_short_scan) priv->next_scan_jiffies = 0; -- cgit v1.2.3 From 92ae80eec7ac642f249b7a2fc02f41441d128a62 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Apr 2010 04:12:39 -0700 Subject: iwlwifi: remove next_scan_jiffies This logic is just confusing, if anything it belongs into mac80211. Also, even if we do scan during the EAPOL handshake, that will not cause any problems, just a short delay. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 9 --------- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-scan.c | 20 -------------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 ----- 4 files changed, 35 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 73f5fc6c35d5..9d300b2d9fe3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1867,7 +1867,6 @@ static inline void iwl_set_no_assoc(struct iwl_priv *priv) iwlcore_commit_rxon(priv); } -#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -1988,14 +1987,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, iwl_led_associate(priv); - /* - * We have just associated, don't start scan too early - * leave time for EAPOL exchange to complete. - * - * XXX: do this in mac80211 - */ - priv->next_scan_jiffies = jiffies + - IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; if (!iwl_is_rfkill(priv)) priv->cfg->ops->lib->post_associate(priv); } else diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index ee4cb028e138..f2d4ca5b132a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1049,7 +1049,6 @@ struct iwl_priv { struct iwl_calib_result calib_results[IWL_CALIB_MAX]; /* Scan related variables */ - unsigned long next_scan_jiffies; unsigned long scan_start; unsigned long scan_pass_start; unsigned long scan_start_tsf; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 7982b1930763..e45b49ada9fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -199,9 +199,6 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv, le32_to_cpu(notif->statistics[0]), le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf); #endif - - if (!priv->is_internal_short_scan) - priv->next_scan_jiffies = 0; } /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ @@ -234,9 +231,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, if (test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status)) IWL_DEBUG_INFO(priv, "Aborted scan completed.\n"); - if (!priv->is_internal_short_scan) - priv->next_scan_jiffies = 0; - IWL_DEBUG_INFO(priv, "Setting scan to off\n"); clear_bit(STATUS_SCANNING, &priv->status); @@ -462,8 +456,6 @@ static int iwl_scan_initiate(struct iwl_priv *priv) return 0; } -#define IWL_DELAY_NEXT_SCAN (HZ*2) - int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req) { @@ -497,18 +489,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, goto out_unlock; } - /* We don't schedule scan within next_scan_jiffies period. - * Avoid scanning during possible EAPOL exchange, return - * success immediately. - */ - if (priv->next_scan_jiffies && - time_after(priv->next_scan_jiffies, jiffies)) { - IWL_DEBUG_SCAN(priv, "scan rejected: within next scan period\n"); - queue_work(priv->workqueue, &priv->scan_completed); - ret = 0; - goto out_unlock; - } - /* mac80211 will only ask for one band at a time */ priv->scan_band = req->channels[0]->band; priv->scan_request = req; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index e26669558fc2..af32359400b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3048,8 +3048,6 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data) mutex_unlock(&priv->mutex); } -#define IWL_DELAY_NEXT_SCAN (HZ*2) - void iwl3945_post_associate(struct iwl_priv *priv) { int rc = 0; @@ -3134,9 +3132,6 @@ void iwl3945_post_associate(struct iwl_priv *priv) __func__, priv->iw_mode); break; } - - /* we have just associated, don't start scan too early */ - priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; } /***************************************************************************** -- cgit v1.2.3 From b165cf09c0248262232c7566df5ae40284cee7d6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Apr 2010 04:12:40 -0700 Subject: iwlwifi: remove scan_pass_start Since we no longer do a multi-pass scan, keeping track of how long each pass took is pointless since there will only be one. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-scan.c | 8 ++------ 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f2d4ca5b132a..a7ffb4f9280a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1050,7 +1050,6 @@ struct iwl_priv { /* Scan related variables */ unsigned long scan_start; - unsigned long scan_pass_start; unsigned long scan_start_tsf; void *scan; enum ieee80211_band scan_band; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index e45b49ada9fa..cb3601dabf29 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -218,10 +218,10 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, /* The HW is no longer scanning */ clear_bit(STATUS_SCAN_HW, &priv->status); - IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n", + IWL_DEBUG_INFO(priv, "Scan on %sGHz took %dms\n", (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", jiffies_to_msecs(elapsed_jiffies - (priv->scan_pass_start, jiffies))); + (priv->scan_start, jiffies))); /* * If a request to abort was given, or the scan did not succeed @@ -235,9 +235,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, clear_bit(STATUS_SCANNING, &priv->status); - IWL_DEBUG_INFO(priv, "Scan took %dms\n", - jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies))); - queue_work(priv->workqueue, &priv->scan_completed); } @@ -449,7 +446,6 @@ static int iwl_scan_initiate(struct iwl_priv *priv) set_bit(STATUS_SCANNING, &priv->status); priv->is_internal_short_scan = false; priv->scan_start = jiffies; - priv->scan_pass_start = priv->scan_start; queue_work(priv->workqueue, &priv->request_scan); -- cgit v1.2.3 From 811ecc995b18eb58067ffa75b961ece3b84a1f03 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Apr 2010 04:12:41 -0700 Subject: iwlwifi: rename priv->scan to priv->scan_cmd I keep checking what "priv->scan" is, so rename it to "priv->scan_cmd" which more clearly tells us what it is. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 10 +++++----- drivers/net/wireless/iwlwifi/iwl3945-base.c | 12 ++++++------ 4 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 955315b26435..31998188e879 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3400,7 +3400,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv) iwl_calib_free_results(priv); iwlcore_free_geos(priv); iwl_free_channel_map(priv); - kfree(priv->scan); + kfree(priv->scan_cmd); } static struct attribute *iwl_sysfs_entries[] = { diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index a7ffb4f9280a..4007b5785275 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1051,7 +1051,7 @@ struct iwl_priv { /* Scan related variables */ unsigned long scan_start; unsigned long scan_start_tsf; - void *scan; + void *scan_cmd; enum ieee80211_band scan_band; struct cfg80211_scan_request *scan_request; bool is_internal_short_scan; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index cb3601dabf29..18b89d3bd88d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -680,16 +680,16 @@ static void iwl_bg_request_scan(struct work_struct *data) goto done; } - if (!priv->scan) { - priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) + - IWL_MAX_SCAN_SIZE, GFP_KERNEL); - if (!priv->scan) { + if (!priv->scan_cmd) { + priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + + IWL_MAX_SCAN_SIZE, GFP_KERNEL); + if (!priv->scan_cmd) { IWL_DEBUG_SCAN(priv, "fail to allocate memory for scan\n"); goto done; } } - scan = priv->scan; + scan = priv->scan_cmd; memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index af32359400b3..0f773973a4e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2852,15 +2852,15 @@ static void iwl3945_bg_request_scan(struct work_struct *data) goto done; } - if (!priv->scan) { - priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) + - IWL_MAX_SCAN_SIZE, GFP_KERNEL); - if (!priv->scan) { + if (!priv->scan_cmd) { + priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) + + IWL_MAX_SCAN_SIZE, GFP_KERNEL); + if (!priv->scan_cmd) { IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n"); goto done; } } - scan = priv->scan; + scan = priv->scan_cmd; memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE); scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; @@ -4245,7 +4245,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl_free_channel_map(priv); iwlcore_free_geos(priv); - kfree(priv->scan); + kfree(priv->scan_cmd); if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); -- cgit v1.2.3 From b6e4c55aaee4fd40526a6816e60c68dd62e565c4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Apr 2010 04:12:42 -0700 Subject: iwlwifi: trigger scan synchronously Scan requesting doesn't need to be asynchronous since all code paths leading up to it can sleep. Make the scan request a new util operation that is hw-specific (to account for 3945 vs. agn) and call it right in place. This patch moves a lot of code into iwlagn as it need not be in iwlcore. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945.c | 1 + drivers/net/wireless/iwlwifi/iwl-3945.h | 3 + drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 395 ++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 3 + drivers/net/wireless/iwlwifi/iwl-core.h | 2 + drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-scan.c | 418 +--------------------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 10 +- 10 files changed, 416 insertions(+), 419 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 15de649888d8..51f18950f077 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2740,6 +2740,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { .get_hcmd_size = iwl3945_get_hcmd_size, .build_addsta_hcmd = iwl3945_build_addsta_hcmd, .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, + .request_scan = iwl3945_request_scan, }; static const struct iwl_ops iwl3945_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index b89219573b91..e9674f0a1e94 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -294,6 +294,9 @@ extern const struct iwl_channel_info *iwl3945_get_channel_info( extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate); +/* scanning */ +void iwl3945_request_scan(struct iwl_priv *priv); + /* Requires full declaration of iwl_priv before including */ #include "iwl-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 2e3cda75f3ad..0a5f21e14882 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2162,6 +2162,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { .gain_computation = iwl4965_gain_computation, .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, .calc_rssi = iwl4965_calc_rssi, + .request_scan = iwlagn_request_scan, }; static struct iwl_lib_ops iwl4965_lib = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 28bc8f8ba981..231d0e67e6fc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -271,4 +271,5 @@ struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { .chain_noise_reset = iwlagn_chain_noise_reset, .rts_tx_cmd_flag = iwlagn_rts_tx_cmd_flag, .calc_rssi = iwlagn_calc_rssi, + .request_scan = iwlagn_request_scan, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index c465c8590833..048c6156d3be 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1111,3 +1111,398 @@ void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, memcpy(&priv->_agn.last_phy_res, pkt->u.raw, sizeof(struct iwl_rx_phy_res)); } + +static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, + enum ieee80211_band band, + struct iwl_scan_channel *scan_ch) +{ + const struct ieee80211_supported_band *sband; + const struct iwl_channel_info *ch_info; + u16 passive_dwell = 0; + u16 active_dwell = 0; + int i, added = 0; + u16 channel = 0; + + sband = iwl_get_hw_mode(priv, band); + if (!sband) { + IWL_ERR(priv, "invalid band\n"); + return added; + } + + active_dwell = iwl_get_active_dwell_time(priv, band, 0); + passive_dwell = iwl_get_passive_dwell_time(priv, band); + + if (passive_dwell <= active_dwell) + passive_dwell = active_dwell + 1; + + /* only scan single channel, good enough to reset the RF */ + /* pick the first valid not in-use channel */ + if (band == IEEE80211_BAND_5GHZ) { + for (i = 14; i < priv->channel_count; i++) { + if (priv->channel_info[i].channel != + le16_to_cpu(priv->staging_rxon.channel)) { + channel = priv->channel_info[i].channel; + ch_info = iwl_get_channel_info(priv, + band, channel); + if (is_channel_valid(ch_info)) + break; + } + } + } else { + for (i = 0; i < 14; i++) { + if (priv->channel_info[i].channel != + le16_to_cpu(priv->staging_rxon.channel)) { + channel = + priv->channel_info[i].channel; + ch_info = iwl_get_channel_info(priv, + band, channel); + if (is_channel_valid(ch_info)) + break; + } + } + } + if (channel) { + scan_ch->channel = cpu_to_le16(channel); + scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; + scan_ch->active_dwell = cpu_to_le16(active_dwell); + scan_ch->passive_dwell = cpu_to_le16(passive_dwell); + /* Set txpower levels to defaults */ + scan_ch->dsp_atten = 110; + if (band == IEEE80211_BAND_5GHZ) + scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; + else + scan_ch->tx_gain = ((1 << 5) | (5 << 3)); + added++; + } else + IWL_ERR(priv, "no valid channel found\n"); + return added; +} + +static int iwl_get_channels_for_scan(struct iwl_priv *priv, + enum ieee80211_band band, + u8 is_active, u8 n_probes, + struct iwl_scan_channel *scan_ch) +{ + struct ieee80211_channel *chan; + const struct ieee80211_supported_band *sband; + const struct iwl_channel_info *ch_info; + u16 passive_dwell = 0; + u16 active_dwell = 0; + int added, i; + u16 channel; + + sband = iwl_get_hw_mode(priv, band); + if (!sband) + return 0; + + active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); + passive_dwell = iwl_get_passive_dwell_time(priv, band); + + if (passive_dwell <= active_dwell) + passive_dwell = active_dwell + 1; + + for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) { + chan = priv->scan_request->channels[i]; + + if (chan->band != band) + continue; + + channel = ieee80211_frequency_to_channel(chan->center_freq); + scan_ch->channel = cpu_to_le16(channel); + + ch_info = iwl_get_channel_info(priv, band, channel); + if (!is_channel_valid(ch_info)) { + IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n", + channel); + continue; + } + + if (!is_active || is_channel_passive(ch_info) || + (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) + scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; + else + scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; + + if (n_probes) + scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); + + scan_ch->active_dwell = cpu_to_le16(active_dwell); + scan_ch->passive_dwell = cpu_to_le16(passive_dwell); + + /* Set txpower levels to defaults */ + scan_ch->dsp_atten = 110; + + /* NOTE: if we were doing 6Mb OFDM for scans we'd use + * power level: + * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; + */ + if (band == IEEE80211_BAND_5GHZ) + scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; + else + scan_ch->tx_gain = ((1 << 5) | (5 << 3)); + + IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n", + channel, le32_to_cpu(scan_ch->type), + (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? + "ACTIVE" : "PASSIVE", + (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? + active_dwell : passive_dwell); + + scan_ch++; + added++; + } + + IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); + return added; +} + +void iwlagn_request_scan(struct iwl_priv *priv) +{ + struct iwl_host_cmd cmd = { + .id = REPLY_SCAN_CMD, + .len = sizeof(struct iwl_scan_cmd), + .flags = CMD_SIZE_HUGE, + }; + struct iwl_scan_cmd *scan; + struct ieee80211_conf *conf = NULL; + u32 rate_flags = 0; + u16 cmd_len; + u16 rx_chain = 0; + enum ieee80211_band band; + u8 n_probes = 0; + u8 rx_ant = priv->hw_params.valid_rx_ant; + u8 rate; + bool is_active = false; + int chan_mod; + u8 active_chains; + + conf = ieee80211_get_hw_conf(priv->hw); + + cancel_delayed_work(&priv->scan_check); + + if (!iwl_is_ready(priv)) { + IWL_WARN(priv, "request scan called when driver not ready.\n"); + goto done; + } + + /* Make sure the scan wasn't canceled before this queued work + * was given the chance to run... */ + if (!test_bit(STATUS_SCANNING, &priv->status)) + goto done; + + /* This should never be called or scheduled if there is currently + * a scan active in the hardware. */ + if (test_bit(STATUS_SCAN_HW, &priv->status)) { + IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. " + "Ignoring second request.\n"); + goto done; + } + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { + IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n"); + goto done; + } + + if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { + IWL_DEBUG_HC(priv, "Scan request while abort pending. Queuing.\n"); + goto done; + } + + if (iwl_is_rfkill(priv)) { + IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n"); + goto done; + } + + if (!test_bit(STATUS_READY, &priv->status)) { + IWL_DEBUG_HC(priv, "Scan request while uninitialized. Queuing.\n"); + goto done; + } + + if (!priv->scan_cmd) { + priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + + IWL_MAX_SCAN_SIZE, GFP_KERNEL); + if (!priv->scan_cmd) { + IWL_DEBUG_SCAN(priv, + "fail to allocate memory for scan\n"); + goto done; + } + } + scan = priv->scan_cmd; + memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); + + scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; + scan->quiet_time = IWL_ACTIVE_QUIET_TIME; + + if (iwl_is_associated(priv)) { + u16 interval = 0; + u32 extra; + u32 suspend_time = 100; + u32 scan_suspend_time = 100; + unsigned long flags; + + IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); + spin_lock_irqsave(&priv->lock, flags); + interval = priv->beacon_int; + spin_unlock_irqrestore(&priv->lock, flags); + + scan->suspend_time = 0; + scan->max_out_time = cpu_to_le32(200 * 1024); + if (!interval) + interval = suspend_time; + + extra = (suspend_time / interval) << 22; + scan_suspend_time = (extra | + ((suspend_time % interval) * 1024)); + scan->suspend_time = cpu_to_le32(scan_suspend_time); + IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", + scan_suspend_time, interval); + } + + if (priv->is_internal_short_scan) { + IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); + } else if (priv->scan_request->n_ssids) { + int i, p = 0; + IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); + for (i = 0; i < priv->scan_request->n_ssids; i++) { + /* always does wildcard anyway */ + if (!priv->scan_request->ssids[i].ssid_len) + continue; + scan->direct_scan[p].id = WLAN_EID_SSID; + scan->direct_scan[p].len = + priv->scan_request->ssids[i].ssid_len; + memcpy(scan->direct_scan[p].ssid, + priv->scan_request->ssids[i].ssid, + priv->scan_request->ssids[i].ssid_len); + n_probes++; + p++; + } + is_active = true; + } else + IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); + + scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; + scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; + scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; + + switch (priv->scan_band) { + case IEEE80211_BAND_2GHZ: + scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; + chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK) + >> RXON_FLG_CHANNEL_MODE_POS; + if (chan_mod == CHANNEL_MODE_PURE_40) { + rate = IWL_RATE_6M_PLCP; + } else { + rate = IWL_RATE_1M_PLCP; + rate_flags = RATE_MCS_CCK_MSK; + } + scan->good_CRC_th = 0; + break; + case IEEE80211_BAND_5GHZ: + rate = IWL_RATE_6M_PLCP; + /* + * If active scaning is requested but a certain channel + * is marked passive, we can do active scanning if we + * detect transmissions. + */ + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; + + /* Force use of chains B and C (0x6) for scan Rx + * Avoid A (0x1) for the device has off-channel reception + * on A-band. + */ + if (priv->cfg->off_channel_workaround) + rx_ant = ANT_BC; + break; + default: + IWL_WARN(priv, "Invalid scan band count\n"); + goto done; + } + + band = priv->scan_band; + + priv->scan_tx_ant[band] = + iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]); + rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); + scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); + + /* In power save mode use one chain, otherwise use all chains */ + if (test_bit(STATUS_POWER_PMI, &priv->status)) { + /* rx_ant has been set to all valid chains previously */ + active_chains = rx_ant & + ((u8)(priv->chain_noise_data.active_chains)); + if (!active_chains) + active_chains = rx_ant; + + IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n", + priv->chain_noise_data.active_chains); + + rx_ant = first_antenna(active_chains); + } + /* MIMO is not used here, but value is required */ + rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; + rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; + rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; + rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; + scan->rx_chain = cpu_to_le16(rx_chain); + if (!priv->is_internal_short_scan) { + cmd_len = iwl_fill_probe_req(priv, + (struct ieee80211_mgmt *)scan->data, + priv->scan_request->ie, + priv->scan_request->ie_len, + IWL_MAX_SCAN_SIZE - sizeof(*scan)); + } else { + cmd_len = iwl_fill_probe_req(priv, + (struct ieee80211_mgmt *)scan->data, + NULL, 0, + IWL_MAX_SCAN_SIZE - sizeof(*scan)); + + } + scan->tx_cmd.len = cpu_to_le16(cmd_len); + if (iwl_is_monitor_mode(priv)) + scan->filter_flags = RXON_FILTER_PROMISC_MSK; + + scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | + RXON_FILTER_BCON_AWARE_MSK); + + if (priv->is_internal_short_scan) { + scan->channel_count = + iwl_get_single_channel_for_scan(priv, band, + (void *)&scan->data[le16_to_cpu( + scan->tx_cmd.len)]); + } else { + scan->channel_count = + iwl_get_channels_for_scan(priv, band, + is_active, n_probes, + (void *)&scan->data[le16_to_cpu( + scan->tx_cmd.len)]); + } + if (scan->channel_count == 0) { + IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); + goto done; + } + + cmd.len += le16_to_cpu(scan->tx_cmd.len) + + scan->channel_count * sizeof(struct iwl_scan_channel); + cmd.data = scan; + scan->len = cpu_to_le16(cmd.len); + + set_bit(STATUS_SCAN_HW, &priv->status); + if (iwl_send_cmd_sync(priv, &cmd)) + goto done; + + queue_delayed_work(priv->workqueue, &priv->scan_check, + IWL_SCAN_CHECK_WATCHDOG); + + return; + + done: + /* Cannot perform scan. Make sure we clear scanning + * bits from status so next scan request can be performed. + * If we don't clear scanning status bit here all next scan + * will fail + */ + clear_bit(STATUS_SCAN_HW, &priv->status); + clear_bit(STATUS_SCANNING, &priv->status); + /* inform mac80211 scan aborted */ + queue_work(priv->workqueue, &priv->scan_completed); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 5d3142287e14..cfee9994383e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -171,4 +171,7 @@ static inline bool iwl_is_tx_success(u32 status) (status == TX_STATUS_DIRECT_DONE); } +/* scan */ +void iwlagn_request_scan(struct iwl_priv *priv); + #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 6c3f0127f743..1d91ffdd4203 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -105,6 +105,7 @@ struct iwl_hcmd_utils_ops { __le32 *tx_flags); int (*calc_rssi)(struct iwl_priv *priv, struct iwl_rx_phy_res *rx_resp); + void (*request_scan)(struct iwl_priv *priv); }; struct iwl_apm_ops { @@ -526,6 +527,7 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv); #define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10) /* msec */ #define IWL_PLCP_QUIET_THRESH cpu_to_le16(1) /* packets */ +#define IWL_SCAN_CHECK_WATCHDOG (HZ * 7) /******************************************************************************* * Calibrations - implemented in iwl-calib.c diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 4007b5785275..dc9d8ae7e26d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1257,7 +1257,6 @@ struct iwl_priv { struct work_struct scan_completed; struct work_struct rx_replenish; struct work_struct abort_scan; - struct work_struct request_scan; struct work_struct beacon_update; struct work_struct tt_work; struct work_struct ct_enter; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 18b89d3bd88d..92115f59ab85 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -284,150 +284,6 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_get_passive_dwell_time); -static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, - enum ieee80211_band band, - struct iwl_scan_channel *scan_ch) -{ - const struct ieee80211_supported_band *sband; - const struct iwl_channel_info *ch_info; - u16 passive_dwell = 0; - u16 active_dwell = 0; - int i, added = 0; - u16 channel = 0; - - sband = iwl_get_hw_mode(priv, band); - if (!sband) { - IWL_ERR(priv, "invalid band\n"); - return added; - } - - active_dwell = iwl_get_active_dwell_time(priv, band, 0); - passive_dwell = iwl_get_passive_dwell_time(priv, band); - - if (passive_dwell <= active_dwell) - passive_dwell = active_dwell + 1; - - /* only scan single channel, good enough to reset the RF */ - /* pick the first valid not in-use channel */ - if (band == IEEE80211_BAND_5GHZ) { - for (i = 14; i < priv->channel_count; i++) { - if (priv->channel_info[i].channel != - le16_to_cpu(priv->staging_rxon.channel)) { - channel = priv->channel_info[i].channel; - ch_info = iwl_get_channel_info(priv, - band, channel); - if (is_channel_valid(ch_info)) - break; - } - } - } else { - for (i = 0; i < 14; i++) { - if (priv->channel_info[i].channel != - le16_to_cpu(priv->staging_rxon.channel)) { - channel = - priv->channel_info[i].channel; - ch_info = iwl_get_channel_info(priv, - band, channel); - if (is_channel_valid(ch_info)) - break; - } - } - } - if (channel) { - scan_ch->channel = cpu_to_le16(channel); - scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; - scan_ch->active_dwell = cpu_to_le16(active_dwell); - scan_ch->passive_dwell = cpu_to_le16(passive_dwell); - /* Set txpower levels to defaults */ - scan_ch->dsp_atten = 110; - if (band == IEEE80211_BAND_5GHZ) - scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; - else - scan_ch->tx_gain = ((1 << 5) | (5 << 3)); - added++; - } else - IWL_ERR(priv, "no valid channel found\n"); - return added; -} - -static int iwl_get_channels_for_scan(struct iwl_priv *priv, - enum ieee80211_band band, - u8 is_active, u8 n_probes, - struct iwl_scan_channel *scan_ch) -{ - struct ieee80211_channel *chan; - const struct ieee80211_supported_band *sband; - const struct iwl_channel_info *ch_info; - u16 passive_dwell = 0; - u16 active_dwell = 0; - int added, i; - u16 channel; - - sband = iwl_get_hw_mode(priv, band); - if (!sband) - return 0; - - active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); - passive_dwell = iwl_get_passive_dwell_time(priv, band); - - if (passive_dwell <= active_dwell) - passive_dwell = active_dwell + 1; - - for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) { - chan = priv->scan_request->channels[i]; - - if (chan->band != band) - continue; - - channel = ieee80211_frequency_to_channel(chan->center_freq); - scan_ch->channel = cpu_to_le16(channel); - - ch_info = iwl_get_channel_info(priv, band, channel); - if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n", - channel); - continue; - } - - if (!is_active || is_channel_passive(ch_info) || - (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) - scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; - else - scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; - - if (n_probes) - scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); - - scan_ch->active_dwell = cpu_to_le16(active_dwell); - scan_ch->passive_dwell = cpu_to_le16(passive_dwell); - - /* Set txpower levels to defaults */ - scan_ch->dsp_atten = 110; - - /* NOTE: if we were doing 6Mb OFDM for scans we'd use - * power level: - * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; - */ - if (band == IEEE80211_BAND_5GHZ) - scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; - else - scan_ch->tx_gain = ((1 << 5) | (5 << 3)); - - IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n", - channel, le32_to_cpu(scan_ch->type), - (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? - "ACTIVE" : "PASSIVE", - (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? - active_dwell : passive_dwell); - - scan_ch++; - added++; - } - - IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); - return added; -} - void iwl_init_scan_params(struct iwl_priv *priv) { u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1; @@ -447,7 +303,10 @@ static int iwl_scan_initiate(struct iwl_priv *priv) priv->is_internal_short_scan = false; priv->scan_start = jiffies; - queue_work(priv->workqueue, &priv->request_scan); + if (WARN_ON(!priv->cfg->ops->utils->request_scan)) + return -EOPNOTSUPP; + + priv->cfg->ops->utils->request_scan(priv); return 0; } @@ -455,7 +314,6 @@ static int iwl_scan_initiate(struct iwl_priv *priv) int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req) { - unsigned long flags; struct iwl_priv *priv = hw->priv; int ret; @@ -465,7 +323,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, return -EINVAL; mutex_lock(&priv->mutex); - spin_lock_irqsave(&priv->lock, flags); if (!iwl_is_ready_rf(priv)) { ret = -EIO; @@ -494,7 +351,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "leave\n"); out_unlock: - spin_unlock_irqrestore(&priv->lock, flags); mutex_unlock(&priv->mutex); return ret; @@ -537,13 +393,15 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) IWL_DEBUG_SCAN(priv, "Start internal short scan...\n"); set_bit(STATUS_SCANNING, &priv->status); priv->is_internal_short_scan = true; - queue_work(priv->workqueue, &priv->request_scan); + + if (WARN_ON(!priv->cfg->ops->utils->request_scan)) + goto unlock; + + priv->cfg->ops->utils->request_scan(priv); unlock: mutex_unlock(&priv->mutex); } -#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) - void iwl_bg_scan_check(struct work_struct *data) { struct iwl_priv *priv = @@ -614,263 +472,6 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, } EXPORT_SYMBOL(iwl_fill_probe_req); -static void iwl_bg_request_scan(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, request_scan); - struct iwl_host_cmd cmd = { - .id = REPLY_SCAN_CMD, - .len = sizeof(struct iwl_scan_cmd), - .flags = CMD_SIZE_HUGE, - }; - struct iwl_scan_cmd *scan; - struct ieee80211_conf *conf = NULL; - u32 rate_flags = 0; - u16 cmd_len; - u16 rx_chain = 0; - enum ieee80211_band band; - u8 n_probes = 0; - u8 rx_ant = priv->hw_params.valid_rx_ant; - u8 rate; - bool is_active = false; - int chan_mod; - u8 active_chains; - - conf = ieee80211_get_hw_conf(priv->hw); - - mutex_lock(&priv->mutex); - - cancel_delayed_work(&priv->scan_check); - - if (!iwl_is_ready(priv)) { - IWL_WARN(priv, "request scan called when driver not ready.\n"); - goto done; - } - - /* Make sure the scan wasn't canceled before this queued work - * was given the chance to run... */ - if (!test_bit(STATUS_SCANNING, &priv->status)) - goto done; - - /* This should never be called or scheduled if there is currently - * a scan active in the hardware. */ - if (test_bit(STATUS_SCAN_HW, &priv->status)) { - IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. " - "Ignoring second request.\n"); - goto done; - } - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n"); - goto done; - } - - if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_HC(priv, "Scan request while abort pending. Queuing.\n"); - goto done; - } - - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n"); - goto done; - } - - if (!test_bit(STATUS_READY, &priv->status)) { - IWL_DEBUG_HC(priv, "Scan request while uninitialized. Queuing.\n"); - goto done; - } - - if (!priv->scan_cmd) { - priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + - IWL_MAX_SCAN_SIZE, GFP_KERNEL); - if (!priv->scan_cmd) { - IWL_DEBUG_SCAN(priv, - "fail to allocate memory for scan\n"); - goto done; - } - } - scan = priv->scan_cmd; - memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); - - scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; - scan->quiet_time = IWL_ACTIVE_QUIET_TIME; - - if (iwl_is_associated(priv)) { - u16 interval = 0; - u32 extra; - u32 suspend_time = 100; - u32 scan_suspend_time = 100; - unsigned long flags; - - IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); - spin_lock_irqsave(&priv->lock, flags); - interval = priv->beacon_int; - spin_unlock_irqrestore(&priv->lock, flags); - - scan->suspend_time = 0; - scan->max_out_time = cpu_to_le32(200 * 1024); - if (!interval) - interval = suspend_time; - - extra = (suspend_time / interval) << 22; - scan_suspend_time = (extra | - ((suspend_time % interval) * 1024)); - scan->suspend_time = cpu_to_le32(scan_suspend_time); - IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", - scan_suspend_time, interval); - } - - if (priv->is_internal_short_scan) { - IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); - } else if (priv->scan_request->n_ssids) { - int i, p = 0; - IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); - for (i = 0; i < priv->scan_request->n_ssids; i++) { - /* always does wildcard anyway */ - if (!priv->scan_request->ssids[i].ssid_len) - continue; - scan->direct_scan[p].id = WLAN_EID_SSID; - scan->direct_scan[p].len = - priv->scan_request->ssids[i].ssid_len; - memcpy(scan->direct_scan[p].ssid, - priv->scan_request->ssids[i].ssid, - priv->scan_request->ssids[i].ssid_len); - n_probes++; - p++; - } - is_active = true; - } else - IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); - - scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; - scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; - scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - - switch (priv->scan_band) { - case IEEE80211_BAND_2GHZ: - scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; - chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK) - >> RXON_FLG_CHANNEL_MODE_POS; - if (chan_mod == CHANNEL_MODE_PURE_40) { - rate = IWL_RATE_6M_PLCP; - } else { - rate = IWL_RATE_1M_PLCP; - rate_flags = RATE_MCS_CCK_MSK; - } - scan->good_CRC_th = 0; - break; - case IEEE80211_BAND_5GHZ: - rate = IWL_RATE_6M_PLCP; - /* - * If active scaning is requested but a certain channel - * is marked passive, we can do active scanning if we - * detect transmissions. - */ - scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; - - /* Force use of chains B and C (0x6) for scan Rx - * Avoid A (0x1) for the device has off-channel reception - * on A-band. - */ - if (priv->cfg->off_channel_workaround) - rx_ant = ANT_BC; - break; - default: - IWL_WARN(priv, "Invalid scan band count\n"); - goto done; - } - - band = priv->scan_band; - - priv->scan_tx_ant[band] = - iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]); - rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); - scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); - - /* In power save mode use one chain, otherwise use all chains */ - if (test_bit(STATUS_POWER_PMI, &priv->status)) { - /* rx_ant has been set to all valid chains previously */ - active_chains = rx_ant & - ((u8)(priv->chain_noise_data.active_chains)); - if (!active_chains) - active_chains = rx_ant; - - IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n", - priv->chain_noise_data.active_chains); - - rx_ant = first_antenna(active_chains); - } - /* MIMO is not used here, but value is required */ - rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; - rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; - rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; - rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; - scan->rx_chain = cpu_to_le16(rx_chain); - if (!priv->is_internal_short_scan) { - cmd_len = iwl_fill_probe_req(priv, - (struct ieee80211_mgmt *)scan->data, - priv->scan_request->ie, - priv->scan_request->ie_len, - IWL_MAX_SCAN_SIZE - sizeof(*scan)); - } else { - cmd_len = iwl_fill_probe_req(priv, - (struct ieee80211_mgmt *)scan->data, - NULL, 0, - IWL_MAX_SCAN_SIZE - sizeof(*scan)); - - } - scan->tx_cmd.len = cpu_to_le16(cmd_len); - if (iwl_is_monitor_mode(priv)) - scan->filter_flags = RXON_FILTER_PROMISC_MSK; - - scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | - RXON_FILTER_BCON_AWARE_MSK); - - if (priv->is_internal_short_scan) { - scan->channel_count = - iwl_get_single_channel_for_scan(priv, band, - (void *)&scan->data[le16_to_cpu( - scan->tx_cmd.len)]); - } else { - scan->channel_count = - iwl_get_channels_for_scan(priv, band, - is_active, n_probes, - (void *)&scan->data[le16_to_cpu( - scan->tx_cmd.len)]); - } - if (scan->channel_count == 0) { - IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); - goto done; - } - - cmd.len += le16_to_cpu(scan->tx_cmd.len) + - scan->channel_count * sizeof(struct iwl_scan_channel); - cmd.data = scan; - scan->len = cpu_to_le16(cmd.len); - - set_bit(STATUS_SCAN_HW, &priv->status); - if (iwl_send_cmd_sync(priv, &cmd)) - goto done; - - queue_delayed_work(priv->workqueue, &priv->scan_check, - IWL_SCAN_CHECK_WATCHDOG); - - mutex_unlock(&priv->mutex); - return; - - done: - /* Cannot perform scan. Make sure we clear scanning - * bits from status so next scan request can be performed. - * If we don't clear scanning status bit here all next scan - * will fail - */ - clear_bit(STATUS_SCAN_HW, &priv->status); - clear_bit(STATUS_SCANNING, &priv->status); - /* inform mac80211 scan aborted */ - queue_work(priv->workqueue, &priv->scan_completed); - mutex_unlock(&priv->mutex); -} - void iwl_bg_abort_scan(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); @@ -918,7 +519,6 @@ EXPORT_SYMBOL(iwl_bg_scan_completed); void iwl_setup_scan_deferred_work(struct iwl_priv *priv) { INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); - INIT_WORK(&priv->request_scan, iwl_bg_request_scan); INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan); INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 0f773973a4e5..06004d03f20b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2790,11 +2790,8 @@ static void iwl3945_rfkill_poll(struct work_struct *data) } -#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) -static void iwl3945_bg_request_scan(struct work_struct *data) +void iwl3945_request_scan(struct iwl_priv *priv) { - struct iwl_priv *priv = - container_of(data, struct iwl_priv, request_scan); struct iwl_host_cmd cmd = { .id = REPLY_SCAN_CMD, .len = sizeof(struct iwl3945_scan_cmd), @@ -2808,8 +2805,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) conf = ieee80211_get_hw_conf(priv->hw); - mutex_lock(&priv->mutex); - cancel_delayed_work(&priv->scan_check); if (!iwl_is_ready(priv)) { @@ -2992,7 +2987,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) queue_delayed_work(priv->workqueue, &priv->scan_check, IWL_SCAN_CHECK_WATCHDOG); - mutex_unlock(&priv->mutex); return; done: @@ -3006,7 +3000,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) /* inform mac80211 scan aborted */ queue_work(priv->workqueue, &priv->scan_completed); - mutex_unlock(&priv->mutex); } static void iwl3945_bg_restart(struct work_struct *data) @@ -3785,7 +3778,6 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll); INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); - INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan); INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); -- cgit v1.2.3 From 7944f8e4acbb76bc8fde64dbffef43d2c8b5d053 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 6 Apr 2010 21:10:33 -0700 Subject: iwlwifi: more generic eeprom defines Some definition for eeprom apply to more than 5000 series device, change the name to reflect it for easy reading. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 14 ++++++------ drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 2 +- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 32 ++++++++++++++-------------- 3 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 048c6156d3be..2d00e83ec0a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -331,7 +331,7 @@ u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv) } *hdr; hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, - EEPROM_5000_CALIB_ALL); + EEPROM_CALIB_ALL); return hdr->version; } @@ -348,22 +348,22 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) switch (address & INDIRECT_TYPE_MSK) { case INDIRECT_HOST: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST); + offset = iwl_eeprom_query16(priv, EEPROM_LINK_HOST); break; case INDIRECT_GENERAL: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL); + offset = iwl_eeprom_query16(priv, EEPROM_LINK_GENERAL); break; case INDIRECT_REGULATORY: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY); + offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY); break; case INDIRECT_CALIBRATION: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION); + offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION); break; case INDIRECT_PROCESS_ADJST: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST); + offset = iwl_eeprom_query16(priv, EEPROM_LINK_PROCESS_ADJST); break; case INDIRECT_OTHERS: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS); + offset = iwl_eeprom_query16(priv, EEPROM_LINK_OTHERS); break; default: IWL_ERR(priv, "illegal indirect type: 0x%X\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 52ae157968b2..059b70e09cd1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -207,7 +207,7 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv) { struct iwl_calib_xtal_freq_cmd cmd; __le16 *xtal_calib = - (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); + (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL); cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; cmd.hdr.first_group = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index ef0e3256eec2..9977d5ef78df 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -172,22 +172,22 @@ struct iwl_eeprom_enhanced_txpwr { #define EEPROM_5000_TX_POWER_VERSION (4) #define EEPROM_5000_EEPROM_VERSION (0x11A) -/*5000 calibrations */ -#define EEPROM_5000_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION) -#define EEPROM_5000_XTAL ((2*0x128) | EEPROM_5000_CALIB_ALL) -#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_5000_CALIB_ALL) - -/* 5000 links */ -#define EEPROM_5000_LINK_HOST (2*0x64) -#define EEPROM_5000_LINK_GENERAL (2*0x65) -#define EEPROM_5000_LINK_REGULATORY (2*0x66) -#define EEPROM_5000_LINK_CALIBRATION (2*0x67) -#define EEPROM_5000_LINK_PROCESS_ADJST (2*0x68) -#define EEPROM_5000_LINK_OTHERS (2*0x69) - -/* 5000 regulatory - indirect access */ -#define EEPROM_5000_REG_SKU_ID ((0x02)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 4 bytes */ +/* 5000 and up calibration */ +#define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION) +#define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL) + +/* 5000 temperature */ +#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL) + +/* agn links */ +#define EEPROM_LINK_HOST (2*0x64) +#define EEPROM_LINK_GENERAL (2*0x65) +#define EEPROM_LINK_REGULATORY (2*0x66) +#define EEPROM_LINK_CALIBRATION (2*0x67) +#define EEPROM_LINK_PROCESS_ADJST (2*0x68) +#define EEPROM_LINK_OTHERS (2*0x69) + +/* agn regulatory - indirect access */ #define EEPROM_REG_BAND_1_CHANNELS ((0x08)\ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */ #define EEPROM_REG_BAND_2_CHANNELS ((0x26)\ -- cgit v1.2.3 From 4b3e8062807822271e02aafc0432e9a2497cb46c Mon Sep 17 00:00:00 2001 From: Shanyu Zhao Date: Wed, 7 Apr 2010 18:06:36 -0700 Subject: iwlwifi: bring up 6000 Series 2x2 AGN Gen2 adapters This patch is to bring up 6000 Series 2x2 AGN Gen2 adapters. Seperate various version numbers from 6000 Series definitions; Add module firmware declaration for the new adapters; Add additional device IDs and subsystem IDs; Signed-off-by: Shanyu Zhao Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-6000.c | 20 +++++++++++++------- drivers/net/wireless/iwlwifi/iwl-agn.c | 7 ++++++- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 4 ++++ 4 files changed, 24 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index f5d0665fd88a..63d27e3e4e35 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -51,13 +51,14 @@ /* Highest firmware API version supported */ #define IWL6000_UCODE_API_MAX 4 #define IWL6050_UCODE_API_MAX 4 +#define IWL6000G2_UCODE_API_MAX 4 /* Lowest firmware API version supported */ #define IWL6000_UCODE_API_MIN 4 #define IWL6050_UCODE_API_MIN 4 +#define IWL6000G2_UCODE_API_MIN 4 #define IWL6000_FW_PRE "iwlwifi-6000-" -#define IWL6000_G2_FW_PRE "iwlwifi-6005-" #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" #define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api) @@ -65,6 +66,10 @@ #define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" #define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api) +#define IWL6000G2_FW_PRE "iwlwifi-6005-" +#define _IWL6000G2_MODULE_FIRMWARE(api) IWL6000G2_FW_PRE #api ".ucode" +#define IWL6000G2_MODULE_FIRMWARE(api) _IWL6000G2_MODULE_FIRMWARE(api) + static void iwl6000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ @@ -363,16 +368,16 @@ static const struct iwl_ops iwl6050_ops = { /* * "i": Internal configuration, use internal Power Amplifier */ -struct iwl_cfg iwl6000i_g2_2agn_cfg = { +struct iwl_cfg iwl6000g2i_2agn_cfg = { .name = "6000 Series 2x2 AGN Gen2", - .fw_name_pre = IWL6000_G2_FW_PRE, - .ucode_api_max = IWL6000_UCODE_API_MAX, - .ucode_api_min = IWL6000_UCODE_API_MIN, + .fw_name_pre = IWL6000G2_FW_PRE, + .ucode_api_max = IWL6000G2_UCODE_API_MAX, + .ucode_api_min = IWL6000G2_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .ops = &iwl6000_ops, .eeprom_size = OTP_LOW_IMAGE_SIZE, - .eeprom_ver = EEPROM_6000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, + .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .mod_params = &iwlagn_mod_params, @@ -600,3 +605,4 @@ struct iwl_cfg iwl6000_3agn_cfg = { MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL6000G2_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 31998188e879..e788722c23ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3835,7 +3835,12 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)}, {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000i_g2_2agn_cfg)}, + +/* 6x00 Series Gen2 */ + {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2i_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2i_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2i_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2i_2agn_cfg)}, /* 6x50 WiFi/WiMax Series */ {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index dc9d8ae7e26d..ff4b47ceafd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -58,7 +58,7 @@ extern struct iwl_cfg iwl5100_abg_cfg; extern struct iwl_cfg iwl5150_agn_cfg; extern struct iwl_cfg iwl5150_abg_cfg; extern struct iwl_cfg iwl6000i_2agn_cfg; -extern struct iwl_cfg iwl6000i_g2_2agn_cfg; +extern struct iwl_cfg iwl6000g2i_2agn_cfg; extern struct iwl_cfg iwl6000i_2abg_cfg; extern struct iwl_cfg iwl6000i_2bg_cfg; extern struct iwl_cfg iwl6000_3agn_cfg; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 9977d5ef78df..95aa202c85e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -276,6 +276,10 @@ struct iwl_eeprom_enhanced_txpwr { #define EEPROM_6050_TX_POWER_VERSION (4) #define EEPROM_6050_EEPROM_VERSION (0x532) +/* 6x00g2 Specific */ +#define EEPROM_6000G2_TX_POWER_VERSION (6) +#define EEPROM_6000G2_EEPROM_VERSION (0x709) + /* OTP */ /* lower blocks contain EEPROM image and calibration data */ #define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ -- cgit v1.2.3 From 69e72801224693bb520cf3ece5e6bf67f0448c96 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 7 Apr 2010 20:12:23 -0700 Subject: iwlwifi: remove duplicated debug functions Use the show uCode statistics function for uCode debugging purposes only; it is being duplicated in both debugfs and sysfs. remove the one from sysfs. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 39 ----------------------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 39 ----------------------------- 2 files changed, 78 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e788722c23ab..8ac154680af1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3177,44 +3177,6 @@ static ssize_t store_tx_power(struct device *d, static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); -static ssize_t show_statistics(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - u32 size = sizeof(struct iwl_notif_statistics); - u32 len = 0, ofs = 0; - u8 *data = (u8 *)&priv->statistics; - int rc = 0; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - mutex_lock(&priv->mutex); - rc = iwl_send_statistics_request(priv, CMD_SYNC, false); - mutex_unlock(&priv->mutex); - - if (rc) { - len = sprintf(buf, - "Error sending statistics request: 0x%08X\n", rc); - return len; - } - - while (size && (PAGE_SIZE - len)) { - hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len, - PAGE_SIZE - len, 1); - len = strlen(buf); - if (PAGE_SIZE - len) - buf[len++] = '\n'; - - ofs += 16; - size -= min(size, 16U); - } - - return len; -} - -static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); - static ssize_t show_rts_ht_protection(struct device *d, struct device_attribute *attr, char *buf) { @@ -3404,7 +3366,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv) } static struct attribute *iwl_sysfs_entries[] = { - &dev_attr_statistics.attr, &dev_attr_temperature.attr, &dev_attr_tx_power.attr, &dev_attr_rts_ht_protection.attr, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 06004d03f20b..8da3375b603b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3657,44 +3657,6 @@ static ssize_t show_channels(struct device *d, static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); -static ssize_t show_statistics(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - u32 size = sizeof(struct iwl3945_notif_statistics); - u32 len = 0, ofs = 0; - u8 *data = (u8 *)&priv->_3945.statistics; - int rc = 0; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - mutex_lock(&priv->mutex); - rc = iwl_send_statistics_request(priv, CMD_SYNC, false); - mutex_unlock(&priv->mutex); - - if (rc) { - len = sprintf(buf, - "Error sending statistics request: 0x%08X\n", rc); - return len; - } - - while (size && (PAGE_SIZE - len)) { - hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len, - PAGE_SIZE - len, 1); - len = strlen(buf); - if (PAGE_SIZE - len) - buf[len++] = '\n'; - - ofs += 16; - size -= min(size, 16U); - } - - return len; -} - -static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); - static ssize_t show_antenna(struct device *d, struct device_attribute *attr, char *buf) { @@ -3814,7 +3776,6 @@ static struct attribute *iwl3945_sysfs_entries[] = { &dev_attr_filter_flags.attr, &dev_attr_measurement.attr, &dev_attr_retry_rate.attr, - &dev_attr_statistics.attr, &dev_attr_status.attr, &dev_attr_temperature.attr, &dev_attr_tx_power.attr, -- cgit v1.2.3 From b8c76267cfb9a025afdd122bc2a8942dbf493dd1 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Thu, 8 Apr 2010 15:29:07 -0700 Subject: iwlwifi: add debugfs ops to iwlwifi Seperate debugfs functions into iwlagn specific debugfs file and Add debugfs ops to iwlwifi. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/Makefile | 1 + drivers/net/wireless/iwlwifi/iwl-1000.c | 6 + drivers/net/wireless/iwlwifi/iwl-4965.c | 6 + drivers/net/wireless/iwlwifi/iwl-5000.c | 11 + drivers/net/wireless/iwlwifi/iwl-6000.c | 11 + drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c | 834 +++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h | 56 ++ drivers/net/wireless/iwlwifi/iwl-core.h | 10 + drivers/net/wireless/iwlwifi/iwl-debug.h | 2 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 775 ++--------------------- 10 files changed, 973 insertions(+), 739 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index a684a72eb6e9..5ed2dcbe6d01 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_IWLAGN) += iwlagn.o iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o iwlagn-objs += iwl-agn-lib.o +iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o iwlagn-$(CONFIG_IWL5000) += iwl-5000.o diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 9a0191a5ea35..8431ffce37d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -46,6 +46,7 @@ #include "iwl-helpers.h" #include "iwl-agn-hw.h" #include "iwl-agn-led.h" +#include "iwl-agn-debugfs.h" /* Highest firmware API version supported */ #define IWL1000_UCODE_API_MAX 3 @@ -212,6 +213,11 @@ static struct iwl_lib_ops iwl1000_lib = { .set_ct_kill = iwl1000_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .debugfs_ops = { + .rx_stats_read = iwl_ucode_rx_stats_read, + .tx_stats_read = iwl_ucode_tx_stats_read, + .general_stats_read = iwl_ucode_general_stats_read, + }, .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, .check_ack_health = iwl_good_ack_health, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 0a5f21e14882..85672978cab1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -47,6 +47,7 @@ #include "iwl-sta.h" #include "iwl-agn-led.h" #include "iwl-agn.h" +#include "iwl-agn-debugfs.h" static int iwl4965_send_tx_power(struct iwl_priv *priv); static int iwl4965_hw_get_temperature(struct iwl_priv *priv); @@ -2217,6 +2218,11 @@ static struct iwl_lib_ops iwl4965_lib = { .set_ct_kill = iwl4965_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .debugfs_ops = { + .rx_stats_read = iwl_ucode_rx_stats_read, + .tx_stats_read = iwl_ucode_tx_stats_read, + .general_stats_read = iwl_ucode_general_stats_read, + }, .check_plcp_health = iwl_good_plcp_health, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index e967cfcac224..e43493685271 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -48,6 +48,7 @@ #include "iwl-agn-led.h" #include "iwl-agn-hw.h" #include "iwl-5000-hw.h" +#include "iwl-agn-debugfs.h" /* Highest firmware API version supported */ #define IWL5000_UCODE_API_MAX 2 @@ -320,6 +321,11 @@ static struct iwl_lib_ops iwl5000_lib = { .set_ct_kill = iwl5000_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .debugfs_ops = { + .rx_stats_read = iwl_ucode_rx_stats_read, + .tx_stats_read = iwl_ucode_tx_stats_read, + .general_stats_read = iwl_ucode_general_stats_read, + }, .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, .check_ack_health = iwl_good_ack_health, @@ -377,6 +383,11 @@ static struct iwl_lib_ops iwl5150_lib = { .set_ct_kill = iwl5150_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .debugfs_ops = { + .rx_stats_read = iwl_ucode_rx_stats_read, + .tx_stats_read = iwl_ucode_tx_stats_read, + .general_stats_read = iwl_ucode_general_stats_read, + }, .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, .check_ack_health = iwl_good_ack_health, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 63d27e3e4e35..7b695e757a2a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -47,6 +47,7 @@ #include "iwl-agn-hw.h" #include "iwl-6000-hw.h" #include "iwl-agn-led.h" +#include "iwl-agn-debugfs.h" /* Highest firmware API version supported */ #define IWL6000_UCODE_API_MAX 4 @@ -284,6 +285,11 @@ static struct iwl_lib_ops iwl6000_lib = { .set_ct_kill = iwl6000_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .debugfs_ops = { + .rx_stats_read = iwl_ucode_rx_stats_read, + .tx_stats_read = iwl_ucode_tx_stats_read, + .general_stats_read = iwl_ucode_general_stats_read, + }, .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, .check_ack_health = iwl_good_ack_health, @@ -352,6 +358,11 @@ static struct iwl_lib_ops iwl6050_lib = { .set_calib_version = iwl6050_set_calib_version, }, .add_bcast_station = iwl_add_bcast_station, + .debugfs_ops = { + .rx_stats_read = iwl_ucode_rx_stats_read, + .tx_stats_read = iwl_ucode_tx_stats_read, + .general_stats_read = iwl_ucode_general_stats_read, + }, .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, .check_ack_health = iwl_good_ack_health, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c new file mode 100644 index 000000000000..f249b706bf17 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c @@ -0,0 +1,834 @@ +/****************************************************************************** +* +* GPL LICENSE SUMMARY +* +* Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of version 2 of the GNU General Public License as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, +* USA +* +* The full GNU General Public License is included in this distribution +* in the file called LICENSE.GPL. +* +* Contact Information: +* Intel Linux Wireless +* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +*****************************************************************************/ + +#include "iwl-agn-debugfs.h" + +ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) + { + struct iwl_priv *priv = file->private_data; + int pos = 0; + char *buf; + int bufsz = sizeof(struct statistics_rx_phy) * 40 + + sizeof(struct statistics_rx_non_phy) * 40 + + sizeof(struct statistics_rx_ht_phy) * 40 + 400; + ssize_t ret; + struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; + struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; + struct statistics_rx_non_phy *general, *accum_general; + struct statistics_rx_non_phy *delta_general, *max_general; + struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + /* + * the statistic information display here is based on + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + ofdm = &priv->statistics.rx.ofdm; + cck = &priv->statistics.rx.cck; + general = &priv->statistics.rx.general; + ht = &priv->statistics.rx.ofdm_ht; + accum_ofdm = &priv->accum_statistics.rx.ofdm; + accum_cck = &priv->accum_statistics.rx.cck; + accum_general = &priv->accum_statistics.rx.general; + accum_ht = &priv->accum_statistics.rx.ofdm_ht; + delta_ofdm = &priv->delta_statistics.rx.ofdm; + delta_cck = &priv->delta_statistics.rx.cck; + delta_general = &priv->delta_statistics.rx.general; + delta_ht = &priv->delta_statistics.rx.ofdm_ht; + max_ofdm = &priv->max_delta.rx.ofdm; + max_cck = &priv->max_delta.rx.cck; + max_general = &priv->max_delta.rx.general; + max_ht = &priv->max_delta.rx.ofdm_ht; + + pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); + pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" + "acumulative delta max\n", + "Statistics_Rx - OFDM:"); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "ina_cnt:", le32_to_cpu(ofdm->ina_cnt), + accum_ofdm->ina_cnt, + delta_ofdm->ina_cnt, max_ofdm->ina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "fina_cnt:", + le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, + delta_ofdm->fina_cnt, max_ofdm->fina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "plcp_err:", + le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, + delta_ofdm->plcp_err, max_ofdm->plcp_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "crc32_err:", + le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, + delta_ofdm->crc32_err, max_ofdm->crc32_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "overrun_err:", + le32_to_cpu(ofdm->overrun_err), + accum_ofdm->overrun_err, delta_ofdm->overrun_err, + max_ofdm->overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "early_overrun_err:", + le32_to_cpu(ofdm->early_overrun_err), + accum_ofdm->early_overrun_err, + delta_ofdm->early_overrun_err, + max_ofdm->early_overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "crc32_good:", le32_to_cpu(ofdm->crc32_good), + accum_ofdm->crc32_good, delta_ofdm->crc32_good, + max_ofdm->crc32_good); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "false_alarm_cnt:", + le32_to_cpu(ofdm->false_alarm_cnt), + accum_ofdm->false_alarm_cnt, + delta_ofdm->false_alarm_cnt, + max_ofdm->false_alarm_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "fina_sync_err_cnt:", + le32_to_cpu(ofdm->fina_sync_err_cnt), + accum_ofdm->fina_sync_err_cnt, + delta_ofdm->fina_sync_err_cnt, + max_ofdm->fina_sync_err_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "sfd_timeout:", + le32_to_cpu(ofdm->sfd_timeout), + accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout, + max_ofdm->sfd_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "fina_timeout:", + le32_to_cpu(ofdm->fina_timeout), + accum_ofdm->fina_timeout, delta_ofdm->fina_timeout, + max_ofdm->fina_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "unresponded_rts:", + le32_to_cpu(ofdm->unresponded_rts), + accum_ofdm->unresponded_rts, + delta_ofdm->unresponded_rts, + max_ofdm->unresponded_rts); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "rxe_frame_lmt_ovrun:", + le32_to_cpu(ofdm->rxe_frame_limit_overrun), + accum_ofdm->rxe_frame_limit_overrun, + delta_ofdm->rxe_frame_limit_overrun, + max_ofdm->rxe_frame_limit_overrun); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "sent_ack_cnt:", + le32_to_cpu(ofdm->sent_ack_cnt), + accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt, + max_ofdm->sent_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "sent_cts_cnt:", + le32_to_cpu(ofdm->sent_cts_cnt), + accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt, + max_ofdm->sent_cts_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "sent_ba_rsp_cnt:", + le32_to_cpu(ofdm->sent_ba_rsp_cnt), + accum_ofdm->sent_ba_rsp_cnt, + delta_ofdm->sent_ba_rsp_cnt, + max_ofdm->sent_ba_rsp_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "dsp_self_kill:", + le32_to_cpu(ofdm->dsp_self_kill), + accum_ofdm->dsp_self_kill, + delta_ofdm->dsp_self_kill, + max_ofdm->dsp_self_kill); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "mh_format_err:", + le32_to_cpu(ofdm->mh_format_err), + accum_ofdm->mh_format_err, + delta_ofdm->mh_format_err, + max_ofdm->mh_format_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "re_acq_main_rssi_sum:", + le32_to_cpu(ofdm->re_acq_main_rssi_sum), + accum_ofdm->re_acq_main_rssi_sum, + delta_ofdm->re_acq_main_rssi_sum, + max_ofdm->re_acq_main_rssi_sum); + + pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" + "acumulative delta max\n", + "Statistics_Rx - CCK:"); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "ina_cnt:", + le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, + delta_cck->ina_cnt, max_cck->ina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "fina_cnt:", + le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, + delta_cck->fina_cnt, max_cck->fina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "plcp_err:", + le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, + delta_cck->plcp_err, max_cck->plcp_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "crc32_err:", + le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, + delta_cck->crc32_err, max_cck->crc32_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "overrun_err:", + le32_to_cpu(cck->overrun_err), + accum_cck->overrun_err, delta_cck->overrun_err, + max_cck->overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "early_overrun_err:", + le32_to_cpu(cck->early_overrun_err), + accum_cck->early_overrun_err, + delta_cck->early_overrun_err, + max_cck->early_overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "crc32_good:", + le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, + delta_cck->crc32_good, max_cck->crc32_good); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "false_alarm_cnt:", + le32_to_cpu(cck->false_alarm_cnt), + accum_cck->false_alarm_cnt, + delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "fina_sync_err_cnt:", + le32_to_cpu(cck->fina_sync_err_cnt), + accum_cck->fina_sync_err_cnt, + delta_cck->fina_sync_err_cnt, + max_cck->fina_sync_err_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "sfd_timeout:", + le32_to_cpu(cck->sfd_timeout), + accum_cck->sfd_timeout, delta_cck->sfd_timeout, + max_cck->sfd_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "fina_timeout:", + le32_to_cpu(cck->fina_timeout), + accum_cck->fina_timeout, delta_cck->fina_timeout, + max_cck->fina_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "unresponded_rts:", + le32_to_cpu(cck->unresponded_rts), + accum_cck->unresponded_rts, delta_cck->unresponded_rts, + max_cck->unresponded_rts); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "rxe_frame_lmt_ovrun:", + le32_to_cpu(cck->rxe_frame_limit_overrun), + accum_cck->rxe_frame_limit_overrun, + delta_cck->rxe_frame_limit_overrun, + max_cck->rxe_frame_limit_overrun); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "sent_ack_cnt:", + le32_to_cpu(cck->sent_ack_cnt), + accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt, + max_cck->sent_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "sent_cts_cnt:", + le32_to_cpu(cck->sent_cts_cnt), + accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt, + max_cck->sent_cts_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "sent_ba_rsp_cnt:", + le32_to_cpu(cck->sent_ba_rsp_cnt), + accum_cck->sent_ba_rsp_cnt, + delta_cck->sent_ba_rsp_cnt, + max_cck->sent_ba_rsp_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "dsp_self_kill:", + le32_to_cpu(cck->dsp_self_kill), + accum_cck->dsp_self_kill, delta_cck->dsp_self_kill, + max_cck->dsp_self_kill); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "mh_format_err:", + le32_to_cpu(cck->mh_format_err), + accum_cck->mh_format_err, delta_cck->mh_format_err, + max_cck->mh_format_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "re_acq_main_rssi_sum:", + le32_to_cpu(cck->re_acq_main_rssi_sum), + accum_cck->re_acq_main_rssi_sum, + delta_cck->re_acq_main_rssi_sum, + max_cck->re_acq_main_rssi_sum); + + pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" + "acumulative delta max\n", + "Statistics_Rx - GENERAL:"); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "bogus_cts:", + le32_to_cpu(general->bogus_cts), + accum_general->bogus_cts, delta_general->bogus_cts, + max_general->bogus_cts); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "bogus_ack:", + le32_to_cpu(general->bogus_ack), + accum_general->bogus_ack, delta_general->bogus_ack, + max_general->bogus_ack); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "non_bssid_frames:", + le32_to_cpu(general->non_bssid_frames), + accum_general->non_bssid_frames, + delta_general->non_bssid_frames, + max_general->non_bssid_frames); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "filtered_frames:", + le32_to_cpu(general->filtered_frames), + accum_general->filtered_frames, + delta_general->filtered_frames, + max_general->filtered_frames); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "non_channel_beacons:", + le32_to_cpu(general->non_channel_beacons), + accum_general->non_channel_beacons, + delta_general->non_channel_beacons, + max_general->non_channel_beacons); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "channel_beacons:", + le32_to_cpu(general->channel_beacons), + accum_general->channel_beacons, + delta_general->channel_beacons, + max_general->channel_beacons); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "num_missed_bcon:", + le32_to_cpu(general->num_missed_bcon), + accum_general->num_missed_bcon, + delta_general->num_missed_bcon, + max_general->num_missed_bcon); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "adc_rx_saturation_time:", + le32_to_cpu(general->adc_rx_saturation_time), + accum_general->adc_rx_saturation_time, + delta_general->adc_rx_saturation_time, + max_general->adc_rx_saturation_time); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "ina_detect_search_tm:", + le32_to_cpu(general->ina_detection_search_time), + accum_general->ina_detection_search_time, + delta_general->ina_detection_search_time, + max_general->ina_detection_search_time); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "beacon_silence_rssi_a:", + le32_to_cpu(general->beacon_silence_rssi_a), + accum_general->beacon_silence_rssi_a, + delta_general->beacon_silence_rssi_a, + max_general->beacon_silence_rssi_a); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "beacon_silence_rssi_b:", + le32_to_cpu(general->beacon_silence_rssi_b), + accum_general->beacon_silence_rssi_b, + delta_general->beacon_silence_rssi_b, + max_general->beacon_silence_rssi_b); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "beacon_silence_rssi_c:", + le32_to_cpu(general->beacon_silence_rssi_c), + accum_general->beacon_silence_rssi_c, + delta_general->beacon_silence_rssi_c, + max_general->beacon_silence_rssi_c); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "interference_data_flag:", + le32_to_cpu(general->interference_data_flag), + accum_general->interference_data_flag, + delta_general->interference_data_flag, + max_general->interference_data_flag); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "channel_load:", + le32_to_cpu(general->channel_load), + accum_general->channel_load, + delta_general->channel_load, + max_general->channel_load); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "dsp_false_alarms:", + le32_to_cpu(general->dsp_false_alarms), + accum_general->dsp_false_alarms, + delta_general->dsp_false_alarms, + max_general->dsp_false_alarms); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "beacon_rssi_a:", + le32_to_cpu(general->beacon_rssi_a), + accum_general->beacon_rssi_a, + delta_general->beacon_rssi_a, + max_general->beacon_rssi_a); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "beacon_rssi_b:", + le32_to_cpu(general->beacon_rssi_b), + accum_general->beacon_rssi_b, + delta_general->beacon_rssi_b, + max_general->beacon_rssi_b); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "beacon_rssi_c:", + le32_to_cpu(general->beacon_rssi_c), + accum_general->beacon_rssi_c, + delta_general->beacon_rssi_c, + max_general->beacon_rssi_c); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "beacon_energy_a:", + le32_to_cpu(general->beacon_energy_a), + accum_general->beacon_energy_a, + delta_general->beacon_energy_a, + max_general->beacon_energy_a); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "beacon_energy_b:", + le32_to_cpu(general->beacon_energy_b), + accum_general->beacon_energy_b, + delta_general->beacon_energy_b, + max_general->beacon_energy_b); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "beacon_energy_c:", + le32_to_cpu(general->beacon_energy_c), + accum_general->beacon_energy_c, + delta_general->beacon_energy_c, + max_general->beacon_energy_c); + + pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); + pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" + "acumulative delta max\n", + "Statistics_Rx - OFDM_HT:"); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "plcp_err:", + le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, + delta_ht->plcp_err, max_ht->plcp_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "overrun_err:", + le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, + delta_ht->overrun_err, max_ht->overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "early_overrun_err:", + le32_to_cpu(ht->early_overrun_err), + accum_ht->early_overrun_err, + delta_ht->early_overrun_err, + max_ht->early_overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "crc32_good:", + le32_to_cpu(ht->crc32_good), accum_ht->crc32_good, + delta_ht->crc32_good, max_ht->crc32_good); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "crc32_err:", + le32_to_cpu(ht->crc32_err), accum_ht->crc32_err, + delta_ht->crc32_err, max_ht->crc32_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "mh_format_err:", + le32_to_cpu(ht->mh_format_err), + accum_ht->mh_format_err, + delta_ht->mh_format_err, max_ht->mh_format_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "agg_crc32_good:", + le32_to_cpu(ht->agg_crc32_good), + accum_ht->agg_crc32_good, + delta_ht->agg_crc32_good, max_ht->agg_crc32_good); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "agg_mpdu_cnt:", + le32_to_cpu(ht->agg_mpdu_cnt), + accum_ht->agg_mpdu_cnt, + delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "agg_cnt:", + le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt, + delta_ht->agg_cnt, max_ht->agg_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "unsupport_mcs:", + le32_to_cpu(ht->unsupport_mcs), + accum_ht->unsupport_mcs, + delta_ht->unsupport_mcs, max_ht->unsupport_mcs); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +ssize_t iwl_ucode_tx_stats_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + int pos = 0; + char *buf; + int bufsz = (sizeof(struct statistics_tx) * 48) + 250; + ssize_t ret; + struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + /* the statistic information display here is based on + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + tx = &priv->statistics.tx; + accum_tx = &priv->accum_statistics.tx; + delta_tx = &priv->delta_statistics.tx; + max_tx = &priv->max_delta.tx; + pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); + pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" + "acumulative delta max\n", + "Statistics_Tx:"); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "preamble:", + le32_to_cpu(tx->preamble_cnt), + accum_tx->preamble_cnt, + delta_tx->preamble_cnt, max_tx->preamble_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "rx_detected_cnt:", + le32_to_cpu(tx->rx_detected_cnt), + accum_tx->rx_detected_cnt, + delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "bt_prio_defer_cnt:", + le32_to_cpu(tx->bt_prio_defer_cnt), + accum_tx->bt_prio_defer_cnt, + delta_tx->bt_prio_defer_cnt, + max_tx->bt_prio_defer_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "bt_prio_kill_cnt:", + le32_to_cpu(tx->bt_prio_kill_cnt), + accum_tx->bt_prio_kill_cnt, + delta_tx->bt_prio_kill_cnt, + max_tx->bt_prio_kill_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "few_bytes_cnt:", + le32_to_cpu(tx->few_bytes_cnt), + accum_tx->few_bytes_cnt, + delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "cts_timeout:", + le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, + delta_tx->cts_timeout, max_tx->cts_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "ack_timeout:", + le32_to_cpu(tx->ack_timeout), + accum_tx->ack_timeout, + delta_tx->ack_timeout, max_tx->ack_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "expected_ack_cnt:", + le32_to_cpu(tx->expected_ack_cnt), + accum_tx->expected_ack_cnt, + delta_tx->expected_ack_cnt, + max_tx->expected_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "actual_ack_cnt:", + le32_to_cpu(tx->actual_ack_cnt), + accum_tx->actual_ack_cnt, + delta_tx->actual_ack_cnt, + max_tx->actual_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "dump_msdu_cnt:", + le32_to_cpu(tx->dump_msdu_cnt), + accum_tx->dump_msdu_cnt, + delta_tx->dump_msdu_cnt, + max_tx->dump_msdu_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "abort_nxt_frame_mismatch:", + le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), + accum_tx->burst_abort_next_frame_mismatch_cnt, + delta_tx->burst_abort_next_frame_mismatch_cnt, + max_tx->burst_abort_next_frame_mismatch_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "abort_missing_nxt_frame:", + le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), + accum_tx->burst_abort_missing_next_frame_cnt, + delta_tx->burst_abort_missing_next_frame_cnt, + max_tx->burst_abort_missing_next_frame_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "cts_timeout_collision:", + le32_to_cpu(tx->cts_timeout_collision), + accum_tx->cts_timeout_collision, + delta_tx->cts_timeout_collision, + max_tx->cts_timeout_collision); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "ack_ba_timeout_collision:", + le32_to_cpu(tx->ack_or_ba_timeout_collision), + accum_tx->ack_or_ba_timeout_collision, + delta_tx->ack_or_ba_timeout_collision, + max_tx->ack_or_ba_timeout_collision); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "agg ba_timeout:", + le32_to_cpu(tx->agg.ba_timeout), + accum_tx->agg.ba_timeout, + delta_tx->agg.ba_timeout, + max_tx->agg.ba_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "agg ba_resched_frames:", + le32_to_cpu(tx->agg.ba_reschedule_frames), + accum_tx->agg.ba_reschedule_frames, + delta_tx->agg.ba_reschedule_frames, + max_tx->agg.ba_reschedule_frames); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "agg scd_query_agg_frame:", + le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), + accum_tx->agg.scd_query_agg_frame_cnt, + delta_tx->agg.scd_query_agg_frame_cnt, + max_tx->agg.scd_query_agg_frame_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "agg scd_query_no_agg:", + le32_to_cpu(tx->agg.scd_query_no_agg), + accum_tx->agg.scd_query_no_agg, + delta_tx->agg.scd_query_no_agg, + max_tx->agg.scd_query_no_agg); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "agg scd_query_agg:", + le32_to_cpu(tx->agg.scd_query_agg), + accum_tx->agg.scd_query_agg, + delta_tx->agg.scd_query_agg, + max_tx->agg.scd_query_agg); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "agg scd_query_mismatch:", + le32_to_cpu(tx->agg.scd_query_mismatch), + accum_tx->agg.scd_query_mismatch, + delta_tx->agg.scd_query_mismatch, + max_tx->agg.scd_query_mismatch); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "agg frame_not_ready:", + le32_to_cpu(tx->agg.frame_not_ready), + accum_tx->agg.frame_not_ready, + delta_tx->agg.frame_not_ready, + max_tx->agg.frame_not_ready); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "agg underrun:", + le32_to_cpu(tx->agg.underrun), + accum_tx->agg.underrun, + delta_tx->agg.underrun, max_tx->agg.underrun); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "agg bt_prio_kill:", + le32_to_cpu(tx->agg.bt_prio_kill), + accum_tx->agg.bt_prio_kill, + delta_tx->agg.bt_prio_kill, + max_tx->agg.bt_prio_kill); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "agg rx_ba_rsp_cnt:", + le32_to_cpu(tx->agg.rx_ba_rsp_cnt), + accum_tx->agg.rx_ba_rsp_cnt, + delta_tx->agg.rx_ba_rsp_cnt, + max_tx->agg.rx_ba_rsp_cnt); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + int pos = 0; + char *buf; + int bufsz = sizeof(struct statistics_general) * 10 + 300; + ssize_t ret; + struct statistics_general *general, *accum_general; + struct statistics_general *delta_general, *max_general; + struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; + struct statistics_div *div, *accum_div, *delta_div, *max_div; + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + /* the statistic information display here is based on + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + general = &priv->statistics.general; + dbg = &priv->statistics.general.dbg; + div = &priv->statistics.general.div; + accum_general = &priv->accum_statistics.general; + delta_general = &priv->delta_statistics.general; + max_general = &priv->max_delta.general; + accum_dbg = &priv->accum_statistics.general.dbg; + delta_dbg = &priv->delta_statistics.general.dbg; + max_dbg = &priv->max_delta.general.dbg; + accum_div = &priv->accum_statistics.general.div; + delta_div = &priv->delta_statistics.general.div; + max_div = &priv->max_delta.general.div; + pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); + pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" + "acumulative delta max\n", + "Statistics_General:"); + pos += scnprintf(buf + pos, bufsz - pos, " %-30s %10u\n", + "temperature:", + le32_to_cpu(general->temperature)); + pos += scnprintf(buf + pos, bufsz - pos, " %-30s %10u\n", + "temperature_m:", + le32_to_cpu(general->temperature_m)); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "burst_check:", + le32_to_cpu(dbg->burst_check), + accum_dbg->burst_check, + delta_dbg->burst_check, max_dbg->burst_check); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "burst_count:", + le32_to_cpu(dbg->burst_count), + accum_dbg->burst_count, + delta_dbg->burst_count, max_dbg->burst_count); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "sleep_time:", + le32_to_cpu(general->sleep_time), + accum_general->sleep_time, + delta_general->sleep_time, max_general->sleep_time); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "slots_out:", + le32_to_cpu(general->slots_out), + accum_general->slots_out, + delta_general->slots_out, max_general->slots_out); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "slots_idle:", + le32_to_cpu(general->slots_idle), + accum_general->slots_idle, + delta_general->slots_idle, max_general->slots_idle); + pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", + le32_to_cpu(general->ttl_timestamp)); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "tx_on_a:", + le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, + delta_div->tx_on_a, max_div->tx_on_a); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "tx_on_b:", + le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, + delta_div->tx_on_b, max_div->tx_on_b); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "exec_time:", + le32_to_cpu(div->exec_time), accum_div->exec_time, + delta_div->exec_time, max_div->exec_time); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "probe_time:", + le32_to_cpu(div->probe_time), accum_div->probe_time, + delta_div->probe_time, max_div->probe_time); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "rx_enable_counter:", + le32_to_cpu(general->rx_enable_counter), + accum_general->rx_enable_counter, + delta_general->rx_enable_counter, + max_general->rx_enable_counter); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "num_of_sos_states:", + le32_to_cpu(general->num_of_sos_states), + accum_general->num_of_sos_states, + delta_general->num_of_sos_states, + max_general->num_of_sos_states); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h new file mode 100644 index 000000000000..59b1f25f0d85 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h @@ -0,0 +1,56 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-debug.h" + +#ifdef CONFIG_IWLWIFI_DEBUGFS +ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); +ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); +ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); +#else +static ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + return 0; +} +static ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + return 0; +} +static ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + return 0; +} +#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 1d91ffdd4203..2a3b173e4db0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -115,6 +115,15 @@ struct iwl_apm_ops { int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src); }; +struct iwl_debugfs_ops { + ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); + ssize_t (*tx_stats_read)(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); + ssize_t (*general_stats_read)(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); +}; + struct iwl_temp_ops { void (*temperature)(struct iwl_priv *priv); void (*set_ct_kill)(struct iwl_priv *priv); @@ -200,6 +209,7 @@ struct iwl_lib_ops { /* check for ack health */ bool (*check_ack_health)(struct iwl_priv *priv, struct iwl_rx_packet *pkt); + struct iwl_debugfs_ops debugfs_ops; }; struct iwl_led_ops { diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 1c7b53d511c7..5c2bcef5df0c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -78,6 +78,8 @@ static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, #ifdef CONFIG_IWLWIFI_DEBUGFS int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); void iwl_dbgfs_unregister(struct iwl_priv *priv); +extern int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, + int bufsz); #else static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) { diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 5f5820249a29..d789f8db4481 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -25,11 +25,6 @@ * Intel Linux Wireless * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *****************************************************************************/ - -#include -#include -#include - #include #include @@ -105,6 +100,26 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ .open = iwl_dbgfs_open_file_generic, \ }; +int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) +{ + int p = 0; + + p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", + le32_to_cpu(priv->statistics.flag)); + if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK) + p += scnprintf(buf + p, bufsz - p, + "\tStatistics have been cleared\n"); + p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", + (le32_to_cpu(priv->statistics.flag) & + UCODE_STATISTICS_FREQUENCY_MSK) + ? "2.4 GHz" : "5.2 GHz"); + p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", + (le32_to_cpu(priv->statistics.flag) & + UCODE_STATISTICS_NARROW_BAND_MSK) + ? "enabled" : "disabled"); + return p; +} +EXPORT_SYMBOL(iwl_dbgfs_statistics_flag); static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, char __user *user_buf, @@ -1033,474 +1048,15 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } -static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, - int bufsz) -{ - int p = 0; - - p += scnprintf(buf + p, bufsz - p, - "Statistics Flag(0x%X):\n", - le32_to_cpu(priv->statistics.flag)); - if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK) - p += scnprintf(buf + p, bufsz - p, - "\tStatistics have been cleared\n"); - p += scnprintf(buf + p, bufsz - p, - "\tOperational Frequency: %s\n", - (le32_to_cpu(priv->statistics.flag) & - UCODE_STATISTICS_FREQUENCY_MSK) - ? "2.4 GHz" : "5.2 GHz"); - p += scnprintf(buf + p, bufsz - p, - "\tTGj Narrow Band: %s\n", - (le32_to_cpu(priv->statistics.flag) & - UCODE_STATISTICS_NARROW_BAND_MSK) - ? "enabled" : "disabled"); - return p; -} - -static const char ucode_stats_header[] = - "%-32s current acumulative delta max\n"; -static const char ucode_stats_short_format[] = - " %-30s %10u\n"; -static const char ucode_stats_format[] = - " %-30s %10u %10u %10u %10u\n"; - static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; - int pos = 0; - char *buf; - int bufsz = sizeof(struct statistics_rx_phy) * 40 + - sizeof(struct statistics_rx_non_phy) * 40 + - sizeof(struct statistics_rx_ht_phy) * 40 + 400; - ssize_t ret; - struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; - struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; - struct statistics_rx_non_phy *general, *accum_general; - struct statistics_rx_non_phy *delta_general, *max_general; - struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - /* the statistic information display here is based on - * the last statistics notification from uCode - * might not reflect the current uCode activity - */ - ofdm = &priv->statistics.rx.ofdm; - cck = &priv->statistics.rx.cck; - general = &priv->statistics.rx.general; - ht = &priv->statistics.rx.ofdm_ht; - accum_ofdm = &priv->accum_statistics.rx.ofdm; - accum_cck = &priv->accum_statistics.rx.cck; - accum_general = &priv->accum_statistics.rx.general; - accum_ht = &priv->accum_statistics.rx.ofdm_ht; - delta_ofdm = &priv->delta_statistics.rx.ofdm; - delta_cck = &priv->delta_statistics.rx.cck; - delta_general = &priv->delta_statistics.rx.general; - delta_ht = &priv->delta_statistics.rx.ofdm_ht; - max_ofdm = &priv->max_delta.rx.ofdm; - max_cck = &priv->max_delta.rx.cck; - max_general = &priv->max_delta.rx.general; - max_ht = &priv->max_delta.rx.ofdm_ht; - - pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, - "Statistics_Rx - OFDM:"); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "ina_cnt:", le32_to_cpu(ofdm->ina_cnt), - accum_ofdm->ina_cnt, - delta_ofdm->ina_cnt, max_ofdm->ina_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "fina_cnt:", - le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, - delta_ofdm->fina_cnt, max_ofdm->fina_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "plcp_err:", - le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, - delta_ofdm->plcp_err, max_ofdm->plcp_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "crc32_err:", - le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, - delta_ofdm->crc32_err, max_ofdm->crc32_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "overrun_err:", - le32_to_cpu(ofdm->overrun_err), - accum_ofdm->overrun_err, - delta_ofdm->overrun_err, max_ofdm->overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "early_overrun_err:", - le32_to_cpu(ofdm->early_overrun_err), - accum_ofdm->early_overrun_err, - delta_ofdm->early_overrun_err, - max_ofdm->early_overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "crc32_good:", - le32_to_cpu(ofdm->crc32_good), - accum_ofdm->crc32_good, - delta_ofdm->crc32_good, max_ofdm->crc32_good); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "false_alarm_cnt:", - le32_to_cpu(ofdm->false_alarm_cnt), - accum_ofdm->false_alarm_cnt, - delta_ofdm->false_alarm_cnt, - max_ofdm->false_alarm_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "fina_sync_err_cnt:", - le32_to_cpu(ofdm->fina_sync_err_cnt), - accum_ofdm->fina_sync_err_cnt, - delta_ofdm->fina_sync_err_cnt, - max_ofdm->fina_sync_err_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "sfd_timeout:", - le32_to_cpu(ofdm->sfd_timeout), - accum_ofdm->sfd_timeout, - delta_ofdm->sfd_timeout, - max_ofdm->sfd_timeout); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "fina_timeout:", - le32_to_cpu(ofdm->fina_timeout), - accum_ofdm->fina_timeout, - delta_ofdm->fina_timeout, - max_ofdm->fina_timeout); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "unresponded_rts:", - le32_to_cpu(ofdm->unresponded_rts), - accum_ofdm->unresponded_rts, - delta_ofdm->unresponded_rts, - max_ofdm->unresponded_rts); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "rxe_frame_lmt_ovrun:", - le32_to_cpu(ofdm->rxe_frame_limit_overrun), - accum_ofdm->rxe_frame_limit_overrun, - delta_ofdm->rxe_frame_limit_overrun, - max_ofdm->rxe_frame_limit_overrun); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "sent_ack_cnt:", - le32_to_cpu(ofdm->sent_ack_cnt), - accum_ofdm->sent_ack_cnt, - delta_ofdm->sent_ack_cnt, - max_ofdm->sent_ack_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "sent_cts_cnt:", - le32_to_cpu(ofdm->sent_cts_cnt), - accum_ofdm->sent_cts_cnt, - delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "sent_ba_rsp_cnt:", - le32_to_cpu(ofdm->sent_ba_rsp_cnt), - accum_ofdm->sent_ba_rsp_cnt, - delta_ofdm->sent_ba_rsp_cnt, - max_ofdm->sent_ba_rsp_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "dsp_self_kill:", - le32_to_cpu(ofdm->dsp_self_kill), - accum_ofdm->dsp_self_kill, - delta_ofdm->dsp_self_kill, - max_ofdm->dsp_self_kill); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "mh_format_err:", - le32_to_cpu(ofdm->mh_format_err), - accum_ofdm->mh_format_err, - delta_ofdm->mh_format_err, - max_ofdm->mh_format_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "re_acq_main_rssi_sum:", - le32_to_cpu(ofdm->re_acq_main_rssi_sum), - accum_ofdm->re_acq_main_rssi_sum, - delta_ofdm->re_acq_main_rssi_sum, - max_ofdm->re_acq_main_rssi_sum); - - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, - "Statistics_Rx - CCK:"); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "ina_cnt:", - le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, - delta_cck->ina_cnt, max_cck->ina_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "fina_cnt:", - le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, - delta_cck->fina_cnt, max_cck->fina_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "plcp_err:", - le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, - delta_cck->plcp_err, max_cck->plcp_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "crc32_err:", - le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, - delta_cck->crc32_err, max_cck->crc32_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "overrun_err:", - le32_to_cpu(cck->overrun_err), - accum_cck->overrun_err, - delta_cck->overrun_err, max_cck->overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "early_overrun_err:", - le32_to_cpu(cck->early_overrun_err), - accum_cck->early_overrun_err, - delta_cck->early_overrun_err, - max_cck->early_overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "crc32_good:", - le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, - delta_cck->crc32_good, - max_cck->crc32_good); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "false_alarm_cnt:", - le32_to_cpu(cck->false_alarm_cnt), - accum_cck->false_alarm_cnt, - delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "fina_sync_err_cnt:", - le32_to_cpu(cck->fina_sync_err_cnt), - accum_cck->fina_sync_err_cnt, - delta_cck->fina_sync_err_cnt, - max_cck->fina_sync_err_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "sfd_timeout:", - le32_to_cpu(cck->sfd_timeout), - accum_cck->sfd_timeout, - delta_cck->sfd_timeout, max_cck->sfd_timeout); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "fina_timeout:", - le32_to_cpu(cck->fina_timeout), - accum_cck->fina_timeout, - delta_cck->fina_timeout, max_cck->fina_timeout); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "unresponded_rts:", - le32_to_cpu(cck->unresponded_rts), - accum_cck->unresponded_rts, - delta_cck->unresponded_rts, - max_cck->unresponded_rts); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "rxe_frame_lmt_ovrun:", - le32_to_cpu(cck->rxe_frame_limit_overrun), - accum_cck->rxe_frame_limit_overrun, - delta_cck->rxe_frame_limit_overrun, - max_cck->rxe_frame_limit_overrun); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "sent_ack_cnt:", - le32_to_cpu(cck->sent_ack_cnt), - accum_cck->sent_ack_cnt, - delta_cck->sent_ack_cnt, - max_cck->sent_ack_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "sent_cts_cnt:", - le32_to_cpu(cck->sent_cts_cnt), - accum_cck->sent_cts_cnt, - delta_cck->sent_cts_cnt, - max_cck->sent_cts_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "sent_ba_rsp_cnt:", - le32_to_cpu(cck->sent_ba_rsp_cnt), - accum_cck->sent_ba_rsp_cnt, - delta_cck->sent_ba_rsp_cnt, - max_cck->sent_ba_rsp_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "dsp_self_kill:", - le32_to_cpu(cck->dsp_self_kill), - accum_cck->dsp_self_kill, - delta_cck->dsp_self_kill, - max_cck->dsp_self_kill); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "mh_format_err:", - le32_to_cpu(cck->mh_format_err), - accum_cck->mh_format_err, - delta_cck->mh_format_err, max_cck->mh_format_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "re_acq_main_rssi_sum:", - le32_to_cpu(cck->re_acq_main_rssi_sum), - accum_cck->re_acq_main_rssi_sum, - delta_cck->re_acq_main_rssi_sum, - max_cck->re_acq_main_rssi_sum); - - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, - "Statistics_Rx - GENERAL:"); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "bogus_cts:", - le32_to_cpu(general->bogus_cts), - accum_general->bogus_cts, - delta_general->bogus_cts, max_general->bogus_cts); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "bogus_ack:", - le32_to_cpu(general->bogus_ack), - accum_general->bogus_ack, - delta_general->bogus_ack, max_general->bogus_ack); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "non_bssid_frames:", - le32_to_cpu(general->non_bssid_frames), - accum_general->non_bssid_frames, - delta_general->non_bssid_frames, - max_general->non_bssid_frames); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "filtered_frames:", - le32_to_cpu(general->filtered_frames), - accum_general->filtered_frames, - delta_general->filtered_frames, - max_general->filtered_frames); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "non_channel_beacons:", - le32_to_cpu(general->non_channel_beacons), - accum_general->non_channel_beacons, - delta_general->non_channel_beacons, - max_general->non_channel_beacons); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "channel_beacons:", - le32_to_cpu(general->channel_beacons), - accum_general->channel_beacons, - delta_general->channel_beacons, - max_general->channel_beacons); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "num_missed_bcon:", - le32_to_cpu(general->num_missed_bcon), - accum_general->num_missed_bcon, - delta_general->num_missed_bcon, - max_general->num_missed_bcon); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "adc_rx_saturation_time:", - le32_to_cpu(general->adc_rx_saturation_time), - accum_general->adc_rx_saturation_time, - delta_general->adc_rx_saturation_time, - max_general->adc_rx_saturation_time); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "ina_detect_search_tm:", - le32_to_cpu(general->ina_detection_search_time), - accum_general->ina_detection_search_time, - delta_general->ina_detection_search_time, - max_general->ina_detection_search_time); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "beacon_silence_rssi_a:", - le32_to_cpu(general->beacon_silence_rssi_a), - accum_general->beacon_silence_rssi_a, - delta_general->beacon_silence_rssi_a, - max_general->beacon_silence_rssi_a); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "beacon_silence_rssi_b:", - le32_to_cpu(general->beacon_silence_rssi_b), - accum_general->beacon_silence_rssi_b, - delta_general->beacon_silence_rssi_b, - max_general->beacon_silence_rssi_b); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "beacon_silence_rssi_c:", - le32_to_cpu(general->beacon_silence_rssi_c), - accum_general->beacon_silence_rssi_c, - delta_general->beacon_silence_rssi_c, - max_general->beacon_silence_rssi_c); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "interference_data_flag:", - le32_to_cpu(general->interference_data_flag), - accum_general->interference_data_flag, - delta_general->interference_data_flag, - max_general->interference_data_flag); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "channel_load:", - le32_to_cpu(general->channel_load), - accum_general->channel_load, - delta_general->channel_load, - max_general->channel_load); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "dsp_false_alarms:", - le32_to_cpu(general->dsp_false_alarms), - accum_general->dsp_false_alarms, - delta_general->dsp_false_alarms, - max_general->dsp_false_alarms); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "beacon_rssi_a:", - le32_to_cpu(general->beacon_rssi_a), - accum_general->beacon_rssi_a, - delta_general->beacon_rssi_a, - max_general->beacon_rssi_a); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "beacon_rssi_b:", - le32_to_cpu(general->beacon_rssi_b), - accum_general->beacon_rssi_b, - delta_general->beacon_rssi_b, - max_general->beacon_rssi_b); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "beacon_rssi_c:", - le32_to_cpu(general->beacon_rssi_c), - accum_general->beacon_rssi_c, - delta_general->beacon_rssi_c, - max_general->beacon_rssi_c); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "beacon_energy_a:", - le32_to_cpu(general->beacon_energy_a), - accum_general->beacon_energy_a, - delta_general->beacon_energy_a, - max_general->beacon_energy_a); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "beacon_energy_b:", - le32_to_cpu(general->beacon_energy_b), - accum_general->beacon_energy_b, - delta_general->beacon_energy_b, - max_general->beacon_energy_b); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "beacon_energy_c:", - le32_to_cpu(general->beacon_energy_c), - accum_general->beacon_energy_c, - delta_general->beacon_energy_c, - max_general->beacon_energy_c); - - pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, - "Statistics_Rx - OFDM_HT:"); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "plcp_err:", - le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, - delta_ht->plcp_err, max_ht->plcp_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "overrun_err:", - le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, - delta_ht->overrun_err, max_ht->overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "early_overrun_err:", - le32_to_cpu(ht->early_overrun_err), - accum_ht->early_overrun_err, - delta_ht->early_overrun_err, - max_ht->early_overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "crc32_good:", - le32_to_cpu(ht->crc32_good), accum_ht->crc32_good, - delta_ht->crc32_good, max_ht->crc32_good); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "crc32_err:", - le32_to_cpu(ht->crc32_err), accum_ht->crc32_err, - delta_ht->crc32_err, max_ht->crc32_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "mh_format_err:", - le32_to_cpu(ht->mh_format_err), - accum_ht->mh_format_err, - delta_ht->mh_format_err, max_ht->mh_format_err); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "agg_crc32_good:", - le32_to_cpu(ht->agg_crc32_good), - accum_ht->agg_crc32_good, - delta_ht->agg_crc32_good, max_ht->agg_crc32_good); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "agg_mpdu_cnt:", - le32_to_cpu(ht->agg_mpdu_cnt), - accum_ht->agg_mpdu_cnt, - delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "agg_cnt:", - le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt, - delta_ht->agg_cnt, max_ht->agg_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "unsupport_mcs:", - le32_to_cpu(ht->unsupport_mcs), - accum_ht->unsupport_mcs, - delta_ht->unsupport_mcs, max_ht->unsupport_mcs); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; + if (priv->cfg->ops->lib->debugfs_ops.rx_stats_read) + return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file, + user_buf, count, ppos); + return 0; } static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, @@ -1508,173 +1064,10 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; - int pos = 0; - char *buf; - int bufsz = (sizeof(struct statistics_tx) * 48) + 250; - ssize_t ret; - struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - /* the statistic information display here is based on - * the last statistics notification from uCode - * might not reflect the current uCode activity - */ - tx = &priv->statistics.tx; - accum_tx = &priv->accum_statistics.tx; - delta_tx = &priv->delta_statistics.tx; - max_tx = &priv->max_delta.tx; - pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, - "Statistics_Tx:"); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "preamble:", - le32_to_cpu(tx->preamble_cnt), - accum_tx->preamble_cnt, - delta_tx->preamble_cnt, max_tx->preamble_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "rx_detected_cnt:", - le32_to_cpu(tx->rx_detected_cnt), - accum_tx->rx_detected_cnt, - delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "bt_prio_defer_cnt:", - le32_to_cpu(tx->bt_prio_defer_cnt), - accum_tx->bt_prio_defer_cnt, - delta_tx->bt_prio_defer_cnt, - max_tx->bt_prio_defer_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "bt_prio_kill_cnt:", - le32_to_cpu(tx->bt_prio_kill_cnt), - accum_tx->bt_prio_kill_cnt, - delta_tx->bt_prio_kill_cnt, - max_tx->bt_prio_kill_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "few_bytes_cnt:", - le32_to_cpu(tx->few_bytes_cnt), - accum_tx->few_bytes_cnt, - delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "cts_timeout:", - le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, - delta_tx->cts_timeout, max_tx->cts_timeout); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "ack_timeout:", - le32_to_cpu(tx->ack_timeout), - accum_tx->ack_timeout, - delta_tx->ack_timeout, max_tx->ack_timeout); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "expected_ack_cnt:", - le32_to_cpu(tx->expected_ack_cnt), - accum_tx->expected_ack_cnt, - delta_tx->expected_ack_cnt, - max_tx->expected_ack_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "actual_ack_cnt:", - le32_to_cpu(tx->actual_ack_cnt), - accum_tx->actual_ack_cnt, - delta_tx->actual_ack_cnt, - max_tx->actual_ack_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "dump_msdu_cnt:", - le32_to_cpu(tx->dump_msdu_cnt), - accum_tx->dump_msdu_cnt, - delta_tx->dump_msdu_cnt, - max_tx->dump_msdu_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "abort_nxt_frame_mismatch:", - le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), - accum_tx->burst_abort_next_frame_mismatch_cnt, - delta_tx->burst_abort_next_frame_mismatch_cnt, - max_tx->burst_abort_next_frame_mismatch_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "abort_missing_nxt_frame:", - le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), - accum_tx->burst_abort_missing_next_frame_cnt, - delta_tx->burst_abort_missing_next_frame_cnt, - max_tx->burst_abort_missing_next_frame_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "cts_timeout_collision:", - le32_to_cpu(tx->cts_timeout_collision), - accum_tx->cts_timeout_collision, - delta_tx->cts_timeout_collision, - max_tx->cts_timeout_collision); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "ack_ba_timeout_collision:", - le32_to_cpu(tx->ack_or_ba_timeout_collision), - accum_tx->ack_or_ba_timeout_collision, - delta_tx->ack_or_ba_timeout_collision, - max_tx->ack_or_ba_timeout_collision); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "agg ba_timeout:", - le32_to_cpu(tx->agg.ba_timeout), - accum_tx->agg.ba_timeout, - delta_tx->agg.ba_timeout, - max_tx->agg.ba_timeout); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "agg ba_resched_frames:", - le32_to_cpu(tx->agg.ba_reschedule_frames), - accum_tx->agg.ba_reschedule_frames, - delta_tx->agg.ba_reschedule_frames, - max_tx->agg.ba_reschedule_frames); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "agg scd_query_agg_frame:", - le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), - accum_tx->agg.scd_query_agg_frame_cnt, - delta_tx->agg.scd_query_agg_frame_cnt, - max_tx->agg.scd_query_agg_frame_cnt); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "agg scd_query_no_agg:", - le32_to_cpu(tx->agg.scd_query_no_agg), - accum_tx->agg.scd_query_no_agg, - delta_tx->agg.scd_query_no_agg, - max_tx->agg.scd_query_no_agg); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "agg scd_query_agg:", - le32_to_cpu(tx->agg.scd_query_agg), - accum_tx->agg.scd_query_agg, - delta_tx->agg.scd_query_agg, - max_tx->agg.scd_query_agg); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "agg scd_query_mismatch:", - le32_to_cpu(tx->agg.scd_query_mismatch), - accum_tx->agg.scd_query_mismatch, - delta_tx->agg.scd_query_mismatch, - max_tx->agg.scd_query_mismatch); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "agg frame_not_ready:", - le32_to_cpu(tx->agg.frame_not_ready), - accum_tx->agg.frame_not_ready, - delta_tx->agg.frame_not_ready, - max_tx->agg.frame_not_ready); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "agg underrun:", - le32_to_cpu(tx->agg.underrun), - accum_tx->agg.underrun, - delta_tx->agg.underrun, max_tx->agg.underrun); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "agg bt_prio_kill:", - le32_to_cpu(tx->agg.bt_prio_kill), - accum_tx->agg.bt_prio_kill, - delta_tx->agg.bt_prio_kill, - max_tx->agg.bt_prio_kill); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "agg rx_ba_rsp_cnt:", - le32_to_cpu(tx->agg.rx_ba_rsp_cnt), - accum_tx->agg.rx_ba_rsp_cnt, - delta_tx->agg.rx_ba_rsp_cnt, - max_tx->agg.rx_ba_rsp_cnt); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; + if (priv->cfg->ops->lib->debugfs_ops.tx_stats_read) + return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file, + user_buf, count, ppos); + return 0; } static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, @@ -1682,107 +1075,10 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; - int pos = 0; - char *buf; - int bufsz = sizeof(struct statistics_general) * 10 + 300; - ssize_t ret; - struct statistics_general *general, *accum_general; - struct statistics_general *delta_general, *max_general; - struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; - struct statistics_div *div, *accum_div, *delta_div, *max_div; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - /* the statistic information display here is based on - * the last statistics notification from uCode - * might not reflect the current uCode activity - */ - general = &priv->statistics.general; - dbg = &priv->statistics.general.dbg; - div = &priv->statistics.general.div; - accum_general = &priv->accum_statistics.general; - delta_general = &priv->delta_statistics.general; - max_general = &priv->max_delta.general; - accum_dbg = &priv->accum_statistics.general.dbg; - delta_dbg = &priv->delta_statistics.general.dbg; - max_dbg = &priv->max_delta.general.dbg; - accum_div = &priv->accum_statistics.general.div; - delta_div = &priv->delta_statistics.general.div; - max_div = &priv->max_delta.general.div; - pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, - "Statistics_General:"); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format, - "temperature:", - le32_to_cpu(general->temperature)); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format, - "temperature_m:", - le32_to_cpu(general->temperature_m)); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "burst_check:", - le32_to_cpu(dbg->burst_check), - accum_dbg->burst_check, - delta_dbg->burst_check, max_dbg->burst_check); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "burst_count:", - le32_to_cpu(dbg->burst_count), - accum_dbg->burst_count, - delta_dbg->burst_count, max_dbg->burst_count); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "sleep_time:", - le32_to_cpu(general->sleep_time), - accum_general->sleep_time, - delta_general->sleep_time, max_general->sleep_time); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "slots_out:", - le32_to_cpu(general->slots_out), - accum_general->slots_out, - delta_general->slots_out, max_general->slots_out); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "slots_idle:", - le32_to_cpu(general->slots_idle), - accum_general->slots_idle, - delta_general->slots_idle, max_general->slots_idle); - pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", - le32_to_cpu(general->ttl_timestamp)); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "tx_on_a:", - le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, - delta_div->tx_on_a, max_div->tx_on_a); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "tx_on_b:", - le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, - delta_div->tx_on_b, max_div->tx_on_b); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "exec_time:", - le32_to_cpu(div->exec_time), accum_div->exec_time, - delta_div->exec_time, max_div->exec_time); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "probe_time:", - le32_to_cpu(div->probe_time), accum_div->probe_time, - delta_div->probe_time, max_div->probe_time); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "rx_enable_counter:", - le32_to_cpu(general->rx_enable_counter), - accum_general->rx_enable_counter, - delta_general->rx_enable_counter, - max_general->rx_enable_counter); - pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, - "num_of_sos_states:", - le32_to_cpu(general->num_of_sos_states), - accum_general->num_of_sos_states, - delta_general->num_of_sos_states, - max_general->num_of_sos_states); - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; + if (priv->cfg->ops->lib->debugfs_ops.general_stats_read) + return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file, + user_buf, count, ppos); + return 0; } static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, @@ -2340,10 +1636,11 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); + if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { - DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); - DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); - DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); -- cgit v1.2.3 From c8d5420d958e2ed0945d89d5cc20369310b0559b Mon Sep 17 00:00:00 2001 From: Shanyu Zhao Date: Thu, 8 Apr 2010 19:03:55 -0700 Subject: iwlwifi: remove redundant iwl_dump_lq_cmd() This function is called twice in a row, remove the second one. Signed-off-by: Shanyu Zhao Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-sta.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 09d9c4d56450..db934476b5e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1206,7 +1206,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, iwl_dump_lq_cmd(priv, lq); BUG_ON(init && (cmd.flags & CMD_ASYNC)); - iwl_dump_lq_cmd(priv, lq); ret = iwl_send_cmd(priv, &cmd); if (ret || (cmd.flags & CMD_ASYNC)) return ret; -- cgit v1.2.3 From 1780221141047c83c99f9d02b504700080cc35c9 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 9 Apr 2010 09:12:56 -0700 Subject: iwlwifi: add hw revision for 6000g2 NIC Add hardware revision for 6000g2 series of NIC Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-csr.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 808b7146bead..254c35ae8b38 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -298,6 +298,7 @@ #define CSR_HW_REV_TYPE_1000 (0x0000060) #define CSR_HW_REV_TYPE_6x00 (0x0000070) #define CSR_HW_REV_TYPE_6x50 (0x0000080) +#define CSR_HW_REV_TYPE_6x00g2 (0x00000B0) #define CSR_HW_REV_TYPE_NONE (0x00000F0) /* EEPROM REG */ -- cgit v1.2.3 From 33e6f816105b5cfaafbbf42682807cc317e87cb5 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 9 Apr 2010 09:36:11 -0700 Subject: iwlwifi: PA type for 6000g2 series For 6000g2 series of NICs, PA type is determined by uCode, driver do not have to set the register for internal/external PA. It is a workaround just for 6000 series NICs. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-6000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn.c | 8 ++++---- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 7b695e757a2a..7da23d3ff7b6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -379,7 +379,7 @@ static const struct iwl_ops iwl6050_ops = { /* * "i": Internal configuration, use internal Power Amplifier */ -struct iwl_cfg iwl6000g2i_2agn_cfg = { +struct iwl_cfg iwl6000g2_2agn_cfg = { .name = "6000 Series 2x2 AGN Gen2", .fw_name_pre = IWL6000G2_FW_PRE, .ucode_api_max = IWL6000G2_UCODE_API_MAX, @@ -397,7 +397,7 @@ struct iwl_cfg iwl6000g2i_2agn_cfg = { .pll_cfg_val = 0, .set_l0s = true, .use_bsm = false, - .pa_type = IWL_PA_INTERNAL, + .pa_type = IWL_PA_SYSTEM, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, .ht_greenfield_support = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8ac154680af1..1f3c5d5860a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3798,10 +3798,10 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, /* 6x00 Series Gen2 */ - {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2i_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2i_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2i_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2i_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2_2agn_cfg)}, /* 6x50 WiFi/WiMax Series */ {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index ff4b47ceafd2..bdc60aae75ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -58,7 +58,7 @@ extern struct iwl_cfg iwl5100_abg_cfg; extern struct iwl_cfg iwl5150_agn_cfg; extern struct iwl_cfg iwl5150_abg_cfg; extern struct iwl_cfg iwl6000i_2agn_cfg; -extern struct iwl_cfg iwl6000g2i_2agn_cfg; +extern struct iwl_cfg iwl6000g2_2agn_cfg; extern struct iwl_cfg iwl6000i_2abg_cfg; extern struct iwl_cfg iwl6000i_2bg_cfg; extern struct iwl_cfg iwl6000_3agn_cfg; -- cgit v1.2.3 From 82ca9341763107615a15da6e59b9535d49eb91c3 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 12 Apr 2010 14:02:36 -0700 Subject: iwlwifi: sanity check for turn on aggregation tid Perform sanity check for turn on aggregation tid. Also remove the option for turn on all the aggregation tids at once since it is deprecated function and not being used. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 34 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 5bc406c5c793..8f8d5e3e688d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -294,11 +294,11 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) return tl->total; } -static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, +static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, struct iwl_lq_sta *lq_data, u8 tid, struct ieee80211_sta *sta) { - int ret; + int ret = -EAGAIN; if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", @@ -312,29 +312,29 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, */ IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", tid); - ret = ieee80211_stop_tx_ba_session(sta, tid, + ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); } - } + } else + IWL_ERR(priv, "Fail finding valid aggregation tid: %d\n", tid); + return ret; } static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, struct iwl_lq_sta *lq_data, struct ieee80211_sta *sta) { - if ((tid < TID_MAX_LOAD_COUNT)) - rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); - else if (tid == IWL_AGG_ALL_TID) - for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) - rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); - if (priv->cfg->use_rts_for_ht) { - /* - * switch to RTS/CTS if it is the prefer protection method - * for HT traffic - */ - IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n"); - priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; - iwlcore_commit_rxon(priv); + if ((tid < TID_MAX_LOAD_COUNT) && + !rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta)) { + if (priv->cfg->use_rts_for_ht) { + /* + * switch to RTS/CTS if it is the prefer protection + * method for HT traffic + */ + IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n"); + priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; + iwlcore_commit_rxon(priv); + } } } -- cgit v1.2.3 From f4388adc92464397bb08a62c62c98b3b654bccc2 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 12 Apr 2010 18:32:11 -0700 Subject: iwlwifi: more code clean up for agn devices Since multiple new devices having similar uCode architecture and use same registers address, remove more reference to 5000 series to eliminate the confusion. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 42 +++++++-------- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 34 ++++++------ drivers/net/wireless/iwlwifi/iwl-prph.h | 80 ++++++++++++++-------------- 3 files changed, 78 insertions(+), 78 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 3077eac58880..11661fa28f21 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -167,7 +167,7 @@ static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; tbl_dw_addr = priv->scd_base_addr + - IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); + IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); @@ -186,9 +186,9 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) /* Simply stop the queue, but don't change any configuration; * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ iwl_write_prph(priv, - IWL50_SCD_QUEUE_STATUS_BITS(txq_id), - (0 << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE)| - (1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); + IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id), + (0 << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE)| + (1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); } void iwlagn_set_wr_ptrs(struct iwl_priv *priv, @@ -196,7 +196,7 @@ void iwlagn_set_wr_ptrs(struct iwl_priv *priv, { iwl_write_direct32(priv, HBUS_TARG_WRPTR, (index & 0xff) | (txq_id << 8)); - iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(txq_id), index); + iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(txq_id), index); } void iwlagn_tx_queue_set_status(struct iwl_priv *priv, @@ -206,11 +206,11 @@ void iwlagn_tx_queue_set_status(struct iwl_priv *priv, int txq_id = txq->q.id; int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; - iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id), - (active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) | - (tx_fifo_id << IWL50_SCD_QUEUE_STTS_REG_POS_TXF) | - (1 << IWL50_SCD_QUEUE_STTS_REG_POS_WSL) | - IWL50_SCD_QUEUE_STTS_REG_MSK); + iwl_write_prph(priv, IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id), + (active << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE) | + (tx_fifo_id << IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF) | + (1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL) | + IWLAGN_SCD_QUEUE_STTS_REG_MSK); txq->sched_retry = scd_retry; @@ -250,10 +250,10 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id); /* Set this queue as a chain-building queue */ - iwl_set_bits_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, (1<scd_base_addr + - IWL50_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + + IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), ((SCD_WIN_SIZE << - IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & - IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | + IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & + IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | ((SCD_FRAME_LIMIT << - IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & - IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); + IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & + IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - iwl_set_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_set_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id)); /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); @@ -298,14 +298,14 @@ int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, iwlagn_tx_queue_stop_scheduler(priv, txq_id); - iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id)); + iwl_clear_bits_prph(priv, IWLAGN_SCD_AGGR_SEL, (1 << txq_id)); priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); /* supposes that ssn_idx is valid (!= 0xFFF) */ iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); - iwl_clear_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_clear_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id)); iwl_txq_ctx_deactivate(priv, txq_id); iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); @@ -318,7 +318,7 @@ int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, */ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask) { - iwl_write_prph(priv, IWL50_SCD_TXFACT, mask); + iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask); } static inline int get_queue_from_ac(u16 ac) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 059b70e09cd1..ae476c234a7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -329,19 +329,19 @@ int iwlagn_alive_notify(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); - priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR); - a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET; - for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET; + priv->scd_base_addr = iwl_read_prph(priv, IWLAGN_SCD_SRAM_BASE_ADDR); + a = priv->scd_base_addr + IWLAGN_SCD_CONTEXT_DATA_OFFSET; + for (; a < priv->scd_base_addr + IWLAGN_SCD_TX_STTS_BITMAP_OFFSET; a += 4) iwl_write_targ_mem(priv, a, 0); - for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET; + for (; a < priv->scd_base_addr + IWLAGN_SCD_TRANSLATE_TBL_OFFSET; a += 4) iwl_write_targ_mem(priv, a, 0); for (; a < priv->scd_base_addr + - IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) + IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) iwl_write_targ_mem(priv, a, 0); - iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, + iwl_write_prph(priv, IWLAGN_SCD_DRAM_BASE_ADDR, priv->scd_bc_tbls.dma >> 10); /* Enable DMA channel */ @@ -355,28 +355,28 @@ int iwlagn_alive_notify(struct iwl_priv *priv) iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); - iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, - IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); - iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); + iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, + IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); + iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0); /* initiate the queues */ for (i = 0; i < priv->hw_params.max_txq_num; i++) { - iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(i), 0); + iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(i), 0); iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); iwl_write_targ_mem(priv, priv->scd_base_addr + - IWL50_SCD_CONTEXT_QUEUE_OFFSET(i), 0); + IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i), 0); iwl_write_targ_mem(priv, priv->scd_base_addr + - IWL50_SCD_CONTEXT_QUEUE_OFFSET(i) + + IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i) + sizeof(u32), ((SCD_WIN_SIZE << - IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & - IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | + IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & + IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | ((SCD_FRAME_LIMIT << - IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & - IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); + IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & + IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); } - iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK, + iwl_write_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, IWL_MASK(0, priv->hw_params.max_txq_num)); /* Activate all Tx DMA/FIFO channels */ diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 5944de7a98a2..b1f101caf19d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -529,48 +529,48 @@ #define IWL_SCD_TXFIFO_POS_RA (4) #define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF) -/* 5000 SCD */ -#define IWL50_SCD_QUEUE_STTS_REG_POS_TXF (0) -#define IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE (3) -#define IWL50_SCD_QUEUE_STTS_REG_POS_WSL (4) -#define IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) -#define IWL50_SCD_QUEUE_STTS_REG_MSK (0x00FF0000) - -#define IWL50_SCD_QUEUE_CTX_REG1_CREDIT_POS (8) -#define IWL50_SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00) -#define IWL50_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24) -#define IWL50_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000) -#define IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0) -#define IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F) -#define IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) -#define IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) - -#define IWL50_SCD_CONTEXT_DATA_OFFSET (0x600) -#define IWL50_SCD_TX_STTS_BITMAP_OFFSET (0x7B1) -#define IWL50_SCD_TRANSLATE_TBL_OFFSET (0x7E0) - -#define IWL50_SCD_CONTEXT_QUEUE_OFFSET(x)\ - (IWL50_SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) - -#define IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ - ((IWL50_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc) - -#define IWL50_SCD_QUEUECHAIN_SEL_ALL(x) (((1<<(x)) - 1) &\ +/* agn SCD */ +#define IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF (0) +#define IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE (3) +#define IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL (4) +#define IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) +#define IWLAGN_SCD_QUEUE_STTS_REG_MSK (0x00FF0000) + +#define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_POS (8) +#define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00) +#define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24) +#define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000) +#define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0) +#define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F) +#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) +#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) + +#define IWLAGN_SCD_CONTEXT_DATA_OFFSET (0x600) +#define IWLAGN_SCD_TX_STTS_BITMAP_OFFSET (0x7B1) +#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET (0x7E0) + +#define IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(x)\ + (IWLAGN_SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) + +#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ + ((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc) + +#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(x) (((1<<(x)) - 1) &\ (~(1< Date: Tue, 13 Apr 2010 01:04:31 -0700 Subject: iwlwifi: make BT coex config a virtual method Some future hardware will require a different command to be sent for bluetooth coexist, so make this a virtual method that can be changed on a per-device basis. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945.c | 1 + drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-core.h | 3 ++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 7 files changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 51f18950f077..d10e59def53e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2687,6 +2687,7 @@ IWL3945_UCODE_GET(boot_size); static struct iwl_hcmd_ops iwl3945_hcmd = { .rxon_assoc = iwl3945_send_rxon_assoc, .commit_rxon = iwl3945_commit_rxon, + .send_bt_config = iwl_send_bt_config, }; static struct iwl_ucode_ops iwl3945_ucode = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 85672978cab1..2861819e56e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2144,6 +2144,7 @@ static struct iwl_hcmd_ops iwl4965_hcmd = { .rxon_assoc = iwl4965_send_rxon_assoc, .commit_rxon = iwl_commit_rxon, .set_rxon_chain = iwl_set_rxon_chain, + .send_bt_config = iwl_send_bt_config, }; static struct iwl_ucode_ops iwl4965_ucode = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 231d0e67e6fc..44ef5d93befc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -262,6 +262,7 @@ struct iwl_hcmd_ops iwlagn_hcmd = { .commit_rxon = iwl_commit_rxon, .set_rxon_chain = iwl_set_rxon_chain, .set_tx_ant = iwlagn_send_tx_ant_config, + .send_bt_config = iwl_send_bt_config, }; struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1f3c5d5860a4..c22d3d8c440c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2173,7 +2173,7 @@ static void iwl_alive_start(struct iwl_priv *priv) } /* Configure Bluetooth device coexistence support */ - iwl_send_bt_config(priv); + priv->cfg->ops->hcmd->send_bt_config(priv); iwl_reset_run_time_calib(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 9d300b2d9fe3..aa86ef9fb426 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1479,7 +1479,7 @@ irqreturn_t iwl_isr_legacy(int irq, void *data) } EXPORT_SYMBOL(iwl_isr_legacy); -int iwl_send_bt_config(struct iwl_priv *priv) +void iwl_send_bt_config(struct iwl_priv *priv) { struct iwl_bt_cmd bt_cmd = { .lead_time = BT_LEAD_TIME_DEF, @@ -1496,8 +1496,9 @@ int iwl_send_bt_config(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "BT coex %s\n", (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); - return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, - sizeof(struct iwl_bt_cmd), &bt_cmd); + if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, + sizeof(struct iwl_bt_cmd), &bt_cmd)) + IWL_ERR(priv, "failed to send BT Coex Config\n"); } EXPORT_SYMBOL(iwl_send_bt_config); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 2a3b173e4db0..d9ec0307220c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -90,6 +90,7 @@ struct iwl_hcmd_ops { int (*commit_rxon)(struct iwl_priv *priv); void (*set_rxon_chain)(struct iwl_priv *priv); int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant); + void (*send_bt_config)(struct iwl_priv *priv); }; struct iwl_hcmd_utils_ops { @@ -677,7 +678,7 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv) } extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); -extern int iwl_send_bt_config(struct iwl_priv *priv); +extern void iwl_send_bt_config(struct iwl_priv *priv); extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear); extern int iwl_verify_ucode(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 8da3375b603b..64b20e78376e 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2526,7 +2526,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) } /* Configure Bluetooth device coexistence support */ - iwl_send_bt_config(priv); + priv->cfg->ops->hcmd->send_bt_config(priv); /* Configure the adapter for unassociated operation */ iwlcore_commit_rxon(priv); -- cgit v1.2.3 From b2e8690d5a4d1868ee12f50aa00c138bec985b3c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 13 Apr 2010 01:04:32 -0700 Subject: iwlwifi: rename TX_CMD_FLG_BT_DIS_MSK The flag name is a little misleading, this flag instructs the device to ignore bluetooth messages for purposes of frame transmissions, so rename the flag to TX_CMD_FLG_IGNORE_BT. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index d830086ca195..67c723cc32d2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -1443,7 +1443,7 @@ struct iwl4965_rx_mpdu_res_start { /* 1: Ignore Bluetooth priority for this frame. * 0: Delay Tx until Bluetooth device is done (normal usage). */ -#define TX_CMD_FLG_BT_DIS_MSK cpu_to_le32(1 << 12) +#define TX_CMD_FLG_IGNORE_BT cpu_to_le32(1 << 12) /* 1: uCode overrides sequence control field in MAC header. * 0: Driver provides sequence control field in MAC header. -- cgit v1.2.3 From fa58b6a3b34944bb9fc0129ba2534bd91d082d61 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 13 Apr 2010 01:04:33 -0700 Subject: iwlwifi: don't check monitor for scanning Monitor mode operation need not (and probably should not) affect scanning this way since real monitoring can not properly happen while scanning anyway. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 -- drivers/net/wireless/iwlwifi/iwl-core.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 3 --- 4 files changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 2d00e83ec0a5..ccf335775ec3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1458,8 +1458,6 @@ void iwlagn_request_scan(struct iwl_priv *priv) } scan->tx_cmd.len = cpu_to_le16(cmd_len); - if (iwl_is_monitor_mode(priv)) - scan->filter_flags = RXON_FILTER_PROMISC_MSK; scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | RXON_FILTER_BCON_AWARE_MSK); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index aa86ef9fb426..d282bef5d7ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -834,11 +834,10 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap) * never called for monitor mode. The only way mac80211 informs us about * monitor mode is through configuring filters (call to configure_filter). */ -bool iwl_is_monitor_mode(struct iwl_priv *priv) +static bool iwl_is_monitor_mode(struct iwl_priv *priv) { return !!(priv->staging_rxon.filter_flags & RXON_FILTER_PROMISC_MSK); } -EXPORT_SYMBOL(iwl_is_monitor_mode); /** * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index d9ec0307220c..e267a218e3e0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -351,7 +351,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, u64 multicast); int iwl_set_hw_params(struct iwl_priv *priv); -bool iwl_is_monitor_mode(struct iwl_priv *priv); void iwl_post_associate(struct iwl_priv *priv); void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 64b20e78376e..e7263ed693c4 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2963,9 +2963,6 @@ void iwl3945_request_scan(struct iwl_priv *priv) /* select Rx antennas */ scan->flags |= iwl3945_get_antenna_flags(priv); - if (iwl_is_monitor_mode(priv)) - scan->filter_flags = RXON_FILTER_PROMISC_MSK; - scan->channel_count = iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); -- cgit v1.2.3 From ee102603c04d84d3079e3d593d88d5254085efa0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 13 Apr 2010 01:04:34 -0700 Subject: iwlwifi: remove monitor check Off-channel reception is acceptable in monitor mode, and checking for monitor mode this way is not really correct anyway since it could be the case while operating. Now iwl_is_monitor_mode() is no longer used so remove it completely. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 25 ------------------------- 1 file changed, 25 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d282bef5d7ea..7a82b1abd8f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -827,18 +827,6 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap) return res; } -/** - * iwl_is_monitor_mode - Determine if interface in monitor mode - * - * priv->iw_mode is set in add_interface, but add_interface is - * never called for monitor mode. The only way mac80211 informs us about - * monitor mode is through configuring filters (call to configure_filter). - */ -static bool iwl_is_monitor_mode(struct iwl_priv *priv) -{ - return !!(priv->staging_rxon.filter_flags & RXON_FILTER_PROMISC_MSK); -} - /** * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image * @@ -882,19 +870,6 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS; rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; - /* copied from 'iwl_bg_request_scan()' */ - /* Force use of chains B and C (0x6) for Rx - * Avoid A (0x1) for the device has off-channel reception on A-band. - * MIMO is not used here, but value is required */ - if (iwl_is_monitor_mode(priv) && - !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) && - priv->cfg->off_channel_workaround) { - rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS; - rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS; - rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; - rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; - } - priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain); if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam) -- cgit v1.2.3 From e7cb49550eb25f2e551d7d7f3bb71560df83680c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 13 Apr 2010 01:04:35 -0700 Subject: iwlwifi: make scan antenna forcing more generic Some future hardware will also require some antenna overrides so make the current logic more generic; right now it is semantically based on a workaround for off-channel reception but the reasons for the new antenna overrides will be different. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-4965.c | 7 ++++++- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 10 +++------- drivers/net/wireless/iwlwifi/iwl-core.h | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 2861819e56e3..136c29067489 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2261,8 +2261,13 @@ struct iwl_cfg iwl4965_agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .monitor_recover_period = IWL_MONITORING_PERIOD, .temperature_kelvin = true, - .off_channel_workaround = true, .max_event_log_size = 512, + + /* + * Force use of chains B and C for scan RX on 5 GHz band + * because the device has off-channel reception on chain A. + */ + .scan_antennas[IEEE80211_BAND_5GHZ] = ANT_BC, }; /* Module firmware */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index ccf335775ec3..4bd0aecc7713 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1405,13 +1405,6 @@ void iwlagn_request_scan(struct iwl_priv *priv) * detect transmissions. */ scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; - - /* Force use of chains B and C (0x6) for scan Rx - * Avoid A (0x1) for the device has off-channel reception - * on A-band. - */ - if (priv->cfg->off_channel_workaround) - rx_ant = ANT_BC; break; default: IWL_WARN(priv, "Invalid scan band count\n"); @@ -1420,6 +1413,9 @@ void iwlagn_request_scan(struct iwl_priv *priv) band = priv->scan_band; + if (priv->cfg->scan_antennas[band]) + rx_ant = priv->cfg->scan_antennas[band]; + priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]); rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index e267a218e3e0..a0cc11ecbe93 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -318,8 +318,8 @@ struct iwl_cfg { /* timer period for monitor the driver queues */ u32 monitor_recover_period; bool temperature_kelvin; - bool off_channel_workaround; u32 max_event_log_size; + u8 scan_antennas[IEEE80211_NUM_BANDS]; }; /*************************** -- cgit v1.2.3 From c3d415030c1a00cc21935c38f8761db46ef1d7ff Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Mon, 19 Apr 2010 08:16:21 +0100 Subject: orinoco: implement set_wiphy_params ... to set fragmentation and RTS thresholds. Also report RTS retry settings during wiphy init. Note that the existing semantics for enabling microwave robustness are preserved on firmwares that have it. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/cfg.c | 88 +++++++++++++++- drivers/net/wireless/orinoco/hw.c | 26 +++++ drivers/net/wireless/orinoco/orinoco.h | 2 + drivers/net/wireless/orinoco/wext.c | 183 +-------------------------------- 4 files changed, 120 insertions(+), 179 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c index 27f2d3342645..90dd4d0595c3 100644 --- a/drivers/net/wireless/orinoco/cfg.c +++ b/drivers/net/wireless/orinoco/cfg.c @@ -88,7 +88,9 @@ int orinoco_wiphy_register(struct wiphy *wiphy) wiphy->rts_threshold = priv->rts_thresh; if (!priv->has_mwo) - wiphy->frag_threshold = priv->frag_thresh; + wiphy->frag_threshold = priv->frag_thresh + 1; + wiphy->retry_short = priv->short_retry_limit; + wiphy->retry_long = priv->long_retry_limit; return wiphy_register(wiphy); } @@ -196,8 +198,92 @@ static int orinoco_set_channel(struct wiphy *wiphy, return err; } +static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + struct orinoco_private *priv = wiphy_priv(wiphy); + int frag_value = -1; + int rts_value = -1; + int err = 0; + + if (changed & WIPHY_PARAM_RETRY_SHORT) { + /* Setting short retry not supported */ + err = -EINVAL; + } + + if (changed & WIPHY_PARAM_RETRY_LONG) { + /* Setting long retry not supported */ + err = -EINVAL; + } + + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { + /* Set fragmentation */ + if (priv->has_mwo) { + if (wiphy->frag_threshold < 0) + frag_value = 0; + else { + printk(KERN_WARNING "%s: Fixed fragmentation " + "is not supported on this firmware. " + "Using MWO robust instead.\n", + priv->ndev->name); + frag_value = 1; + } + } else { + if (wiphy->frag_threshold < 0) + frag_value = 2346; + else if ((wiphy->frag_threshold < 257) || + (wiphy->frag_threshold > 2347)) + err = -EINVAL; + else + /* cfg80211 value is 257-2347 (odd only) + * orinoco rid has range 256-2346 (even only) */ + frag_value = wiphy->frag_threshold & ~0x1; + } + } + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + /* Set RTS. + * + * Prism documentation suggests default of 2432, + * and a range of 0-3000. + * + * Current implementation uses 2347 as the default and + * the upper limit. + */ + + if (wiphy->rts_threshold < 0) + rts_value = 2347; + else if (wiphy->rts_threshold > 2347) + err = -EINVAL; + else + rts_value = wiphy->rts_threshold; + } + + if (!err) { + unsigned long flags; + + if (orinoco_lock(priv, &flags) != 0) + return -EBUSY; + + if (frag_value >= 0) { + if (priv->has_mwo) + priv->mwo_robust = frag_value; + else + priv->frag_thresh = frag_value; + } + if (rts_value >= 0) + priv->rts_thresh = rts_value; + + err = orinoco_commit(priv); + + orinoco_unlock(priv, &flags); + } + + return err; +} + const struct cfg80211_ops orinoco_cfg_ops = { .change_virtual_intf = orinoco_change_vif, .set_channel = orinoco_set_channel, .scan = orinoco_scan, + .set_wiphy_params = orinoco_set_wiphy_params, }; diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index 883b8f868626..24ea4b4d487e 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c @@ -374,6 +374,32 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr) err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPREAMBLE_SYMBOL, &priv->preamble); + if (err) { + dev_err(dev, "Failed to read preamble setup\n"); + goto out; + } + } + + /* Retry settings */ + err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT, + &priv->short_retry_limit); + if (err) { + dev_err(dev, "Failed to read short retry limit\n"); + goto out; + } + + err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT, + &priv->long_retry_limit); + if (err) { + dev_err(dev, "Failed to read long retry limit\n"); + goto out; + } + + err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME, + &priv->retry_lifetime); + if (err) { + dev_err(dev, "Failed to read max retry lifetime\n"); + goto out; } out: diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index 665ef56f8382..ff6b7b1d421d 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h @@ -131,6 +131,8 @@ struct orinoco_private { u16 ap_density, rts_thresh; u16 pm_on, pm_mcast, pm_period, pm_timeout; u16 preamble; + u16 short_retry_limit, long_retry_limit; + u16 retry_lifetime; #ifdef WIRELESS_SPY struct iw_spy_data spy_data; /* iwspy support */ struct iw_public_data wireless_data; diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index 29f9bc03190a..d261423ecf62 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c @@ -537,125 +537,6 @@ static int orinoco_ioctl_setsens(struct net_device *dev, return -EINPROGRESS; /* Call commit handler */ } -static int orinoco_ioctl_setrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int val = rrq->value; - unsigned long flags; - - if (rrq->disabled) - val = 2347; - - if ((val < 0) || (val > 2347)) - return -EINVAL; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - priv->rts_thresh = val; - orinoco_unlock(priv, &flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -static int orinoco_ioctl_getrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - - rrq->value = priv->rts_thresh; - rrq->disabled = (rrq->value == 2347); - rrq->fixed = 1; - - return 0; -} - -static int orinoco_ioctl_setfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int err = -EINPROGRESS; /* Call commit handler */ - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - if (priv->has_mwo) { - if (frq->disabled) - priv->mwo_robust = 0; - else { - if (frq->fixed) - printk(KERN_WARNING "%s: Fixed fragmentation " - "is not supported on this firmware. " - "Using MWO robust instead.\n", - dev->name); - priv->mwo_robust = 1; - } - } else { - if (frq->disabled) - priv->frag_thresh = 2346; - else { - if ((frq->value < 256) || (frq->value > 2346)) - err = -EINVAL; - else - /* must be even */ - priv->frag_thresh = frq->value & ~0x1; - } - } - - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_getfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; - int err; - u16 val; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - if (priv->has_mwo) { - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFMWOROBUST_AGERE, - &val); - if (err) - val = 0; - - frq->value = val ? 2347 : 0; - frq->disabled = !val; - frq->fixed = 0; - } else { - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFFRAGMENTATIONTHRESHOLD, - &val); - if (err) - val = 0; - - frq->value = val; - frq->disabled = (val >= 2346); - frq->fixed = 1; - } - - orinoco_unlock(priv, &flags); - - return err; -} - static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, @@ -1200,60 +1081,6 @@ static int orinoco_ioctl_set_mlme(struct net_device *dev, return ret; } -static int orinoco_ioctl_getretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; - int err = 0; - u16 short_limit, long_limit, lifetime; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT, - &short_limit); - if (err) - goto out; - - err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT, - &long_limit); - if (err) - goto out; - - err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME, - &lifetime); - if (err) - goto out; - - rrq->disabled = 0; /* Can't be disabled */ - - /* Note : by default, display the retry number */ - if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { - rrq->flags = IW_RETRY_LIFETIME; - rrq->value = lifetime * 1000; /* ??? */ - } else { - /* By default, display the min number */ - if ((rrq->flags & IW_RETRY_LONG)) { - rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; - rrq->value = long_limit; - } else { - rrq->flags = IW_RETRY_LIMIT; - rrq->value = short_limit; - if (short_limit != long_limit) - rrq->flags |= IW_RETRY_SHORT; - } - } - - out: - orinoco_unlock(priv, &flags); - - return err; -} - static int orinoco_ioctl_reset(struct net_device *dev, struct iw_request_info *info, void *wrqu, @@ -1527,11 +1354,11 @@ static const iw_handler orinoco_handler[] = { IW_HANDLER(SIOCGIWESSID, (iw_handler)orinoco_ioctl_getessid), IW_HANDLER(SIOCSIWRATE, (iw_handler)orinoco_ioctl_setrate), IW_HANDLER(SIOCGIWRATE, (iw_handler)orinoco_ioctl_getrate), - IW_HANDLER(SIOCSIWRTS, (iw_handler)orinoco_ioctl_setrts), - IW_HANDLER(SIOCGIWRTS, (iw_handler)orinoco_ioctl_getrts), - IW_HANDLER(SIOCSIWFRAG, (iw_handler)orinoco_ioctl_setfrag), - IW_HANDLER(SIOCGIWFRAG, (iw_handler)orinoco_ioctl_getfrag), - IW_HANDLER(SIOCGIWRETRY, (iw_handler)orinoco_ioctl_getretry), + IW_HANDLER(SIOCSIWRTS, (iw_handler)cfg80211_wext_siwrts), + IW_HANDLER(SIOCGIWRTS, (iw_handler)cfg80211_wext_giwrts), + IW_HANDLER(SIOCSIWFRAG, (iw_handler)cfg80211_wext_siwfrag), + IW_HANDLER(SIOCGIWFRAG, (iw_handler)cfg80211_wext_giwfrag), + IW_HANDLER(SIOCGIWRETRY, (iw_handler)cfg80211_wext_giwretry), IW_HANDLER(SIOCSIWENCODE, (iw_handler)orinoco_ioctl_setiwencode), IW_HANDLER(SIOCGIWENCODE, (iw_handler)orinoco_ioctl_getiwencode), IW_HANDLER(SIOCSIWPOWER, (iw_handler)orinoco_ioctl_setpower), -- cgit v1.2.3 From 69c264de2ada18bd9da6c9f582a8babd3dcf5f18 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Mon, 19 Apr 2010 08:16:22 +0100 Subject: orinoco: use cfg80211_find_ie Instead of using a local function. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/main.h | 12 ------------ drivers/net/wireless/orinoco/scan.c | 4 ++-- 2 files changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/orinoco/main.h b/drivers/net/wireless/orinoco/main.h index 21ab36cd76c7..4dadf9880a97 100644 --- a/drivers/net/wireless/orinoco/main.h +++ b/drivers/net/wireless/orinoco/main.h @@ -33,18 +33,6 @@ int orinoco_commit(struct orinoco_private *priv); void orinoco_reset(struct work_struct *work); /* Information element helpers - find a home for these... */ -static inline u8 *orinoco_get_ie(u8 *data, size_t len, - enum ieee80211_eid eid) -{ - u8 *p = data; - while ((p + 2) < (data + len)) { - if (p[0] == eid) - return p; - p += p[1] + 2; - } - return NULL; -} - #define WPA_OUI_TYPE "\x00\x50\xF2\x01" #define WPA_SELECTOR_LEN 4 static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len) diff --git a/drivers/net/wireless/orinoco/scan.c b/drivers/net/wireless/orinoco/scan.c index d2f10e9c2162..e97a95bacb7e 100644 --- a/drivers/net/wireless/orinoco/scan.c +++ b/drivers/net/wireless/orinoco/scan.c @@ -126,7 +126,7 @@ void orinoco_add_extscan_result(struct orinoco_private *priv, { struct wiphy *wiphy = priv_to_wiphy(priv); struct ieee80211_channel *channel; - u8 *ie; + const u8 *ie; u64 timestamp; s32 signal; u16 capability; @@ -135,7 +135,7 @@ void orinoco_add_extscan_result(struct orinoco_private *priv, int chan, freq; ie_len = len - sizeof(*bss); - ie = orinoco_get_ie(bss->data, ie_len, WLAN_EID_DS_PARAMS); + ie = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bss->data, ie_len); chan = ie ? ie[2] : 0; freq = ieee80211_dsss_chan_to_freq(chan); channel = ieee80211_get_channel(wiphy, freq); -- cgit v1.2.3 From 088899c43ce8bc54c6de519e4b1a1fc41b95867e Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Mon, 19 Apr 2010 08:16:23 +0100 Subject: orinoco: have sparse check endian issues Orinoco should be endian clean, so enable the checking. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/Makefile | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/orinoco/Makefile b/drivers/net/wireless/orinoco/Makefile index 9abd6329bcbd..e6452698eba9 100644 --- a/drivers/net/wireless/orinoco/Makefile +++ b/drivers/net/wireless/orinoco/Makefile @@ -11,3 +11,6 @@ obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o + +# Orinoco should be endian clean. +ccflags-y += -D__CHECK_ENDIAN__ -- cgit v1.2.3 From e8958330190c57c0d32bee88b64a12de2f58059f Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Mon, 19 Apr 2010 11:54:16 +0200 Subject: wireless: rt2x00: rt2800usb: identify Allwin devices Applied common sense, no info from the manufacturer: (0x8516, 0x2070) is RT2070 (0x8516, 0x2770) is RT2770 (0x8516, 0x2870) is RT2870 [...] Signed-off-by: Xose Vazquez Perez Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index cfa21ec70ccc..a71615606c37 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -806,6 +806,10 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Allwin */ + { USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Amit */ { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Askey */ @@ -912,6 +916,10 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, /* AirTies */ { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Allwin */ + { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, /* ASUS */ { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, /* AzureWave */ @@ -996,6 +1004,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, #endif #ifdef CONFIG_RT2800USB_RT35XX + /* Allwin */ + { USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Askey */ { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Cisco */ @@ -1019,14 +1029,6 @@ static struct usb_device_id rt2800usb_device_table[] = { * Unclear what kind of devices these are (they aren't supported by the * vendor driver). */ - /* Allwin */ - { USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Amigo */ { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, -- cgit v1.2.3 From 03ceedea972a82d343fa5c2528b3952fa9e615d5 Mon Sep 17 00:00:00 2001 From: Daniel Yingqiang Ma Date: Tue, 13 Apr 2010 15:12:07 +0800 Subject: ath9k: Group Key fix for VAPs When I set up multiple VAPs with ath9k, I encountered an issue that the traffic may be lost after a while. The detailed phenomenon is 1. After a while the clients connected to one of these VAPs will get into a state that no broadcast/multicast packets can be transfered successfully while the unicast packets can be transfered normally. 2. Minutes latter the unitcast packets transfer will fail as well, because the ARP entry is expired and it can't be freshed due to the broadcast trouble. It's caused by the group key overwritten and someone discussed this issue in ath9k-devel maillist before, but haven't work out a fix yet. I referred the method in madwifi, and made a patch for ath9k. The method is to set the high bit of the sender(AP)'s address, and associated that mac and the group key. It requires the hardware supports multicast frame key search. It seems true for AR9160. Not sure whether it's the correct way to fix this issue. But it seems to work in my test. The patch is attached, feel free to revise it. Signed-off-by: Daniel Yingqiang ma Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 1f4ea74bf4ca..40136cf63fa4 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -751,6 +751,7 @@ static int ath_key_config(struct ath_common *common, struct ath_hw *ah = common->ah; struct ath9k_keyval hk; const u8 *mac = NULL; + u8 gmac[ETH_ALEN]; int ret = 0; int idx; @@ -774,9 +775,30 @@ static int ath_key_config(struct ath_common *common, memcpy(hk.kv_val, key->key, key->keylen); if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { - /* For now, use the default keys for broadcast keys. This may - * need to change with virtual interfaces. */ - idx = key->keyidx; + + if (key->ap_addr) { + /* + * Group keys on hardware that supports multicast frame + * key search use a mac that is the sender's address with + * the high bit set instead of the app-specified address. + */ + memcpy(gmac, key->ap_addr, ETH_ALEN); + gmac[0] |= 0x80; + mac = gmac; + + if (key->alg == ALG_TKIP) + idx = ath_reserve_key_cache_slot_tkip(common); + else + idx = ath_reserve_key_cache_slot(common); + if (idx < 0) + mac = NULL; /* no free key cache entries */ + } + + if (!mac) { + /* For now, use the default keys for broadcast keys. This may + * need to change with virtual interfaces. */ + idx = key->keyidx; + } } else if (key->keyidx) { if (WARN_ON(!sta)) return -EOPNOTSUPP; -- cgit v1.2.3 From 1289723ef238908ca8d95ff48a46ee0de970f882 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Mon, 19 Apr 2010 10:23:57 +0200 Subject: mac80211: sample survey implementation for mac80211 & hwsim This adds the survey function to both mac80211 itself and to mac80211_hwsim. For the latter driver, we simply invent some noise level.A real driver which cannot determine the real channel noise MUST NOT report any noise, especially not a magically conjured one :-) Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index ec8b08291790..79bb8833ddb9 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -829,6 +829,33 @@ static int mac80211_hwsim_conf_tx( return 0; } +static int mac80211_hwsim_get_survey( + struct ieee80211_hw *hw, int idx, + struct survey_info *survey) +{ + struct ieee80211_conf *conf = &hw->conf; + + printk(KERN_DEBUG "%s:%s (idx=%d)\n", + wiphy_name(hw->wiphy), __func__, idx); + + if (idx != 0) + return -ENOENT; + + /* Current channel */ + survey->channel = conf->channel; + + /* + * Magically conjured noise level --- this is only ok for simulated hardware. + * + * A real driver which cannot determine the real channel noise MUST NOT + * report any noise, especially not a magically conjured one :-) + */ + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = -92; + + return 0; +} + #ifdef CONFIG_NL80211_TESTMODE /* * This section contains example code for using netlink @@ -1012,6 +1039,7 @@ static struct ieee80211_ops mac80211_hwsim_ops = .sta_notify = mac80211_hwsim_sta_notify, .set_tim = mac80211_hwsim_set_tim, .conf_tx = mac80211_hwsim_conf_tx, + .get_survey = mac80211_hwsim_get_survey, CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) .ampdu_action = mac80211_hwsim_ampdu_action, .sw_scan_start = mac80211_hwsim_sw_scan, -- cgit v1.2.3 From 55ee82b500551f80720de57a00d2990d56cf08a8 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Mon, 19 Apr 2010 10:24:22 +0200 Subject: ath5k: basic support for survey This adds the first element of survey data, the noise floor figure. Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 92327423325f..a49ede7b87b1 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -241,6 +241,8 @@ static int ath5k_set_key(struct ieee80211_hw *hw, struct ieee80211_key_conf *key); static int ath5k_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); +static int ath5k_get_survey(struct ieee80211_hw *hw, + int idx, struct survey_info *survey); static u64 ath5k_get_tsf(struct ieee80211_hw *hw); static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); static void ath5k_reset_tsf(struct ieee80211_hw *hw); @@ -266,6 +268,7 @@ static const struct ieee80211_ops ath5k_hw_ops = { .configure_filter = ath5k_configure_filter, .set_key = ath5k_set_key, .get_stats = ath5k_get_stats, + .get_survey = ath5k_get_survey, .conf_tx = NULL, .get_tsf = ath5k_get_tsf, .set_tsf = ath5k_set_tsf, @@ -3294,6 +3297,22 @@ ath5k_get_stats(struct ieee80211_hw *hw, return 0; } +static int ath5k_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) +{ + struct ath5k_softc *sc = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + + if (idx != 0) + return -ENOENT; + + survey->channel = conf->channel; + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = sc->ah->ah_noise_floor; + + return 0; +} + static u64 ath5k_get_tsf(struct ieee80211_hw *hw) { -- cgit v1.2.3 From c9c99e5e440013c420fd8ec41ee83e89909d5186 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 19 Apr 2010 19:57:29 +0200 Subject: ath9k: check for specific rx stuck conditions and recover from them Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 28 ++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 3 ++- 3 files changed, 31 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 0b85f68d516f..11e6a897c21a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1159,6 +1159,34 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, return true; } +bool ath9k_hw_check_alive(struct ath_hw *ah) +{ + int count = 50; + u32 reg; + + if (AR_SREV_9285_10_OR_LATER(ah)) + return true; + + do { + reg = REG_READ(ah, AR_OBS_BUS_1); + + if ((reg & 0x7E7FFFEF) == 0x00702400) + continue; + + switch (reg & 0x7E000B00) { + case 0x1E000000: + case 0x52000B00: + case 0x18000B00: + continue; + default: + return true; + } + } while (count-- > 0); + + return false; +} +EXPORT_SYMBOL(ath9k_hw_check_alive); + int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, bool bChannelChange) { diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 8158e8e6a53d..a78e09bab431 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -869,6 +869,7 @@ void ath9k_hw_set11nmac2040(struct ath_hw *ah); void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, const struct ath9k_beacon_state *bs); +bool ath9k_hw_check_alive(struct ath_hw *ah); bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 40136cf63fa4..aad370a7f95b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -405,7 +405,8 @@ void ath9k_tasklet(unsigned long data) ath9k_ps_wakeup(sc); - if (status & ATH9K_INT_FATAL) { + if ((status & ATH9K_INT_FATAL) || + !ath9k_hw_check_alive(ah)) { ath_reset(sc, false); ath9k_ps_restore(sc); return; -- cgit v1.2.3 From 0a8cea844d93d5fd689140ac913acc5fdcf1fdb1 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 19 Apr 2010 19:57:30 +0200 Subject: ath9k: clean up tx buffer handling Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 67 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 35 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index cac178a6bd9b..fcbb4a856a00 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -261,19 +261,40 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); } -static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) +static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) { - struct ath_buf *tbf; + struct ath_buf *bf = NULL; spin_lock_bh(&sc->tx.txbuflock); - if (WARN_ON(list_empty(&sc->tx.txbuf))) { + + if (unlikely(list_empty(&sc->tx.txbuf))) { spin_unlock_bh(&sc->tx.txbuflock); return NULL; } - tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); - list_del(&tbf->list); + + bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); + list_del(&bf->list); + spin_unlock_bh(&sc->tx.txbuflock); + return bf; +} + +static void ath_tx_return_buffer(struct ath_softc *sc, struct ath_buf *bf) +{ + spin_lock_bh(&sc->tx.txbuflock); + list_add_tail(&bf->list, &sc->tx.txbuf); + spin_unlock_bh(&sc->tx.txbuflock); +} + +static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) +{ + struct ath_buf *tbf; + + tbf = ath_tx_get_buffer(sc); + if (WARN_ON(!tbf)) + return NULL; + ATH_TXBUF_RESET(tbf); tbf->aphy = bf->aphy; @@ -1081,9 +1102,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) list_del(&bf->list); spin_unlock_bh(&txq->axq_lock); - spin_lock_bh(&sc->tx.txbuflock); - list_add_tail(&bf->list, &sc->tx.txbuf); - spin_unlock_bh(&sc->tx.txbuflock); + ath_tx_return_buffer(sc, bf); continue; } } @@ -1325,25 +1344,6 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, txq->axq_depth++; } -static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) -{ - struct ath_buf *bf = NULL; - - spin_lock_bh(&sc->tx.txbuflock); - - if (unlikely(list_empty(&sc->tx.txbuf))) { - spin_unlock_bh(&sc->tx.txbuflock); - return NULL; - } - - bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); - list_del(&bf->list); - - spin_unlock_bh(&sc->tx.txbuflock); - - return bf; -} - static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, struct list_head *bf_head, struct ath_tx_control *txctl) @@ -1825,9 +1825,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, } spin_unlock_bh(&txq->axq_lock); - spin_lock_bh(&sc->tx.txbuflock); - list_add_tail(&bf->list, &sc->tx.txbuf); - spin_unlock_bh(&sc->tx.txbuflock); + ath_tx_return_buffer(sc, bf); return r; } @@ -2141,13 +2139,12 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) txq->axq_depth--; txok = !(ts.ts_status & ATH9K_TXERR_MASK); txq->axq_tx_inprogress = false; + if (bf_held) + list_del(&bf_held->list); spin_unlock_bh(&txq->axq_lock); - if (bf_held) { - spin_lock_bh(&sc->tx.txbuflock); - list_move_tail(&bf_held->list, &sc->tx.txbuf); - spin_unlock_bh(&sc->tx.txbuflock); - } + if (bf_held) + ath_tx_return_buffer(sc, bf_held); if (!bf_isampdu(bf)) { /* -- cgit v1.2.3 From 7817e4ceb64a53c518bc45b02819e0e57a4c4d83 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 19 Apr 2010 19:57:31 +0200 Subject: ath9k: update the MCS mask for MCS16 and above Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index fcbb4a856a00..5d3d5635b92f 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -19,7 +19,7 @@ #define BITS_PER_BYTE 8 #define OFDM_PLCP_BITS 22 -#define HT_RC_2_MCS(_rc) ((_rc) & 0x0f) +#define HT_RC_2_MCS(_rc) ((_rc) & 0x1f) #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) #define L_STF 8 #define L_LTF 8 -- cgit v1.2.3 From 0e668cde0d78fb1b5f1f5e9a4bf7f9900269c98e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 19 Apr 2010 19:57:32 +0200 Subject: ath9k: update the ath_max_4ms_framelen table Include MCS0-31 and also add SGI for HT20. This makes it possible to support more different rate combinations with newer hardware. Based on a patch by Selvam. T. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 41 +++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 14 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 5d3d5635b92f..4078982fb9e9 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -71,24 +71,36 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, int nbad, int txok, bool update_rc); enum { - MCS_DEFAULT, + MCS_HT20, + MCS_HT20_SGI, MCS_HT40, MCS_HT40_SGI, }; -static int ath_max_4ms_framelen[3][16] = { - [MCS_DEFAULT] = { - 3216, 6434, 9650, 12868, 19304, 25740, 28956, 32180, - 6430, 12860, 19300, 25736, 38600, 51472, 57890, 64320, +static int ath_max_4ms_framelen[4][32] = { + [MCS_HT20] = { + 3212, 6432, 9648, 12864, 19300, 25736, 28952, 32172, + 6424, 12852, 19280, 25708, 38568, 51424, 57852, 64280, + 9628, 19260, 28896, 38528, 57792, 65532, 65532, 65532, + 12828, 25656, 38488, 51320, 65532, 65532, 65532, 65532, + }, + [MCS_HT20_SGI] = { + 3572, 7144, 10720, 14296, 21444, 28596, 32172, 35744, + 7140, 14284, 21428, 28568, 42856, 57144, 64288, 65532, + 10700, 21408, 32112, 42816, 64228, 65532, 65532, 65532, + 14256, 28516, 42780, 57040, 65532, 65532, 65532, 65532, }, [MCS_HT40] = { - 6684, 13368, 20052, 26738, 40104, 53476, 60156, 66840, - 13360, 26720, 40080, 53440, 80160, 106880, 120240, 133600, + 6680, 13360, 20044, 26724, 40092, 53456, 60140, 65532, + 13348, 26700, 40052, 53400, 65532, 65532, 65532, 65532, + 20004, 40008, 60016, 65532, 65532, 65532, 65532, 65532, + 26644, 53292, 65532, 65532, 65532, 65532, 65532, 65532, }, [MCS_HT40_SGI] = { - /* TODO: Only MCS 7 and 15 updated, recalculate the rest */ - 6684, 13368, 20052, 26738, 40104, 53476, 60156, 74200, - 13360, 26720, 40080, 53440, 80160, 106880, 120240, 148400, + 7420, 14844, 22272, 29696, 44544, 59396, 65532, 65532, + 14832, 29668, 44504, 59340, 65532, 65532, 65532, 65532, + 22232, 44464, 65532, 65532, 65532, 65532, 65532, 65532, + 29616, 59232, 65532, 65532, 65532, 65532, 65532, 65532, } }; @@ -538,12 +550,13 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, break; } - if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) - modeidx = MCS_HT40_SGI; - else if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) modeidx = MCS_HT40; else - modeidx = MCS_DEFAULT; + modeidx = MCS_HT20; + + if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) + modeidx++; frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx]; max_4ms_framelen = min(max_4ms_framelen, frmlen); -- cgit v1.2.3 From c666387682faaec7d7b4a8afd30b0b6bc0816ddb Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 19 Apr 2010 19:57:33 +0200 Subject: ath9k: reduce the bits_per_symbol table size, support more streams Instead of increasing bits_per_symbol for supporting more streams, keep it single-stream only and multiply the values by the numer of streams. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 4078982fb9e9..2237658144e6 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -34,7 +34,7 @@ #define OFDM_SIFS_TIME 16 -static u32 bits_per_symbol[][2] = { +static u16 bits_per_symbol[][2] = { /* 20MHz 40MHz */ { 26, 54 }, /* 0: BPSK */ { 52, 108 }, /* 1: QPSK 1/2 */ @@ -44,14 +44,6 @@ static u32 bits_per_symbol[][2] = { { 208, 432 }, /* 5: 64-QAM 2/3 */ { 234, 486 }, /* 6: 64-QAM 3/4 */ { 260, 540 }, /* 7: 64-QAM 5/6 */ - { 52, 108 }, /* 8: BPSK */ - { 104, 216 }, /* 9: QPSK 1/2 */ - { 156, 324 }, /* 10: QPSK 3/4 */ - { 208, 432 }, /* 11: 16-QAM 1/2 */ - { 312, 648 }, /* 12: 16-QAM 3/4 */ - { 416, 864 }, /* 13: 64-QAM 2/3 */ - { 468, 972 }, /* 14: 64-QAM 3/4 */ - { 520, 1080 }, /* 15: 64-QAM 5/6 */ }; #define IS_HT_RATE(_rate) ((_rate) & 0x80) @@ -601,7 +593,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, u32 nsymbits, nsymbols; u16 minlen; u8 flags, rix; - int width, half_gi, ndelim, mindelim; + int width, streams, half_gi, ndelim, mindelim; /* Select standard number of delimiters based on frame length alone */ ndelim = ATH_AGGR_GET_NDELIM(frmlen); @@ -641,7 +633,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, if (nsymbols == 0) nsymbols = 1; - nsymbits = bits_per_symbol[rix][width]; + streams = HT_RC_2_STREAMS(rix); + nsymbits = bits_per_symbol[rix % 8][width] * streams; minlen = (nsymbols * nsymbits) / BITS_PER_BYTE; if (frmlen < minlen) { @@ -1533,8 +1526,9 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; /* find number of symbols: PLCP + data */ + streams = HT_RC_2_STREAMS(rix); nbits = (pktlen << 3) + OFDM_PLCP_BITS; - nsymbits = bits_per_symbol[rix][width]; + nsymbits = bits_per_symbol[rix % 8][width] * streams; nsymbols = (nbits + nsymbits - 1) / nsymbits; if (!half_gi) @@ -1543,7 +1537,6 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, duration = SYMBOL_TIME_HALFGI(nsymbols); /* addup duration for legacy/ht training and signal fields */ - streams = HT_RC_2_STREAMS(rix); duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams); return duration; -- cgit v1.2.3 From 3bb065a7420c90421d6bbea5f7cffe36bd79a048 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 19 Apr 2010 19:57:34 +0200 Subject: ath9k: initialize the number of tx/rx streams correctly AR9300 based hardware can 3x3 MCS rates, this should be set in the HT capabilities. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 39 +++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 5adc2e335cff..351538cd8e4c 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -173,6 +173,18 @@ static const struct ath_ops ath9k_common_ops = { .write = ath9k_iowrite32, }; +static int count_streams(unsigned int chainmask, int max) +{ + int streams = 0; + + do { + if (++streams == max) + break; + } while ((chainmask = chainmask & (chainmask - 1))); + + return streams; +} + /**************************/ /* Initialization */ /**************************/ @@ -180,8 +192,10 @@ static const struct ath_ops ath9k_common_ops = { static void setup_ht_cap(struct ath_softc *sc, struct ieee80211_sta_ht_cap *ht_info) { - struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); u8 tx_streams, rx_streams; + int i, max_streams; ht_info->ht_supported = true; ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | @@ -195,25 +209,28 @@ static void setup_ht_cap(struct ath_softc *sc, ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; + if (AR_SREV_9300_20_OR_LATER(ah)) + max_streams = 3; + else + max_streams = 2; + /* set up supported mcs set */ memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ? - 1 : 2; - rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ? - 1 : 2; + tx_streams = count_streams(common->tx_chainmask, max_streams); + rx_streams = count_streams(common->rx_chainmask, max_streams); + + ath_print(common, ATH_DBG_CONFIG, + "TX streams %d, RX streams: %d\n", + tx_streams, rx_streams); if (tx_streams != rx_streams) { - ath_print(common, ATH_DBG_CONFIG, - "TX streams %d, RX streams: %d\n", - tx_streams, rx_streams); ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; ht_info->mcs.tx_params |= ((tx_streams - 1) << IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); } - ht_info->mcs.rx_mask[0] = 0xff; - if (rx_streams >= 2) - ht_info->mcs.rx_mask[1] = 0xff; + for (i = 0; i < rx_streams; i++) + ht_info->mcs.rx_mask[i] = 0xff; ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; } -- cgit v1.2.3 From 074a8c0db255e79960593122b5458c9a9c0551fa Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 19 Apr 2010 19:57:36 +0200 Subject: ath9k: add support for Tx and Rx STBC Supported only for single stream rates by the hardware Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 6 ++++++ drivers/net/wireless/ath/ath9k/mac.h | 8 +++++++- drivers/net/wireless/ath/ath9k/xmit.c | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 351538cd8e4c..70e5aa415c89 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -214,6 +214,12 @@ static void setup_ht_cap(struct ath_softc *sc, else max_streams = 2; + if (AR_SREV_9280_10_OR_LATER(ah)) { + if (max_streams >= 2) + ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; + ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); + } + /* set up supported mcs set */ memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); tx_streams = count_streams(common->tx_chainmask, max_streams); diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 66d0d5e56149..00f3e0c7528a 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -37,6 +37,8 @@ AR_2040_##_index : 0) \ |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \ AR_GI##_index : 0) \ + |((_series)[_index].RateFlags & ATH9K_RATESERIES_STBC ? \ + AR_STBC##_index : 0) \ |SM((_series)[_index].ChSel, AR_ChainSel##_index)) #define CCK_SIFS_TIME 10 @@ -434,7 +436,10 @@ struct ar5416_desc { #define AR_ChainSel3_S 17 #define AR_RTSCTSRate 0x0ff00000 #define AR_RTSCTSRate_S 20 -#define AR_TxCtlRsvd70 0xf0000000 +#define AR_STBC0 0x10000000 +#define AR_STBC1 0x20000000 +#define AR_STBC2 0x40000000 +#define AR_STBC3 0x80000000 #define AR_TxRSSIAnt00 0x000000ff #define AR_TxRSSIAnt00_S 0 @@ -647,6 +652,7 @@ enum ath9k_rx_filter { #define ATH9K_RATESERIES_RTS_CTS 0x0001 #define ATH9K_RATESERIES_2040 0x0002 #define ATH9K_RATESERIES_HALFGI 0x0004 +#define ATH9K_RATESERIES_STBC 0x0008 struct ath9k_11n_rate_series { u32 Tries; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 2237658144e6..b0d345a675fe 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1607,6 +1607,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) series[i].Rate = rix | 0x80; series[i].PktDuration = ath_pkt_duration(sc, rix, bf, is_40, is_sgi, is_sp); + if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) + series[i].RateFlags |= ATH9K_RATESERIES_STBC; continue; } -- cgit v1.2.3 From 58b5190e740241b33fcd901855436aa5d0c5e087 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 19 Apr 2010 19:57:37 +0200 Subject: ath9k: set the STBC flag in rate control if the peer supports it Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index f10bd06dc218..66bc1f6c8ccf 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -698,6 +698,10 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) tx_info->flags |= IEEE80211_TX_CTL_LDPC; + if (conf_is_ht(&sc->hw->conf) && + (sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC)) + tx_info->flags |= (1 << IEEE80211_TX_CTL_STBC_SHIFT); + if (is_probe) { /* set one try for probe rates. For the * probes don't enable rts */ -- cgit v1.2.3 From 020ab48d1e3538d33d7d1c1531c45708ff795ebc Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 20 Apr 2010 18:28:35 -0400 Subject: ath9k_hw: make two initvals consto for the AR9001 family This makes ar5416Addac_9160 and ar5416Addac_9160 const I guess we skipped them long ago. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9001_initvals.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h index 20abffeeb4b7..0b94bd385b0a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h @@ -1182,7 +1182,7 @@ static const u32 ar5416Bank7_9160[][2] = { { 0x000098cc, 0x0000000e }, }; -static u32 ar5416Addac_9160[][2] = { +static const u32 ar5416Addac_9160[][2] = { {0x0000989c, 0x00000000 }, {0x0000989c, 0x00000000 }, {0x0000989c, 0x00000000 }, @@ -1217,7 +1217,7 @@ static u32 ar5416Addac_9160[][2] = { {0x000098cc, 0x00000000 }, }; -static u32 ar5416Addac_91601_1[][2] = { +static const u32 ar5416Addac_91601_1[][2] = { {0x0000989c, 0x00000000 }, {0x0000989c, 0x00000000 }, {0x0000989c, 0x00000000 }, -- cgit v1.2.3 From 81b208a6b6e2923dcc2dd5292f0d2ffe20b5d16f Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 20 Apr 2010 18:28:36 -0400 Subject: ath9k_hw: make all AR9002 initvals use u32 Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_initvals.h | 68 ++++++++++++------------ 1 file changed, 34 insertions(+), 34 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h index 0f74ea764e8c..f06313d3bad6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h @@ -1468,7 +1468,7 @@ static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { }; /* AR9285 Revsion 10*/ -static const u_int32_t ar9285Modes_9285[][6] = { +static const u32 ar9285Modes_9285[][6] = { { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, @@ -1790,7 +1790,7 @@ static const u_int32_t ar9285Modes_9285[][6] = { { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, }; -static const u_int32_t ar9285Common_9285[][2] = { +static const u32 ar9285Common_9285[][2] = { { 0x0000000c, 0x00000000 }, { 0x00000030, 0x00020045 }, { 0x00000034, 0x00000005 }, @@ -2123,7 +2123,7 @@ static const u_int32_t ar9285Common_9285[][2] = { { 0x00007870, 0x10142c00 }, }; -static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285[][2] = { +static const u32 ar9285PciePhy_clkreq_always_on_L1_9285[][2] = { {0x00004040, 0x9248fd00 }, {0x00004040, 0x24924924 }, {0x00004040, 0xa8000019 }, @@ -2136,7 +2136,7 @@ static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285[][2] = { {0x00004044, 0x00000000 }, }; -static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = { +static const u32 ar9285PciePhy_clkreq_off_L1_9285[][2] = { {0x00004040, 0x9248fd00 }, {0x00004040, 0x24924924 }, {0x00004040, 0xa8000019 }, @@ -2150,7 +2150,7 @@ static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = { }; /* AR9285 v1_2 PCI Register Writes. Created: 04/13/09 */ -static const u_int32_t ar9285Modes_9285_1_2[][6] = { +static const u32 ar9285Modes_9285_1_2[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, @@ -2456,7 +2456,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, }; -static const u_int32_t ar9285Common_9285_1_2[][2] = { +static const u32 ar9285Common_9285_1_2[][2] = { { 0x0000000c, 0x00000000 }, { 0x00000030, 0x00020045 }, { 0x00000034, 0x00000005 }, @@ -2775,7 +2775,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { { 0x00007870, 0x10142c00 }, }; -static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { +static const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, @@ -2816,7 +2816,7 @@ static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, }; -static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { +static const u32 ar9285Modes_original_tx_gain_9285_1_2[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, @@ -2857,7 +2857,7 @@ static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, }; -static const u_int32_t ar9285Modes_XE2_0_normal_power[][6] = { +static const u32 ar9285Modes_XE2_0_normal_power[][6] = { { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, @@ -2897,7 +2897,7 @@ static const u_int32_t ar9285Modes_XE2_0_normal_power[][6] = { { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, }; -static const u_int32_t ar9285Modes_XE2_0_high_power[][6] = { +static const u32 ar9285Modes_XE2_0_high_power[][6] = { { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, @@ -2937,7 +2937,7 @@ static const u_int32_t ar9285Modes_XE2_0_high_power[][6] = { { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, }; -static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { +static const u32 ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { {0x00004040, 0x9248fd00 }, {0x00004040, 0x24924924 }, {0x00004040, 0xa8000019 }, @@ -2950,7 +2950,7 @@ static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { {0x00004044, 0x00000000 }, }; -static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = { +static const u32 ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = { {0x00004040, 0x9248fd00 }, {0x00004040, 0x24924924 }, {0x00004040, 0xa8000019 }, @@ -2964,7 +2964,7 @@ static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = { }; /* AR9287 Revision 10 */ -static const u_int32_t ar9287Modes_9287_1_0[][6] = { +static const u32 ar9287Modes_9287_1_0[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ { 0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0 }, @@ -3011,7 +3011,7 @@ static const u_int32_t ar9287Modes_9287_1_0[][6] = { { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, }; -static const u_int32_t ar9287Common_9287_1_0[][2] = { +static const u32 ar9287Common_9287_1_0[][2] = { { 0x0000000c, 0x00000000 }, { 0x00000030, 0x00020015 }, { 0x00000034, 0x00000005 }, @@ -3382,7 +3382,7 @@ static const u_int32_t ar9287Common_9287_1_0[][2] = { { 0x000078b8, 0x2a850160 }, }; -static const u_int32_t ar9287Modes_tx_gain_9287_1_0[][6] = { +static const u32 ar9287Modes_tx_gain_9287_1_0[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002 }, @@ -3432,7 +3432,7 @@ static const u_int32_t ar9287Modes_tx_gain_9287_1_0[][6] = { }; -static const u_int32_t ar9287Modes_rx_gain_9287_1_0[][6] = { +static const u32 ar9287Modes_rx_gain_9287_1_0[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ { 0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 }, { 0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, @@ -3694,7 +3694,7 @@ static const u_int32_t ar9287Modes_rx_gain_9287_1_0[][6] = { { 0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 }, }; -static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_0[][2] = { +static const u32 ar9287PciePhy_clkreq_always_on_L1_9287_1_0[][2] = { {0x00004040, 0x9248fd00 }, {0x00004040, 0x24924924 }, {0x00004040, 0xa8000019 }, @@ -3707,7 +3707,7 @@ static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_0[][2] = { {0x00004044, 0x00000000 }, }; -static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_0[][2] = { +static const u32 ar9287PciePhy_clkreq_off_L1_9287_1_0[][2] = { {0x00004040, 0x9248fd00 }, {0x00004040, 0x24924924 }, {0x00004040, 0xa8000019 }, @@ -3722,7 +3722,7 @@ static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_0[][2] = { /* AR9287 Revision 11 */ -static const u_int32_t ar9287Modes_9287_1_1[][6] = { +static const u32 ar9287Modes_9287_1_1[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ { 0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0 }, @@ -3769,7 +3769,7 @@ static const u_int32_t ar9287Modes_9287_1_1[][6] = { { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, }; -static const u_int32_t ar9287Common_9287_1_1[][2] = { +static const u32 ar9287Common_9287_1_1[][2] = { { 0x0000000c, 0x00000000 }, { 0x00000030, 0x00020015 }, { 0x00000034, 0x00000005 }, @@ -4142,19 +4142,19 @@ static const u_int32_t ar9287Common_9287_1_1[][2] = { * registers be programmed differently from the channel between 2412 and * 2472 MHz. */ -static const u_int32_t ar9287Common_normal_cck_fir_coeff_92871_1[][2] = { +static const u32 ar9287Common_normal_cck_fir_coeff_92871_1[][2] = { { 0x0000a1f4, 0x00fffeff }, { 0x0000a1f8, 0x00f5f9ff }, { 0x0000a1fc, 0xb79f6427 }, }; -static const u_int32_t ar9287Common_japan_2484_cck_fir_coeff_92871_1[][2] = { +static const u32 ar9287Common_japan_2484_cck_fir_coeff_92871_1[][2] = { { 0x0000a1f4, 0x00000000 }, { 0x0000a1f8, 0xefff0301 }, { 0x0000a1fc, 0xca9228ee }, }; -static const u_int32_t ar9287Modes_tx_gain_9287_1_1[][6] = { +static const u32 ar9287Modes_tx_gain_9287_1_1[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002 }, @@ -4203,7 +4203,7 @@ static const u_int32_t ar9287Modes_tx_gain_9287_1_1[][6] = { { 0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000 }, }; -static const u_int32_t ar9287Modes_rx_gain_9287_1_1[][6] = { +static const u32 ar9287Modes_rx_gain_9287_1_1[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ { 0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 }, { 0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, @@ -4465,7 +4465,7 @@ static const u_int32_t ar9287Modes_rx_gain_9287_1_1[][6] = { { 0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 }, }; -static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = { +static const u32 ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = { {0x00004040, 0x9248fd00 }, {0x00004040, 0x24924924 }, {0x00004040, 0xa8000019 }, @@ -4478,7 +4478,7 @@ static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = { {0x00004044, 0x00000000 }, }; -static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { +static const u32 ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { {0x00004040, 0x9248fd00 }, {0x00004040, 0x24924924 }, {0x00004040, 0xa8000019 }, @@ -4493,7 +4493,7 @@ static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { /* AR9271 initialization values automaticaly created: 06/04/09 */ -static const u_int32_t ar9271Modes_9271[][6] = { +static const u32 ar9271Modes_9271[][6] = { { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, @@ -4799,7 +4799,7 @@ static const u_int32_t ar9271Modes_9271[][6] = { { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, }; -static const u_int32_t ar9271Common_9271[][2] = { +static const u32 ar9271Common_9271[][2] = { { 0x0000000c, 0x00000000 }, { 0x00000030, 0x00020045 }, { 0x00000034, 0x00000005 }, @@ -5127,24 +5127,24 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x0000d384, 0xf3307ff0 }, }; -static const u_int32_t ar9271Common_normal_cck_fir_coeff_9271[][2] = { +static const u32 ar9271Common_normal_cck_fir_coeff_9271[][2] = { { 0x0000a1f4, 0x00fffeff }, { 0x0000a1f8, 0x00f5f9ff }, { 0x0000a1fc, 0xb79f6427 }, }; -static const u_int32_t ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = { +static const u32 ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = { { 0x0000a1f4, 0x00000000 }, { 0x0000a1f8, 0xefff0301 }, { 0x0000a1fc, 0xca9228ee }, }; -static const u_int32_t ar9271Modes_9271_1_0_only[][6] = { +static const u32 ar9271Modes_9271_1_0_only[][6] = { { 0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311 }, { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, }; -static const u_int32_t ar9271Modes_9271_ANI_reg[][6] = { +static const u32 ar9271Modes_9271_ANI_reg[][6] = { { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, @@ -5155,7 +5155,7 @@ static const u_int32_t ar9271Modes_9271_ANI_reg[][6] = { { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, }; -static const u_int32_t ar9271Modes_normal_power_tx_gain_9271[][6] = { +static const u32 ar9271Modes_normal_power_tx_gain_9271[][6] = { { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, @@ -5191,7 +5191,7 @@ static const u_int32_t ar9271Modes_normal_power_tx_gain_9271[][6] = { { 0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd }, }; -static const u_int32_t ar9271Modes_high_power_tx_gain_9271[][6] = { +static const u32 ar9271Modes_high_power_tx_gain_9271[][6] = { { 0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000, 0x00000000 }, { 0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200, 0x00000000 }, { 0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201, 0x00000000 }, -- cgit v1.2.3 From d4cde88c1c025ffa18150ec29e80e456f2a5c65a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 22 Apr 2010 19:52:43 +0200 Subject: p54pci: fix regression from prevent stuck rx-ring on slow system This patch fixes a recently introduced use-after-free regression from "p54pci: prevent stuck rx-ring on slow system". Hans de Goede reported a use-after-free regression: >BUG: unable to handle kernel paging request at 6b6b6b6b >IP: [] p54p_check_tx_ring+0x84/0xb1 [p54pci] >*pde = 00000000 >Oops: 0000 [#1] SMP >EIP: 0060:[] EFLAGS: 00010286 CPU: 0 >EIP is at p54p_check_tx_ring+0x84/0xb1 [p54pci] >EAX: 6b6b6b6b EBX: df10b170 ECX: 00000003 EDX: 00000001 >ESI: dc471500 EDI: d8acaeb0 EBP: c098be9c ESP: c098be84 > DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 >Process swapper (pid: 0, ti=c098a000 task=c09ccfe0 task.ti=c098a000) >Call Trace: > [] ? p54p_tasklet+0xaa/0xb5 [p54pci] > [] ? tasklet_action+0x78/0xcb > [] ? __do_softirq+0xbc/0x173 Quote from comment #17: "The problem is the innocent looking moving of the tx processing to after the rx processing in the tasklet. Quoting from the changelog: This patch does it the same way, except that it also prioritize rx data processing, simply because tx routines *can* wait. This is causing an issue with us referencing already freed memory, because some skb's we transmit, we immediately receive back, such as those for reading the eeprom (*) and getting stats. What can happen because of the moving of the tx processing to after the rx processing is that when the tasklet first runs after doing a special skb tx (such as eeprom) we've already received the answer to it. Then the rx processing ends up calling p54_find_and_unlink_skb to find the matching tx skb for the just received special rx skb and frees the tx skb. Then after the processing of the rx skb answer, and thus freeing the tx skb, we go process the completed tx ring entires, and then dereference the free-ed skb, to see if it should free free-ed by p54p_check_tx_ring()." Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=583623 Bug-Identified-by: Hans de Goede Signed-off-by: Hans de Goede Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54pci.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 0a516c8efd20..fc67888db0ca 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -276,6 +276,14 @@ static void p54p_tasklet(unsigned long dev_id) struct p54p_priv *priv = dev->priv; struct p54p_ring_control *ring_control = priv->ring_control; + p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt, + ARRAY_SIZE(ring_control->tx_mgmt), + priv->tx_buf_mgmt); + + p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data, + ARRAY_SIZE(ring_control->tx_data), + priv->tx_buf_data); + p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt, ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt); @@ -284,14 +292,6 @@ static void p54p_tasklet(unsigned long dev_id) wmb(); P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); - - p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt, - ARRAY_SIZE(ring_control->tx_mgmt), - priv->tx_buf_mgmt); - - p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data, - ARRAY_SIZE(ring_control->tx_data), - priv->tx_buf_data); } static irqreturn_t p54p_interrupt(int irq, void *dev_id) -- cgit v1.2.3 From c11d8f89d3b785f3ef987c2d9ee1bfea6f8b3d0f Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Apr 2010 10:28:09 +0530 Subject: ath9k_htc: Simplify TX URB management This patch simplifies URB management for transmission, by removing the 'FLUSH' variable (which is not needed, since we can determine if the URB has been killed by looking at the URB status), and also handling the STOP case properly. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 106 ++++++++++++++----------------- drivers/net/wireless/ath/ath9k/hif_usb.h | 1 - 2 files changed, 49 insertions(+), 58 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 3091bb3cef9b..cee5febb8a4d 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -93,14 +93,24 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev, return ret; } +static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, + struct sk_buff_head *list) +{ + struct sk_buff *skb; + + while ((skb = __skb_dequeue(list)) != NULL) { + dev_kfree_skb_any(skb); + TX_STAT_INC(skb_dropped); + } +} + static void hif_usb_tx_cb(struct urb *urb) { struct tx_buf *tx_buf = (struct tx_buf *) urb->context; struct hif_device_usb *hif_dev = tx_buf->hif_dev; struct sk_buff *skb; - bool drop, flush; - if (!hif_dev) + if (!hif_dev || !tx_buf) return; switch (urb->status) { @@ -108,57 +118,47 @@ static void hif_usb_tx_cb(struct urb *urb) break; case -ENOENT: case -ECONNRESET: - break; case -ENODEV: case -ESHUTDOWN: + /* + * The URB has been killed, free the SKBs + * and return. + */ + ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); return; default: break; } - if (tx_buf) { - spin_lock(&hif_dev->tx.tx_lock); - drop = !!(hif_dev->tx.flags & HIF_USB_TX_STOP); - flush = !!(hif_dev->tx.flags & HIF_USB_TX_FLUSH); - spin_unlock(&hif_dev->tx.tx_lock); - - while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) { - if (!drop && !flush) { - ath9k_htc_txcompletion_cb(hif_dev->htc_handle, - skb, 1); - TX_STAT_INC(skb_completed); - } else { - dev_kfree_skb_any(skb); - TX_STAT_INC(skb_dropped); - } - } - - if (flush) - return; - - tx_buf->len = tx_buf->offset = 0; - __skb_queue_head_init(&tx_buf->skb_queue); - - spin_lock(&hif_dev->tx.tx_lock); - list_del(&tx_buf->list); - list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf); - hif_dev->tx.tx_buf_cnt++; - if (!drop) - __hif_usb_tx(hif_dev); /* Check for pending SKBs */ - TX_STAT_INC(buf_completed); + /* Check if TX has been stopped */ + spin_lock(&hif_dev->tx.tx_lock); + if (hif_dev->tx.flags & HIF_USB_TX_STOP) { spin_unlock(&hif_dev->tx.tx_lock); - } -} - -static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, - struct sk_buff_head *list) -{ - struct sk_buff *skb; - - while ((skb = __skb_dequeue(list)) != NULL) { - dev_kfree_skb_any(skb); - TX_STAT_INC(skb_dropped); - } + ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); + goto add_free; + } + spin_unlock(&hif_dev->tx.tx_lock); + + /* Complete the queued SKBs. */ + while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) { + ath9k_htc_txcompletion_cb(hif_dev->htc_handle, + skb, 1); + TX_STAT_INC(skb_completed); + } + +add_free: + /* Re-initialize the SKB queue */ + tx_buf->len = tx_buf->offset = 0; + __skb_queue_head_init(&tx_buf->skb_queue); + + /* Add this TX buffer to the free list */ + spin_lock(&hif_dev->tx.tx_lock); + list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); + hif_dev->tx.tx_buf_cnt++; + if (!(hif_dev->tx.flags & HIF_USB_TX_STOP)) + __hif_usb_tx(hif_dev); /* Check for pending SKBs */ + TX_STAT_INC(buf_completed); + spin_unlock(&hif_dev->tx.tx_lock); } /* TX lock has to be taken */ @@ -178,8 +178,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) return 0; tx_buf = list_first_entry(&hif_dev->tx.tx_buf, struct tx_buf, list); - list_del(&tx_buf->list); - list_add_tail(&tx_buf->list, &hif_dev->tx.tx_pending); + list_move_tail(&tx_buf->list, &hif_dev->tx.tx_pending); hif_dev->tx.tx_buf_cnt--; tx_skb_cnt = min_t(u16, hif_dev->tx.tx_skb_cnt, MAX_TX_AGGR_NUM); @@ -548,20 +547,17 @@ free: static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) { - unsigned long flags; struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; - list_for_each_entry_safe(tx_buf, tx_buf_tmp, &hif_dev->tx.tx_buf, list) { + list_for_each_entry_safe(tx_buf, tx_buf_tmp, + &hif_dev->tx.tx_buf, list) { + usb_kill_urb(tx_buf->urb); list_del(&tx_buf->list); usb_free_urb(tx_buf->urb); kfree(tx_buf->buf); kfree(tx_buf); } - spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); - hif_dev->tx.flags |= HIF_USB_TX_FLUSH; - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); - list_for_each_entry_safe(tx_buf, tx_buf_tmp, &hif_dev->tx.tx_pending, list) { usb_kill_urb(tx_buf->urb); @@ -570,10 +566,6 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) kfree(tx_buf->buf); kfree(tx_buf); } - - spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); - hif_dev->tx.flags &= ~HIF_USB_TX_FLUSH; - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); } static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 7d49a8af420e..0aca49b6fcb6 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -61,7 +61,6 @@ struct tx_buf { }; #define HIF_USB_TX_STOP BIT(0) -#define HIF_USB_TX_FLUSH BIT(1) struct hif_usb_tx { u8 flags; -- cgit v1.2.3 From a3be14b76da111ebe4d245b0542613f9317104e7 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Apr 2010 10:28:10 +0530 Subject: ath9k_htc: Handle device unplug properly When the USB device has been unplugged, there is no point in trying to send commands to the target. Fix this by denying all WMI commands in such a case. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_init.c | 8 ++++++++ drivers/net/wireless/ath/ath9k/wmi.c | 3 +++ 3 files changed, 12 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index c765ff4a505c..b771e20075a5 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -329,6 +329,7 @@ struct htc_beacon_config { #define OP_ASSOCIATED BIT(8) #define OP_ENABLE_BEACON BIT(9) #define OP_LED_DEINIT BIT(10) +#define OP_UNPLUGGED BIT(11) struct ath9k_htc_priv { struct device *dev; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index a86189629d92..701f2ef5a440 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -744,6 +744,9 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, if (ret) goto err_init; + /* The device may have been unplugged earlier. */ + priv->op_flags &= ~OP_UNPLUGGED; + ret = ath9k_init_device(priv, devid); if (ret) goto err_init; @@ -760,6 +763,11 @@ err_free: void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug) { if (htc_handle->drv_priv) { + + /* Check if the device has been yanked out. */ + if (hotunplug) + htc_handle->drv_priv->op_flags |= OP_UNPLUGGED; + ath9k_deinit_device(htc_handle->drv_priv); ath9k_deinit_wmi(htc_handle->drv_priv); ieee80211_free_hw(htc_handle->drv_priv->hw); diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index dc6c6fc2e095..c68854532659 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -276,6 +276,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, int time_left, ret = 0; unsigned long flags; + if (wmi->drv_priv->op_flags & OP_UNPLUGGED) + return 0; + if (!wmi) return -EINVAL; -- cgit v1.2.3 From d5e347bf0f5e99f540aaaaca25ef4e957d59a506 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Apr 2010 10:28:11 +0530 Subject: ath9k_htc: Use multiple register writes This patch fixes a code segment in configpciepowersave() to make use of multiple register writes. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_hw.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index adb33b34a56d..a8a8cdc04afa 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -408,6 +408,8 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); } else { + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); @@ -428,6 +430,9 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, /* Load the new settings */ REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); } udelay(1000); -- cgit v1.2.3 From 7073daa63b8794710fa6c928a6dd169e52791185 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Apr 2010 10:28:13 +0530 Subject: ath9k_htc: Cancel running timers before disabling HW Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index ec7bcc8696ec..9c9f3e0d6787 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1178,6 +1178,13 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) return; } + /* Cancel all the running timers/work .. */ + cancel_work_sync(&priv->ps_work); + cancel_delayed_work_sync(&priv->ath9k_ani_work); + cancel_delayed_work_sync(&priv->ath9k_aggr_work); + cancel_delayed_work_sync(&priv->ath9k_led_blink_work); + ath9k_led_stop_brightness(priv); + ath9k_htc_ps_wakeup(priv); htc_stop(priv->htc); WMI_CMD(WMI_DISABLE_INTR_CMDID); @@ -1189,11 +1196,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) ath9k_htc_ps_restore(priv); ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); - cancel_work_sync(&priv->ps_work); - cancel_delayed_work_sync(&priv->ath9k_ani_work); - cancel_delayed_work_sync(&priv->ath9k_aggr_work); - cancel_delayed_work_sync(&priv->ath9k_led_blink_work); - ath9k_led_stop_brightness(priv); skb_queue_purge(&priv->tx_queue); /* Remove monitor interface here */ -- cgit v1.2.3 From 51f139d567574e6a9b5c8aaddb8ff3a240cf8e52 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Apr 2010 10:28:14 +0530 Subject: ath9k_hw: Remove pointless ANI deinit There is no reason to disable the PHY Error / MIB counters when the module is being unloaded. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 9 --------- drivers/net/wireless/ath/ath9k/ani.h | 1 - drivers/net/wireless/ath/ath9k/hw.c | 3 --- 3 files changed, 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index cec62d311c78..ba8b20f01594 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -657,12 +657,3 @@ void ath9k_hw_ani_init(struct ath_hw *ah) if (ah->config.enable_ani) ah->proc_phyerr |= HAL_PROCESS_ANI; } - -void ath9k_hw_ani_disable(struct ath_hw *ah) -{ - ath_print(ath9k_hw_common(ah), ATH_DBG_ANI, "Disabling ANI\n"); - - ath9k_hw_disable_mib_counters(ah); - REG_WRITE(ah, AR_PHY_ERR_1, 0); - REG_WRITE(ah, AR_PHY_ERR_2, 0); -} diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 4e1ab94a5153..3356762ea384 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -118,6 +118,5 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, void ath9k_hw_procmibevent(struct ath_hw *ah); void ath9k_hw_ani_setup(struct ath_hw *ah); void ath9k_hw_ani_init(struct ath_hw *ah); -void ath9k_hw_ani_disable(struct ath_hw *ah); #endif /* ANI_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 11e6a897c21a..b6d12e52d30e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -818,9 +818,6 @@ void ath9k_hw_deinit(struct ath_hw *ah) if (common->state < ATH_HW_INITIALIZED) goto free_hw; - if (!AR_SREV_9100(ah)) - ath9k_hw_ani_disable(ah); - ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); free_hw: -- cgit v1.2.3 From f66890724fb3131894b8eee5fc552a5dc42dc1df Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Apr 2010 10:28:15 +0530 Subject: ath9k_htc: Pass correct private pointer In the TX callback, the HTC layer has to pass the priv pointer that was registered during service initialization. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_hst.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index f2dca258bdc2..7bf6ce1e7e2e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -341,8 +341,9 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, skb_pull(skb, sizeof(struct htc_frame_hdr)); if (endpoint->ep_callbacks.tx) { - endpoint->ep_callbacks.tx(htc_handle->drv_priv, skb, - htc_hdr->endpoint_id, txok); + endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv, + skb, htc_hdr->endpoint_id, + txok); } } -- cgit v1.2.3 From 62e4716aff31a8ab687016680443012034734c92 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Apr 2010 10:28:16 +0530 Subject: ath9k_htc: Use USB reboot So, apparently there is a USB reboot command that the target accepts. Using this instead of usb_reset_device() fixes the issue of "descriptor read error" that pops up on repeated load/unload. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index cee5febb8a4d..31665c5ad907 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -889,6 +889,26 @@ err_alloc: return ret; } +static void ath9k_hif_usb_reboot(struct usb_device *udev) +{ + u32 reboot_cmd = 0xffffffff; + void *buf; + int ret; + + buf = kmalloc(4, GFP_KERNEL); + if (!buf) + return; + + memcpy(buf, &reboot_cmd, 4); + + ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, USB_REG_OUT_PIPE), + buf, 4, NULL, HZ); + if (ret) + dev_err(&udev->dev, "ath9k_htc: USB reboot failed\n"); + + kfree(buf); +} + static void ath9k_hif_usb_disconnect(struct usb_interface *interface) { struct usb_device *udev = interface_to_usbdev(interface); @@ -903,7 +923,7 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface) } if (hif_dev->flags & HIF_USB_START) - usb_reset_device(udev); + ath9k_hif_usb_reboot(udev); kfree(hif_dev); dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n"); -- cgit v1.2.3 From 5ab0af3270b29c62b8960a60092917ec8be48c4a Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Apr 2010 10:28:17 +0530 Subject: ath9k_htc: Process command data properly When handling the REGIN callback, processing the incoming data first should be the preferred mode of operation. Allocation of a new SKB may fail, in which case, the URB will not be resubmitted. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 31665c5ad907..49b7a8970ddd 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -510,9 +510,18 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) if (likely(urb->actual_length != 0)) { skb_put(skb, urb->actual_length); + /* Process the command first */ + ath9k_htc_rx_msg(hif_dev->htc_handle, skb, + skb->len, USB_REG_IN_PIPE); + + nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); - if (!nskb) - goto resubmit; + if (!nskb) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: REG_IN memory allocation failure\n"); + urb->context = NULL; + return; + } usb_fill_int_urb(urb, hif_dev->udev, usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), @@ -522,12 +531,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret) { kfree_skb(nskb); - goto free; + urb->context = NULL; } - ath9k_htc_rx_msg(hif_dev->htc_handle, skb, - skb->len, USB_REG_IN_PIPE); - return; } -- cgit v1.2.3 From ba44370175d2e743065382508ed7823cc83cea0a Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Apr 2010 10:28:18 +0530 Subject: ath9k_htc: Increase WMI timeout value Completion of WMI commands take a longer time on some platforms. Increase the timeout value to handle this. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/wmi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 167e15c50062..765db5faa2d3 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -126,14 +126,14 @@ void ath9k_wmi_tasklet(unsigned long data); do { \ ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, NULL, 0, \ (u8 *) &cmd_rsp, \ - sizeof(cmd_rsp), HZ); \ + sizeof(cmd_rsp), HZ*2); \ } while (0) #define WMI_CMD_BUF(_wmi_cmd, _buf) \ do { \ ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, \ (u8 *) _buf, sizeof(*_buf), \ - &cmd_rsp, sizeof(cmd_rsp), HZ); \ + &cmd_rsp, sizeof(cmd_rsp), HZ*2); \ } while (0) #endif /* WMI_H */ -- cgit v1.2.3 From 0d36d71da2a3e5b28b4e7743c0041515cca798ef Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Apr 2010 10:28:19 +0530 Subject: ath9k_htc: Fix WMI command race My patch "ath9k_htc: Handle WMI timeouts properly" introduced a race condition in WMI command processing. The last issued command should be stored _before_ issuing a WMI command. Not doing this would result in the WMI event IRQ dropping correct command responses as invalid. Fix this race by storing the command id correctly. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/wmi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index c68854532659..e23172c9caaf 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -305,14 +305,14 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, wmi->cmd_rsp_buf = rsp_buf; wmi->cmd_rsp_len = rsp_len; - ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len); - if (ret) - goto out; - spin_lock_irqsave(&wmi->wmi_lock, flags); wmi->last_cmd_id = cmd_id; spin_unlock_irqrestore(&wmi->wmi_lock, flags); + ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len); + if (ret) + goto out; + time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout); if (!time_left) { ath_print(common, ATH_DBG_WMI, -- cgit v1.2.3 From d8f996f6ff7e6eab4c7b96e908ba789533595e7d Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Apr 2010 10:28:20 +0530 Subject: ath9k_htc: Really fix device hotunplug All commands to the target are disabled when the device is unplugged, but a normal module unload has to be differentiated from this case, as we could still receive data in the RX endpoint. Fix this by checking if the device is attached or not. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 49b7a8970ddd..74872ca76f9a 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -922,7 +922,8 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface) (struct hif_device_usb *) usb_get_intfdata(interface); if (hif_dev) { - ath9k_htc_hw_deinit(hif_dev->htc_handle, true); + ath9k_htc_hw_deinit(hif_dev->htc_handle, + (udev->state == USB_STATE_NOTATTACHED) ? true : false); ath9k_htc_hw_free(hif_dev->htc_handle); ath9k_hif_usb_dev_deinit(hif_dev); usb_set_intfdata(interface, NULL); -- cgit v1.2.3 From 2caaa5d36ee210919bd0ecc7b2e6648171544e95 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Fri, 23 Apr 2010 15:05:29 +0200 Subject: rt2x00: rt2800lib: disable HT40 for now as it causes reception problems Disable HT40 support for now as it causes rx problems with HT40 capable 11n APs (when mac80211 enables HT40, rx is completely disfunctional). Once the rt2800 HT code is capable of using HT40 we should enable the flag again. I only tested this patch with a rt305x SoC device, nevertheless the patch disables HT40 also on PCI and USB rt2800 devices. Signed-off-by: Helmut Schaa Acked-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 638600092f19..867b6527a1fd 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2317,8 +2317,11 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) else spec->ht.ht_supported = false; + /* + * Don't set IEEE80211_HT_CAP_SUP_WIDTH_20_40 for now as it causes + * reception problems with HT40 capable 11n APs + */ spec->ht.cap = - IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | -- cgit v1.2.3 From 5a673964266438784b4ebf65ee07970cde61ab5e Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Fri, 23 Apr 2010 15:54:43 +0200 Subject: rt2x00: rt2800: use tx_power2 in rt2800_config_channel_rf3xxx Get closer to what the ralink driver does by setting the rf register 13 to tx_power2 during channel switch. Signed-off-by: Helmut Schaa Acked-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 5 +++++ drivers/net/wireless/rt2x00/rt2800lib.c | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index ec893721cc80..1c59dc6a3aa2 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -1565,6 +1565,11 @@ struct mac_iveiv_entry { */ #define RFCSR12_TX_POWER FIELD8(0x1f) +/* + * RFCSR 13: + */ +#define RFCSR13_TX_POWER FIELD8(0x1f) + /* * RFCSR 15: */ diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 867b6527a1fd..2b9be79fc77f 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -793,6 +793,11 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, TXPOWER_G_TO_DEV(info->tx_power1)); rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); + rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, + TXPOWER_G_TO_DEV(info->tx_power2)); + rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); + rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); -- cgit v1.2.3 From 0bdab171ec04ea9d26a40608f69350c8c9e4872c Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 26 Apr 2010 10:18:08 +0200 Subject: rt2x00: fix typo in rt2800.h Fix a typo in a comment in rt2800.h. Instead of replacing the wrong hexvalue (0x171c) with the correct one (0x1718) just use the appropriate readable define. Signed-off-by: Helmut Schaa Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 1c59dc6a3aa2..4c0b48173213 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -107,7 +107,7 @@ /* * INT_SOURCE_CSR: Interrupt source register. * Write one to clear corresponding bit. - * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c + * TX_FIFO_STATUS: FIFO Statistics is full, sw should read TX_STA_FIFO */ #define INT_SOURCE_CSR 0x0200 #define INT_SOURCE_CSR_RXDELAYINT FIELD32(0x00000001) -- cgit v1.2.3 From 23812383c6b03afef44c4aa642500f8235c3d079 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 26 Apr 2010 13:48:45 +0200 Subject: rt2x00: rt2800lib: Fix rx path on SoC devices Restore the rfcsr initialization for RT305x SoC devices which was removed by "rt2x00: Finish rt3070 support in rt2800 register initialization.". This fixes the rx path on SoC devices. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 34 ++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 2b9be79fc77f..adb690174d1d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1707,7 +1707,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) if (!rt2x00_rt(rt2x00dev, RT3070) && !rt2x00_rt(rt2x00dev, RT3071) && !rt2x00_rt(rt2x00dev, RT3090) && - !rt2x00_rt(rt2x00dev, RT3390)) + !rt2x00_rt(rt2x00dev, RT3390) && + !(rt2x00_is_soc(rt2x00dev) && rt2x00_rt(rt2x00dev, RT2872))) return 0; /* @@ -1775,6 +1776,37 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 29, 0x8f); rt2800_rfcsr_write(rt2x00dev, 30, 0x20); rt2800_rfcsr_write(rt2x00dev, 31, 0x0f); + } else if (rt2x00_rt(rt2x00dev, RT2872)) { + rt2800_rfcsr_write(rt2x00dev, 0, 0x50); + rt2800_rfcsr_write(rt2x00dev, 1, 0x01); + rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); + rt2800_rfcsr_write(rt2x00dev, 3, 0x75); + rt2800_rfcsr_write(rt2x00dev, 4, 0x40); + rt2800_rfcsr_write(rt2x00dev, 5, 0x03); + rt2800_rfcsr_write(rt2x00dev, 6, 0x02); + rt2800_rfcsr_write(rt2x00dev, 7, 0x50); + rt2800_rfcsr_write(rt2x00dev, 8, 0x39); + rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); + rt2800_rfcsr_write(rt2x00dev, 10, 0x60); + rt2800_rfcsr_write(rt2x00dev, 11, 0x21); + rt2800_rfcsr_write(rt2x00dev, 12, 0x75); + rt2800_rfcsr_write(rt2x00dev, 13, 0x75); + rt2800_rfcsr_write(rt2x00dev, 14, 0x90); + rt2800_rfcsr_write(rt2x00dev, 15, 0x58); + rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); + rt2800_rfcsr_write(rt2x00dev, 17, 0x92); + rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); + rt2800_rfcsr_write(rt2x00dev, 19, 0x02); + rt2800_rfcsr_write(rt2x00dev, 20, 0xba); + rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); + rt2800_rfcsr_write(rt2x00dev, 22, 0x00); + rt2800_rfcsr_write(rt2x00dev, 23, 0x31); + rt2800_rfcsr_write(rt2x00dev, 24, 0x08); + rt2800_rfcsr_write(rt2x00dev, 25, 0x01); + rt2800_rfcsr_write(rt2x00dev, 26, 0x25); + rt2800_rfcsr_write(rt2x00dev, 27, 0x23); + rt2800_rfcsr_write(rt2x00dev, 28, 0x13); + rt2800_rfcsr_write(rt2x00dev, 29, 0x83); } if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { -- cgit v1.2.3 From 9a8b424ea8b64da83b6868423dcd0f3c259fdde0 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 26 Apr 2010 13:50:27 +0200 Subject: rt2x00: rt2800lib: Remove redundant check for RT2872 Remove redundant check for RT2872. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index adb690174d1d..12a49e0c4ac5 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2022,7 +2022,6 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); } else if (rt2x00_rt(rt2x00dev, RT2860) || rt2x00_rt(rt2x00dev, RT2870) || - rt2x00_rt(rt2x00dev, RT2872) || rt2x00_rt(rt2x00dev, RT2872)) { /* * There is a max of 2 RX streams for RT28x0 series -- cgit v1.2.3 From e9bd5bcde7af27ebb92bb866afde5ef5e4f3dc6c Mon Sep 17 00:00:00 2001 From: Steve deRosier Date: Sun, 25 Apr 2010 14:40:46 -0700 Subject: libertastf: add configurable debug messages Add the same type of configurable debug messages to libertas_tf as already exist in the libertas driver. This has facilitated creation of a interface specification and will facilitate future development of this driver. Signed-off-by: Steve deRosier Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 6 + drivers/net/wireless/libertas_tf/cmd.c | 202 ++++++++++++++++++---- drivers/net/wireless/libertas_tf/deb_defs.h | 106 ++++++++++++ drivers/net/wireless/libertas_tf/if_usb.c | 250 +++++++++++++++++++++++----- drivers/net/wireless/libertas_tf/main.c | 87 +++++++++- 5 files changed, 572 insertions(+), 79 deletions(-) create mode 100644 drivers/net/wireless/libertas_tf/deb_defs.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 77500cb7fd26..2fbe9b4506c0 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -38,6 +38,12 @@ config LIBERTAS_THINFIRM ---help--- A library for Marvell Libertas 8xxx devices using thinfirm. +config LIBERTAS_THINFIRM_DEBUG + bool "Enable full debugging output in the Libertas thin firmware module." + depends on LIBERTAS_THINFIRM + ---help--- + Debugging support. + config LIBERTAS_THINFIRM_USB tristate "Marvell Libertas 8388 USB 802.11b/g cards with thin firmware" depends on LIBERTAS_THINFIRM && USB diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c index 28790e03dc43..22645e4028de 100644 --- a/drivers/net/wireless/libertas_tf/cmd.c +++ b/drivers/net/wireless/libertas_tf/cmd.c @@ -7,6 +7,7 @@ * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. */ +#include "deb_defs.h" #include "libertas_tf.h" static const struct channel_range channel_ranges[] = { @@ -80,6 +81,8 @@ int lbtf_update_hw_spec(struct lbtf_private *priv) int ret = -1; u32 i; + lbtf_deb_enter(LBTF_DEB_CMD); + memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN); @@ -102,6 +105,8 @@ int lbtf_update_hw_spec(struct lbtf_private *priv) priv->fwrelease >> 8 & 0xff, priv->fwrelease & 0xff, priv->fwcapinfo); + lbtf_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", + cmd.hwifversion, cmd.version); /* Clamp region code to 8-bit since FW spec indicates that it should * only ever be 8-bit, even though the field size is 16-bit. Some @@ -116,8 +121,10 @@ int lbtf_update_hw_spec(struct lbtf_private *priv) } /* if it's unidentified region code, use the default (USA) */ - if (i >= MRVDRV_MAX_REGION_CODE) + if (i >= MRVDRV_MAX_REGION_CODE) { priv->regioncode = 0x10; + pr_info("unidentified region code; using the default (USA)\n"); + } if (priv->current_addr[0] == 0xff) memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN); @@ -126,6 +133,7 @@ int lbtf_update_hw_spec(struct lbtf_private *priv) lbtf_geo_init(priv); out: + lbtf_deb_leave(LBTF_DEB_CMD); return ret; } @@ -139,13 +147,18 @@ out: */ int lbtf_set_channel(struct lbtf_private *priv, u8 channel) { + int ret = 0; struct cmd_ds_802_11_rf_channel cmd; + lbtf_deb_enter(LBTF_DEB_CMD); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET); cmd.channel = cpu_to_le16(channel); - return lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd); + ret = lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd); + lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret); + return ret; } int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon) @@ -153,20 +166,28 @@ int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon) struct cmd_ds_802_11_beacon_set cmd; int size; - if (beacon->len > MRVL_MAX_BCN_SIZE) + lbtf_deb_enter(LBTF_DEB_CMD); + + if (beacon->len > MRVL_MAX_BCN_SIZE) { + lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", -1); return -1; + } size = sizeof(cmd) - sizeof(cmd.beacon) + beacon->len; cmd.hdr.size = cpu_to_le16(size); cmd.len = cpu_to_le16(beacon->len); memcpy(cmd.beacon, (u8 *) beacon->data, beacon->len); lbtf_cmd_async(priv, CMD_802_11_BEACON_SET, &cmd.hdr, size); + + lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", 0); return 0; } int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable, - int beacon_int) { + int beacon_int) +{ struct cmd_ds_802_11_beacon_control cmd; + lbtf_deb_enter(LBTF_DEB_CMD); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_SET); @@ -174,6 +195,8 @@ int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable, cmd.beacon_period = cpu_to_le16(beacon_int); lbtf_cmd_async(priv, CMD_802_11_BEACON_CTRL, &cmd.hdr, sizeof(cmd)); + + lbtf_deb_leave(LBTF_DEB_CMD); return 0; } @@ -181,17 +204,28 @@ static void lbtf_queue_cmd(struct lbtf_private *priv, struct cmd_ctrl_node *cmdnode) { unsigned long flags; + lbtf_deb_enter(LBTF_DEB_HOST); - if (!cmdnode) - return; + if (!cmdnode) { + lbtf_deb_host("QUEUE_CMD: cmdnode is NULL\n"); + goto qcmd_done; + } - if (!cmdnode->cmdbuf->size) - return; + if (!cmdnode->cmdbuf->size) { + lbtf_deb_host("DNLD_CMD: cmd size is zero\n"); + goto qcmd_done; + } cmdnode->result = 0; spin_lock_irqsave(&priv->driver_lock, flags); list_add_tail(&cmdnode->list, &priv->cmdpendingq); spin_unlock_irqrestore(&priv->driver_lock, flags); + + lbtf_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n", + le16_to_cpu(cmdnode->cmdbuf->command)); + +qcmd_done: + lbtf_deb_leave(LBTF_DEB_HOST); } static void lbtf_submit_command(struct lbtf_private *priv, @@ -204,22 +238,33 @@ static void lbtf_submit_command(struct lbtf_private *priv, int timeo = 5 * HZ; int ret; + lbtf_deb_enter(LBTF_DEB_HOST); + cmd = cmdnode->cmdbuf; spin_lock_irqsave(&priv->driver_lock, flags); priv->cur_cmd = cmdnode; cmdsize = le16_to_cpu(cmd->size); command = le16_to_cpu(cmd->command); + + lbtf_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n", + command, le16_to_cpu(cmd->seqnum), cmdsize); + lbtf_deb_hex(LBTF_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize); + ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize); spin_unlock_irqrestore(&priv->driver_lock, flags); - if (ret) + if (ret) { + pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret); /* Let the timer kick in and retry, and potentially reset the whole thing if the condition persists */ timeo = HZ; + } /* Setup the timer after transmit command */ mod_timer(&priv->command_timer, jiffies + timeo); + + lbtf_deb_leave(LBTF_DEB_HOST); } /** @@ -229,8 +274,10 @@ static void lbtf_submit_command(struct lbtf_private *priv, static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv, struct cmd_ctrl_node *cmdnode) { + lbtf_deb_enter(LBTF_DEB_HOST); + if (!cmdnode) - return; + goto cl_ins_out; cmdnode->callback = NULL; cmdnode->callback_arg = 0; @@ -238,6 +285,9 @@ static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv, memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE); list_add_tail(&cmdnode->list, &priv->cmdfreeq); + +cl_ins_out: + lbtf_deb_leave(LBTF_DEB_HOST); } static void lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv, @@ -266,29 +316,41 @@ int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv) { struct cmd_ds_mac_multicast_addr cmd; + lbtf_deb_enter(LBTF_DEB_CMD); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_SET); cmd.nr_of_adrs = cpu_to_le16((u16) priv->nr_of_multicastmacaddr); + + lbtf_deb_cmd("MULTICAST_ADR: setting %d addresses\n", cmd.nr_of_adrs); + memcpy(cmd.maclist, priv->multicastlist, priv->nr_of_multicastmacaddr * ETH_ALEN); lbtf_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &cmd.hdr, sizeof(cmd)); + + lbtf_deb_leave(LBTF_DEB_CMD); return 0; } void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode) { struct cmd_ds_set_mode cmd; + lbtf_deb_enter(LBTF_DEB_WEXT); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.mode = cpu_to_le16(mode); + lbtf_deb_wext("Switching to mode: 0x%x\n", mode); lbtf_cmd_async(priv, CMD_802_11_SET_MODE, &cmd.hdr, sizeof(cmd)); + + lbtf_deb_leave(LBTF_DEB_WEXT); } void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid) { struct cmd_ds_set_bssid cmd; + lbtf_deb_enter(LBTF_DEB_CMD); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.activate = activate ? 1 : 0; @@ -296,11 +358,13 @@ void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid) memcpy(cmd.bssid, bssid, ETH_ALEN); lbtf_cmd_async(priv, CMD_802_11_SET_BSSID, &cmd.hdr, sizeof(cmd)); + lbtf_deb_leave(LBTF_DEB_CMD); } int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr) { struct cmd_ds_802_11_mac_address cmd; + lbtf_deb_enter(LBTF_DEB_CMD); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_SET); @@ -308,6 +372,7 @@ int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr) memcpy(cmd.macadd, mac_addr, ETH_ALEN); lbtf_cmd_async(priv, CMD_802_11_MAC_ADDRESS, &cmd.hdr, sizeof(cmd)); + lbtf_deb_leave(LBTF_DEB_CMD); return 0; } @@ -316,6 +381,8 @@ int lbtf_set_radio_control(struct lbtf_private *priv) int ret = 0; struct cmd_ds_802_11_radio_control cmd; + lbtf_deb_enter(LBTF_DEB_CMD); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_SET); @@ -339,19 +406,28 @@ int lbtf_set_radio_control(struct lbtf_private *priv) else cmd.control &= cpu_to_le16(~TURN_ON_RF); + lbtf_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon, + priv->preamble); + ret = lbtf_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd); + + lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret); return ret; } void lbtf_set_mac_control(struct lbtf_private *priv) { struct cmd_ds_mac_control cmd; + lbtf_deb_enter(LBTF_DEB_CMD); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(priv->mac_control); cmd.reserved = 0; lbtf_cmd_async(priv, CMD_MAC_CONTROL, &cmd.hdr, sizeof(cmd)); + + lbtf_deb_leave(LBTF_DEB_CMD); } /** @@ -363,29 +439,43 @@ void lbtf_set_mac_control(struct lbtf_private *priv) */ int lbtf_allocate_cmd_buffer(struct lbtf_private *priv) { + int ret = 0; u32 bufsize; u32 i; struct cmd_ctrl_node *cmdarray; + lbtf_deb_enter(LBTF_DEB_HOST); + /* Allocate and initialize the command array */ bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS; cmdarray = kzalloc(bufsize, GFP_KERNEL); - if (!cmdarray) - return -1; + if (!cmdarray) { + lbtf_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n"); + ret = -1; + goto done; + } priv->cmd_array = cmdarray; /* Allocate and initialize each command buffer in the command array */ for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) { cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL); - if (!cmdarray[i].cmdbuf) - return -1; + if (!cmdarray[i].cmdbuf) { + lbtf_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n"); + ret = -1; + goto done; + } } for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) { init_waitqueue_head(&cmdarray[i].cmdwait_q); lbtf_cleanup_and_insert_cmd(priv, &cmdarray[i]); } - return 0; + + ret = 0; + +done: + lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret); + return ret; } /** @@ -400,9 +490,13 @@ int lbtf_free_cmd_buffer(struct lbtf_private *priv) struct cmd_ctrl_node *cmdarray; unsigned int i; + lbtf_deb_enter(LBTF_DEB_HOST); + /* need to check if cmd array is allocated or not */ - if (priv->cmd_array == NULL) - return 0; + if (priv->cmd_array == NULL) { + lbtf_deb_host("FREE_CMD_BUF: cmd_array is NULL\n"); + goto done; + } cmdarray = priv->cmd_array; @@ -416,6 +510,8 @@ int lbtf_free_cmd_buffer(struct lbtf_private *priv) kfree(priv->cmd_array); priv->cmd_array = NULL; +done: + lbtf_deb_leave(LBTF_DEB_HOST); return 0; } @@ -431,6 +527,8 @@ static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv) struct cmd_ctrl_node *tempnode; unsigned long flags; + lbtf_deb_enter(LBTF_DEB_HOST); + if (!priv) return NULL; @@ -440,11 +538,14 @@ static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv) tempnode = list_first_entry(&priv->cmdfreeq, struct cmd_ctrl_node, list); list_del(&tempnode->list); - } else + } else { + lbtf_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n"); tempnode = NULL; + } spin_unlock_irqrestore(&priv->driver_lock, flags); + lbtf_deb_leave(LBTF_DEB_HOST); return tempnode; } @@ -460,16 +561,20 @@ int lbtf_execute_next_command(struct lbtf_private *priv) struct cmd_ctrl_node *cmdnode = NULL; struct cmd_header *cmd; unsigned long flags; + int ret = 0; - /* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the + /* Debug group is lbtf_deb_THREAD and not lbtf_deb_HOST, because the * only caller to us is lbtf_thread() and we get even when a * data packet is received */ + lbtf_deb_enter(LBTF_DEB_THREAD); spin_lock_irqsave(&priv->driver_lock, flags); if (priv->cur_cmd) { + pr_alert("EXEC_NEXT_CMD: already processing command!\n"); spin_unlock_irqrestore(&priv->driver_lock, flags); - return -1; + ret = -1; + goto done; } if (!list_empty(&priv->cmdpendingq)) { @@ -481,11 +586,17 @@ int lbtf_execute_next_command(struct lbtf_private *priv) cmd = cmdnode->cmdbuf; list_del(&cmdnode->list); + lbtf_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n", + le16_to_cpu(cmd->command)); spin_unlock_irqrestore(&priv->driver_lock, flags); lbtf_submit_command(priv, cmdnode); } else spin_unlock_irqrestore(&priv->driver_lock, flags); - return 0; + + ret = 0; +done: + lbtf_deb_leave(LBTF_DEB_THREAD); + return ret; } static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv, @@ -496,14 +607,22 @@ static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv, { struct cmd_ctrl_node *cmdnode; - if (priv->surpriseremoved) - return ERR_PTR(-ENOENT); + lbtf_deb_enter(LBTF_DEB_HOST); + + if (priv->surpriseremoved) { + lbtf_deb_host("PREP_CMD: card removed\n"); + cmdnode = ERR_PTR(-ENOENT); + goto done; + } cmdnode = lbtf_get_cmd_ctrl_node(priv); if (cmdnode == NULL) { + lbtf_deb_host("PREP_CMD: cmdnode is NULL\n"); + /* Wake up main thread to execute next command */ queue_work(lbtf_wq, &priv->cmd_work); - return ERR_PTR(-ENOBUFS); + cmdnode = ERR_PTR(-ENOBUFS); + goto done; } cmdnode->callback = callback; @@ -518,17 +637,24 @@ static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv, cmdnode->cmdbuf->size = cpu_to_le16(in_cmd_size); cmdnode->cmdbuf->seqnum = cpu_to_le16(priv->seqnum); cmdnode->cmdbuf->result = 0; + + lbtf_deb_host("PREP_CMD: command 0x%04x\n", command); + cmdnode->cmdwaitqwoken = 0; lbtf_queue_cmd(priv, cmdnode); queue_work(lbtf_wq, &priv->cmd_work); + done: + lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %p", cmdnode); return cmdnode; } void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command, struct cmd_header *in_cmd, int in_cmd_size) { + lbtf_deb_enter(LBTF_DEB_CMD); __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size, NULL, 0); + lbtf_deb_leave(LBTF_DEB_CMD); } int __lbtf_cmd(struct lbtf_private *priv, uint16_t command, @@ -541,30 +667,35 @@ int __lbtf_cmd(struct lbtf_private *priv, uint16_t command, unsigned long flags; int ret = 0; + lbtf_deb_enter(LBTF_DEB_HOST); + cmdnode = __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size, callback, callback_arg); - if (IS_ERR(cmdnode)) - return PTR_ERR(cmdnode); + if (IS_ERR(cmdnode)) { + ret = PTR_ERR(cmdnode); + goto done; + } might_sleep(); ret = wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken); - if (ret) { - printk(KERN_DEBUG - "libertastf: command 0x%04x interrupted by signal", - command); - return ret; + if (ret) { + pr_info("PREP_CMD: command 0x%04x interrupted by signal: %d\n", + command, ret); + goto done; } spin_lock_irqsave(&priv->driver_lock, flags); ret = cmdnode->result; if (ret) - printk(KERN_DEBUG "libertastf: command 0x%04x failed: %d\n", + pr_info("PREP_CMD: command 0x%04x failed: %d\n", command, ret); __lbtf_cleanup_and_insert_cmd(priv, cmdnode); spin_unlock_irqrestore(&priv->driver_lock, flags); +done: + lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret); return ret; } EXPORT_SYMBOL_GPL(__lbtf_cmd); @@ -585,6 +716,8 @@ int lbtf_process_rx_command(struct lbtf_private *priv) unsigned long flags; uint16_t result; + lbtf_deb_enter(LBTF_DEB_CMD); + mutex_lock(&priv->lock); spin_lock_irqsave(&priv->driver_lock, flags); @@ -600,7 +733,7 @@ int lbtf_process_rx_command(struct lbtf_private *priv) result = le16_to_cpu(resp->result); if (net_ratelimit()) - printk(KERN_DEBUG "libertastf: cmd response 0x%04x, seq %d, size %d\n", + pr_info("libertastf: cmd response 0x%04x, seq %d, size %d\n", respcmd, le16_to_cpu(resp->seqnum), le16_to_cpu(resp->size)); @@ -637,7 +770,7 @@ int lbtf_process_rx_command(struct lbtf_private *priv) switch (respcmd) { case CMD_RET(CMD_GET_HW_SPEC): case CMD_RET(CMD_802_11_RESET): - printk(KERN_DEBUG "libertastf: reset failed\n"); + pr_info("libertastf: reset failed\n"); break; } @@ -664,5 +797,6 @@ int lbtf_process_rx_command(struct lbtf_private *priv) done: mutex_unlock(&priv->lock); + lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret); return ret; } diff --git a/drivers/net/wireless/libertas_tf/deb_defs.h b/drivers/net/wireless/libertas_tf/deb_defs.h new file mode 100644 index 000000000000..9a3e92bec5fd --- /dev/null +++ b/drivers/net/wireless/libertas_tf/deb_defs.h @@ -0,0 +1,106 @@ +/** + * This header file contains global constant/enum definitions, + * global variable declaration. + */ +#ifndef _LBS_DEB_DEFS_H_ +#define _LBS_DEB_EFS_H_ + +#ifndef DRV_NAME +#define DRV_NAME "libertas_tf" +#endif + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include + +#ifdef CONFIG_LIBERTAS_THINFIRM_DEBUG +#define DEBUG +#define PROC_DEBUG +#endif + +#define LBTF_DEB_ENTER 0x00000001 +#define LBTF_DEB_LEAVE 0x00000002 +#define LBTF_DEB_MAIN 0x00000004 +#define LBTF_DEB_NET 0x00000008 +#define LBTF_DEB_MESH 0x00000010 +#define LBTF_DEB_WEXT 0x00000020 +#define LBTF_DEB_IOCTL 0x00000040 +#define LBTF_DEB_SCAN 0x00000080 +#define LBTF_DEB_ASSOC 0x00000100 +#define LBTF_DEB_JOIN 0x00000200 +#define LBTF_DEB_11D 0x00000400 +#define LBTF_DEB_DEBUGFS 0x00000800 +#define LBTF_DEB_ETHTOOL 0x00001000 +#define LBTF_DEB_HOST 0x00002000 +#define LBTF_DEB_CMD 0x00004000 +#define LBTF_DEB_RX 0x00008000 +#define LBTF_DEB_TX 0x00010000 +#define LBTF_DEB_USB 0x00020000 +#define LBTF_DEB_CS 0x00040000 +#define LBTF_DEB_FW 0x00080000 +#define LBTF_DEB_THREAD 0x00100000 +#define LBTF_DEB_HEX 0x00200000 +#define LBTF_DEB_SDIO 0x00400000 +#define LBTF_DEB_MACOPS 0x00800000 + +extern unsigned int lbtf_debug; + + +#ifdef DEBUG +#define LBTF_DEB_LL(grp, grpnam, fmt, args...) \ +do { if ((lbtf_debug & (grp)) == (grp)) \ + printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \ + in_interrupt() ? " (INT)" : "", ## args); } while (0) +#else +#define LBTF_DEB_LL(grp, grpnam, fmt, args...) do {} while (0) +#endif + +#define lbtf_deb_enter(grp) \ + LBTF_DEB_LL(grp | LBTF_DEB_ENTER, " enter", "%s()\n", __func__); +#define lbtf_deb_enter_args(grp, fmt, args...) \ + LBTF_DEB_LL(grp | LBTF_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args); +#define lbtf_deb_leave(grp) \ + LBTF_DEB_LL(grp | LBTF_DEB_LEAVE, " leave", "%s()\n", __func__); +#define lbtf_deb_leave_args(grp, fmt, args...) \ + LBTF_DEB_LL(grp | LBTF_DEB_LEAVE, " leave", "%s(), " fmt "\n", \ + __func__, ##args); +#define lbtf_deb_main(fmt, args...) LBTF_DEB_LL(LBTF_DEB_MAIN, " main", fmt, ##args) +#define lbtf_deb_net(fmt, args...) LBTF_DEB_LL(LBTF_DEB_NET, " net", fmt, ##args) +#define lbtf_deb_mesh(fmt, args...) LBTF_DEB_LL(LBTF_DEB_MESH, " mesh", fmt, ##args) +#define lbtf_deb_wext(fmt, args...) LBTF_DEB_LL(LBTF_DEB_WEXT, " wext", fmt, ##args) +#define lbtf_deb_ioctl(fmt, args...) LBTF_DEB_LL(LBTF_DEB_IOCTL, " ioctl", fmt, ##args) +#define lbtf_deb_scan(fmt, args...) LBTF_DEB_LL(LBTF_DEB_SCAN, " scan", fmt, ##args) +#define lbtf_deb_assoc(fmt, args...) LBTF_DEB_LL(LBTF_DEB_ASSOC, " assoc", fmt, ##args) +#define lbtf_deb_join(fmt, args...) LBTF_DEB_LL(LBTF_DEB_JOIN, " join", fmt, ##args) +#define lbtf_deb_11d(fmt, args...) LBTF_DEB_LL(LBTF_DEB_11D, " 11d", fmt, ##args) +#define lbtf_deb_debugfs(fmt, args...) LBTF_DEB_LL(LBTF_DEB_DEBUGFS, " debugfs", fmt, ##args) +#define lbtf_deb_ethtool(fmt, args...) LBTF_DEB_LL(LBTF_DEB_ETHTOOL, " ethtool", fmt, ##args) +#define lbtf_deb_host(fmt, args...) LBTF_DEB_LL(LBTF_DEB_HOST, " host", fmt, ##args) +#define lbtf_deb_cmd(fmt, args...) LBTF_DEB_LL(LBTF_DEB_CMD, " cmd", fmt, ##args) +#define lbtf_deb_rx(fmt, args...) LBTF_DEB_LL(LBTF_DEB_RX, " rx", fmt, ##args) +#define lbtf_deb_tx(fmt, args...) LBTF_DEB_LL(LBTF_DEB_TX, " tx", fmt, ##args) +#define lbtf_deb_fw(fmt, args...) LBTF_DEB_LL(LBTF_DEB_FW, " fw", fmt, ##args) +#define lbtf_deb_usb(fmt, args...) LBTF_DEB_LL(LBTF_DEB_USB, " usb", fmt, ##args) +#define lbtf_deb_usbd(dev, fmt, args...) LBTF_DEB_LL(LBTF_DEB_USB, " usbd", "%s:" fmt, dev_name(dev), ##args) +#define lbtf_deb_cs(fmt, args...) LBTF_DEB_LL(LBTF_DEB_CS, " cs", fmt, ##args) +#define lbtf_deb_thread(fmt, args...) LBTF_DEB_LL(LBTF_DEB_THREAD, " thread", fmt, ##args) +#define lbtf_deb_sdio(fmt, args...) LBTF_DEB_LL(LBTF_DEB_SDIO, " thread", fmt, ##args) +#define lbtf_deb_macops(fmt, args...) LBTF_DEB_LL(LBTF_DEB_MACOPS, " thread", fmt, ##args) + +#ifdef DEBUG +static inline void lbtf_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len) +{ + char newprompt[32]; + + if (len && + (lbtf_debug & LBTF_DEB_HEX) && + (lbtf_debug & grp)) { + snprintf(newprompt, sizeof(newprompt), DRV_NAME " %s: ", prompt); + print_hex_dump_bytes(prompt, DUMP_PREFIX_NONE, buf, len); + } +} +#else +#define lbtf_deb_hex(grp, prompt, buf, len) do {} while (0) +#endif + +#endif diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index 3691c307e674..919451a2ee4a 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c @@ -7,16 +7,20 @@ * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. */ +#define DRV_NAME "lbtf_usb" + +#include "deb_defs.h" +#include "libertas_tf.h" +#include "if_usb.h" + #include #include #include #include #include -#define DRV_NAME "lbtf_usb" - -#include "libertas_tf.h" -#include "if_usb.h" +#define INSANEDEBUG 0 +#define lbtf_deb_usb2(...) do { if (INSANEDEBUG) lbtf_deb_usbd(__VA_ARGS__); } while (0) #define MESSAGE_HEADER_LEN 4 @@ -52,9 +56,14 @@ static int if_usb_reset_device(struct if_usb_card *cardp); */ static void if_usb_write_bulk_callback(struct urb *urb) { - if (urb->status != 0) - printk(KERN_INFO "libertastf: URB in failure status: %d\n", - urb->status); + if (urb->status != 0) { + /* print the failure status number for debug */ + pr_info("URB in failure status: %d\n", urb->status); + } else { + lbtf_deb_usb2(&urb->dev->dev, "URB status is successful\n"); + lbtf_deb_usb2(&urb->dev->dev, "Actual length transmitted %d\n", + urb->actual_length); + } } /** @@ -64,6 +73,8 @@ static void if_usb_write_bulk_callback(struct urb *urb) */ static void if_usb_free(struct if_usb_card *cardp) { + lbtf_deb_enter(LBTF_DEB_USB); + /* Unlink tx & rx urb */ usb_kill_urb(cardp->tx_urb); usb_kill_urb(cardp->rx_urb); @@ -80,6 +91,8 @@ static void if_usb_free(struct if_usb_card *cardp) kfree(cardp->ep_out_buf); cardp->ep_out_buf = NULL; + + lbtf_deb_leave(LBTF_DEB_USB); } static void if_usb_setup_firmware(struct lbtf_private *priv) @@ -87,23 +100,33 @@ static void if_usb_setup_firmware(struct lbtf_private *priv) struct if_usb_card *cardp = priv->card; struct cmd_ds_set_boot2_ver b2_cmd; + lbtf_deb_enter(LBTF_DEB_USB); + if_usb_submit_rx_urb(cardp); b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd)); b2_cmd.action = 0; b2_cmd.version = cardp->boot2_version; if (lbtf_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd)) - printk(KERN_INFO "libertastf: setting boot2 version failed\n"); + lbtf_deb_usb("Setting boot2 version failed\n"); + + lbtf_deb_leave(LBTF_DEB_USB); } static void if_usb_fw_timeo(unsigned long priv) { struct if_usb_card *cardp = (void *)priv; - if (!cardp->fwdnldover) + lbtf_deb_enter(LBTF_DEB_USB); + if (!cardp->fwdnldover) { /* Download timed out */ cardp->priv->surpriseremoved = 1; + pr_err("Download timed out\n"); + } else { + lbtf_deb_usb("Download complete, no event. Assuming success\n"); + } wake_up(&cardp->fw_wq); + lbtf_deb_leave(LBTF_DEB_USB); } /** @@ -124,11 +147,14 @@ static int if_usb_probe(struct usb_interface *intf, struct if_usb_card *cardp; int i; + lbtf_deb_enter(LBTF_DEB_USB); udev = interface_to_usbdev(intf); cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL); - if (!cardp) + if (!cardp) { + pr_err("Out of memory allocating private data.\n"); goto error; + } setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp); init_waitqueue_head(&cardp->fw_wq); @@ -136,38 +162,62 @@ static int if_usb_probe(struct usb_interface *intf, cardp->udev = udev; iface_desc = intf->cur_altsetting; + lbtf_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" + " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n", + le16_to_cpu(udev->descriptor.bcdUSB), + udev->descriptor.bDeviceClass, + udev->descriptor.bDeviceSubClass, + udev->descriptor.bDeviceProtocol); + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_bulk_in(endpoint)) { cardp->ep_in_size = le16_to_cpu(endpoint->wMaxPacketSize); cardp->ep_in = usb_endpoint_num(endpoint); + + lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in); + lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size); } else if (usb_endpoint_is_bulk_out(endpoint)) { cardp->ep_out_size = le16_to_cpu(endpoint->wMaxPacketSize); cardp->ep_out = usb_endpoint_num(endpoint); + + lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out); + lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n", + cardp->ep_out_size); } } - if (!cardp->ep_out_size || !cardp->ep_in_size) + if (!cardp->ep_out_size || !cardp->ep_in_size) { + lbtf_deb_usbd(&udev->dev, "Endpoints not found\n"); /* Endpoints not found */ goto dealloc; + } cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!cardp->rx_urb) + if (!cardp->rx_urb) { + lbtf_deb_usbd(&udev->dev, "Rx URB allocation failed\n"); goto dealloc; + } cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!cardp->tx_urb) + if (!cardp->tx_urb) { + lbtf_deb_usbd(&udev->dev, "Tx URB allocation failed\n"); goto dealloc; + } cardp->cmd_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!cardp->cmd_urb) + if (!cardp->cmd_urb) { + lbtf_deb_usbd(&udev->dev, "Cmd URB allocation failed\n"); goto dealloc; + } cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE, GFP_KERNEL); - if (!cardp->ep_out_buf) + if (!cardp->ep_out_buf) { + lbtf_deb_usbd(&udev->dev, "Could not allocate buffer\n"); goto dealloc; + } priv = lbtf_add_card(cardp, &udev->dev); if (!priv) @@ -188,6 +238,7 @@ static int if_usb_probe(struct usb_interface *intf, dealloc: if_usb_free(cardp); error: +lbtf_deb_leave(LBTF_DEB_MAIN); return -ENOMEM; } @@ -201,6 +252,8 @@ static void if_usb_disconnect(struct usb_interface *intf) struct if_usb_card *cardp = usb_get_intfdata(intf); struct lbtf_private *priv = (struct lbtf_private *) cardp->priv; + lbtf_deb_enter(LBTF_DEB_MAIN); + if_usb_reset_device(cardp); if (priv) @@ -211,6 +264,8 @@ static void if_usb_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); usb_put_dev(interface_to_usbdev(intf)); + + lbtf_deb_leave(LBTF_DEB_MAIN); } /** @@ -225,6 +280,8 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp) struct fwdata *fwdata = cardp->ep_out_buf; u8 *firmware = (u8 *) cardp->fw->data; + lbtf_deb_enter(LBTF_DEB_FW); + /* If we got a CRC failure on the last block, back up and retry it */ if (!cardp->CRC_OK) { @@ -232,6 +289,9 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp) cardp->fwseqnum--; } + lbtf_deb_usb2(&cardp->udev->dev, "totalbytes = %d\n", + cardp->totalbytes); + /* struct fwdata (which we sent to the card) has an extra __le32 field in between the header and the data, which is not in the struct fwheader in the actual @@ -245,18 +305,33 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp) memcpy(fwdata->data, &firmware[cardp->totalbytes], le32_to_cpu(fwdata->hdr.datalength)); + lbtf_deb_usb2(&cardp->udev->dev, "Data length = %d\n", + le32_to_cpu(fwdata->hdr.datalength)); + fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum); cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength); usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) + le32_to_cpu(fwdata->hdr.datalength), 0); - if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) + if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) { + lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n"); + lbtf_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n", + cardp->fwseqnum, cardp->totalbytes); + } else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) { + lbtf_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n"); + lbtf_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n"); + /* Host has finished FW downloading * Donwloading FW JUMP BLOCK */ cardp->fwfinalblk = 1; + } + lbtf_deb_usb2(&cardp->udev->dev, "Firmware download done; size %d\n", + cardp->totalbytes); + + lbtf_deb_leave(LBTF_DEB_FW); return 0; } @@ -265,6 +340,8 @@ static int if_usb_reset_device(struct if_usb_card *cardp) struct cmd_ds_802_11_reset *cmd = cardp->ep_out_buf + 4; int ret; + lbtf_deb_enter(LBTF_DEB_USB); + *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST); cmd->hdr.command = cpu_to_le16(CMD_802_11_RESET); @@ -279,6 +356,8 @@ static int if_usb_reset_device(struct if_usb_card *cardp) ret = usb_reset_device(cardp->udev); msleep(100); + lbtf_deb_leave_args(LBTF_DEB_USB, "ret %d", ret); + return ret; } EXPORT_SYMBOL_GPL(if_usb_reset_device); @@ -296,11 +375,15 @@ EXPORT_SYMBOL_GPL(if_usb_reset_device); static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb, u8 data) { + int ret = -1; struct urb *urb; + lbtf_deb_enter(LBTF_DEB_USB); /* check if device is removed */ - if (cardp->priv->surpriseremoved) - return -1; + if (cardp->priv->surpriseremoved) { + lbtf_deb_usbd(&cardp->udev->dev, "Device removed\n"); + goto tx_ret; + } if (data) urb = cardp->tx_urb; @@ -314,19 +397,34 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, urb->transfer_flags |= URB_ZERO_PACKET; - if (usb_submit_urb(urb, GFP_ATOMIC)) - return -1; - return 0; + if (usb_submit_urb(urb, GFP_ATOMIC)) { + lbtf_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret); + goto tx_ret; + } + + lbtf_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n"); + + ret = 0; + +tx_ret: + lbtf_deb_leave(LBTF_DEB_USB); + return ret; } static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, void (*callbackfn)(struct urb *urb)) { struct sk_buff *skb; + int ret = -1; + + lbtf_deb_enter(LBTF_DEB_USB); skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); - if (!skb) + if (!skb) { + pr_err("No free skb\n"); + lbtf_deb_leave(LBTF_DEB_USB); return -1; + } cardp->rx_skb = skb; @@ -338,12 +436,19 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; - if (usb_submit_urb(cardp->rx_urb, GFP_ATOMIC)) { + lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); + ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC); + if (ret) { + lbtf_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret); kfree_skb(skb); cardp->rx_skb = NULL; + lbtf_deb_leave(LBTF_DEB_USB); return -1; - } else + } else { + lbtf_deb_usb2(&cardp->udev->dev, "Submit Rx URB success\n"); + lbtf_deb_leave(LBTF_DEB_USB); return 0; + } } static int if_usb_submit_rx_urb_fwload(struct if_usb_card *cardp) @@ -363,8 +468,12 @@ static void if_usb_receive_fwload(struct urb *urb) struct fwsyncheader *syncfwheader; struct bootcmdresp bcmdresp; + lbtf_deb_enter(LBTF_DEB_USB); if (urb->status) { + lbtf_deb_usbd(&cardp->udev->dev, + "URB status is failed during fw load\n"); kfree_skb(skb); + lbtf_deb_leave(LBTF_DEB_USB); return; } @@ -372,12 +481,17 @@ static void if_usb_receive_fwload(struct urb *urb) __le32 *tmp = (__le32 *)(skb->data); if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) && - tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) + tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) { /* Firmware ready event received */ + pr_info("Firmware ready event received\n"); wake_up(&cardp->fw_wq); - else + } else { + lbtf_deb_usb("Waiting for confirmation; got %x %x\n", + le32_to_cpu(tmp[0]), le32_to_cpu(tmp[1])); if_usb_submit_rx_urb_fwload(cardp); + } kfree_skb(skb); + lbtf_deb_leave(LBTF_DEB_USB); return; } if (cardp->bootcmdresp <= 0) { @@ -388,34 +502,60 @@ static void if_usb_receive_fwload(struct urb *urb) if_usb_submit_rx_urb_fwload(cardp); cardp->bootcmdresp = 1; /* Received valid boot command response */ + lbtf_deb_usbd(&cardp->udev->dev, + "Received valid boot command response\n"); + lbtf_deb_leave(LBTF_DEB_USB); return; } if (bcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) { if (bcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) || bcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) || - bcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) + bcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) { + if (!cardp->bootcmdresp) + pr_info("Firmware already seems alive; resetting\n"); cardp->bootcmdresp = -1; - } else if (bcmdresp.cmd == BOOT_CMD_FW_BY_USB && - bcmdresp.result == BOOT_CMD_RESP_OK) + } else { + pr_info("boot cmd response wrong magic number (0x%x)\n", + le32_to_cpu(bcmdresp.magic)); + } + } else if (bcmdresp.cmd != BOOT_CMD_FW_BY_USB) { + pr_info("boot cmd response cmd_tag error (%d)\n", + bcmdresp.cmd); + } else if (bcmdresp.result != BOOT_CMD_RESP_OK) { + pr_info("boot cmd response result error (%d)\n", + bcmdresp.result); + } else { cardp->bootcmdresp = 1; + lbtf_deb_usbd(&cardp->udev->dev, + "Received valid boot command response\n"); + } kfree_skb(skb); if_usb_submit_rx_urb_fwload(cardp); + lbtf_deb_leave(LBTF_DEB_USB); return; } syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC); if (!syncfwheader) { + lbtf_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); kfree_skb(skb); + lbtf_deb_leave(LBTF_DEB_USB); return; } memcpy(syncfwheader, skb->data, sizeof(struct fwsyncheader)); - if (!syncfwheader->cmd) + if (!syncfwheader->cmd) { + lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); + lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", + le32_to_cpu(syncfwheader->seqnum)); cardp->CRC_OK = 1; - else + } else { + lbtf_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n"); cardp->CRC_OK = 0; + } + kfree_skb(skb); /* reschedule timer for 200ms hence */ @@ -433,6 +573,7 @@ static void if_usb_receive_fwload(struct urb *urb) kfree(syncfwheader); + lbtf_deb_leave(LBTF_DEB_USB); return; } @@ -444,6 +585,7 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb, { if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN || recvlength < MRVDRV_MIN_PKT_LEN) { + lbtf_deb_usbd(&cardp->udev->dev, "Packet length is Invalid\n"); kfree_skb(skb); return; } @@ -459,6 +601,8 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, struct lbtf_private *priv) { if (recvlength > LBS_CMD_BUFFER_SIZE) { + lbtf_deb_usbd(&cardp->udev->dev, + "The receive buffer is too large\n"); kfree_skb(skb); return; } @@ -488,16 +632,24 @@ static void if_usb_receive(struct urb *urb) uint32_t recvtype = 0; __le32 *pkt = (__le32 *) skb->data; + lbtf_deb_enter(LBTF_DEB_USB); + if (recvlength) { if (urb->status) { + lbtf_deb_usbd(&cardp->udev->dev, "RX URB failed: %d\n", + urb->status); kfree_skb(skb); goto setup_for_next; } recvbuff = skb->data; recvtype = le32_to_cpu(pkt[0]); + lbtf_deb_usbd(&cardp->udev->dev, + "Recv length = 0x%x, Recv type = 0x%X\n", + recvlength, recvtype); } else if (urb->status) { kfree_skb(skb); + lbtf_deb_leave(LBTF_DEB_USB); return; } @@ -514,6 +666,7 @@ static void if_usb_receive(struct urb *urb) { /* Event cause handling */ u32 event_cause = le32_to_cpu(pkt[1]); + lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event_cause); /* Icky undocumented magic special case */ if (event_cause & 0xffff0000) { @@ -528,21 +681,22 @@ static void if_usb_receive(struct urb *urb) } else if (event_cause == LBTF_EVENT_BCN_SENT) lbtf_bcn_sent(priv); else - printk(KERN_DEBUG + lbtf_deb_usbd(&cardp->udev->dev, "Unsupported notification %d received\n", event_cause); kfree_skb(skb); break; } default: - printk(KERN_DEBUG "libertastf: unknown command type 0x%X\n", - recvtype); + lbtf_deb_usbd(&cardp->udev->dev, + "libertastf: unknown command type 0x%X\n", recvtype); kfree_skb(skb); break; } setup_for_next: if_usb_submit_rx_urb(cardp); + lbtf_deb_leave(LBTF_DEB_USB); } /** @@ -561,6 +715,9 @@ static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type, struct if_usb_card *cardp = priv->card; u8 data = 0; + lbtf_deb_usbd(&cardp->udev->dev, "*** type = %u\n", type); + lbtf_deb_usbd(&cardp->udev->dev, "size after = %d\n", nb); + if (type == MVMS_CMD) { *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST); } else { @@ -638,8 +795,10 @@ static int check_fwfile_format(const u8 *data, u32 totlen) } while (!exit); if (ret) - printk(KERN_INFO - "libertastf: firmware file format check failed\n"); + pr_err("firmware file format check FAIL\n"); + else + lbtf_deb_fw("firmware file format check PASS\n"); + return ret; } @@ -650,10 +809,12 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp) static int reset_count = 10; int ret = 0; + lbtf_deb_enter(LBTF_DEB_USB); + ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev); if (ret < 0) { - printk(KERN_INFO "libertastf: firmware %s not found\n", - lbtf_fw_name); + pr_err("request_firmware() failed with %#x\n", ret); + pr_err("firmware %s not found\n", lbtf_fw_name); goto done; } @@ -662,6 +823,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp) restart: if (if_usb_submit_rx_urb_fwload(cardp) < 0) { + lbtf_deb_usbd(&cardp->udev->dev, "URB submission is failed\n"); ret = -1; goto release_fw; } @@ -708,14 +870,13 @@ restart: usb_kill_urb(cardp->rx_urb); if (!cardp->fwdnldover) { - printk(KERN_INFO "libertastf: failed to load fw," - " resetting device!\n"); + pr_info("failed to load fw, resetting device!\n"); if (--reset_count >= 0) { if_usb_reset_device(cardp); goto restart; } - printk(KERN_INFO "libertastf: fw download failure\n"); + pr_info("FW download failure, time = %d ms\n", i * 100); ret = -1; goto release_fw; } @@ -729,6 +890,7 @@ restart: if_usb_setup_firmware(cardp->priv); done: + lbtf_deb_leave_args(LBTF_DEB_USB, "ret %d", ret); return ret; } EXPORT_SYMBOL_GPL(if_usb_prog_firmware); @@ -750,13 +912,19 @@ static int __init if_usb_init_module(void) { int ret = 0; + lbtf_deb_enter(LBTF_DEB_MAIN); + ret = usb_register(&if_usb_driver); + + lbtf_deb_leave_args(LBTF_DEB_MAIN, "ret %d", ret); return ret; } static void __exit if_usb_exit_module(void) { + lbtf_deb_enter(LBTF_DEB_MAIN); usb_deregister(&if_usb_driver); + lbtf_deb_leave(LBTF_DEB_MAIN); } module_init(if_usb_init_module); diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 6ab30033c26c..3b1db84addb5 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -7,6 +7,7 @@ * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. */ +#include "deb_defs.h" #include "libertas_tf.h" #include "linux/etherdevice.h" @@ -16,7 +17,17 @@ #define LBTF_FW_VER_MAX 0x0584ffff #define QOS_CONTROL_LEN 2 -static const char lbtf_driver_version[] = "THINFIRM-USB8388-" DRIVER_RELEASE_VERSION; +/* Module parameters */ +unsigned int lbtf_debug; +EXPORT_SYMBOL_GPL(lbtf_debug); +module_param_named(libertas_tf_debug, lbtf_debug, int, 0644); + +static const char lbtf_driver_version[] = "THINFIRM-USB8388-" DRIVER_RELEASE_VERSION +#ifdef DEBUG + "-dbg" +#endif + ""; + struct workqueue_struct *lbtf_wq; static const struct ieee80211_channel lbtf_channels[] = { @@ -79,6 +90,9 @@ static void lbtf_cmd_work(struct work_struct *work) { struct lbtf_private *priv = container_of(work, struct lbtf_private, cmd_work); + + lbtf_deb_enter(LBTF_DEB_CMD); + spin_lock_irq(&priv->driver_lock); /* command response? */ if (priv->cmd_response_rxed) { @@ -106,11 +120,16 @@ static void lbtf_cmd_work(struct work_struct *work) priv->cmd_timed_out = 0; spin_unlock_irq(&priv->driver_lock); - if (!priv->fw_ready) + if (!priv->fw_ready) { + lbtf_deb_leave_args(LBTF_DEB_CMD, "fw not ready"); return; + } + /* Execute the next command */ if (!priv->cur_cmd) lbtf_execute_next_command(priv); + + lbtf_deb_leave(LBTF_DEB_CMD); } /** @@ -124,6 +143,7 @@ static int lbtf_setup_firmware(struct lbtf_private *priv) { int ret = -1; + lbtf_deb_enter(LBTF_DEB_FW); /* * Read priv address from HW */ @@ -139,6 +159,7 @@ static int lbtf_setup_firmware(struct lbtf_private *priv) ret = 0; done: + lbtf_deb_leave_args(LBTF_DEB_FW, "ret: %d", ret); return ret; } @@ -150,6 +171,7 @@ static void command_timer_fn(unsigned long data) { struct lbtf_private *priv = (struct lbtf_private *)data; unsigned long flags; + lbtf_deb_enter(LBTF_DEB_CMD); spin_lock_irqsave(&priv->driver_lock, flags); @@ -166,10 +188,12 @@ static void command_timer_fn(unsigned long data) queue_work(lbtf_wq, &priv->cmd_work); out: spin_unlock_irqrestore(&priv->driver_lock, flags); + lbtf_deb_leave(LBTF_DEB_CMD); } static int lbtf_init_adapter(struct lbtf_private *priv) { + lbtf_deb_enter(LBTF_DEB_MAIN); memset(priv->current_addr, 0xff, ETH_ALEN); mutex_init(&priv->lock); @@ -186,13 +210,16 @@ static int lbtf_init_adapter(struct lbtf_private *priv) if (lbtf_allocate_cmd_buffer(priv)) return -1; + lbtf_deb_leave(LBTF_DEB_MAIN); return 0; } static void lbtf_free_adapter(struct lbtf_private *priv) { + lbtf_deb_enter(LBTF_DEB_MAIN); lbtf_free_cmd_buffer(priv); del_timer(&priv->command_timer); + lbtf_deb_leave(LBTF_DEB_MAIN); } static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) @@ -219,14 +246,18 @@ static void lbtf_tx_work(struct work_struct *work) struct sk_buff *skb = NULL; int err; + lbtf_deb_enter(LBTF_DEB_MACOPS | LBTF_DEB_TX); + if ((priv->vif->type == NL80211_IFTYPE_AP) && (!skb_queue_empty(&priv->bc_ps_buf))) skb = skb_dequeue(&priv->bc_ps_buf); else if (priv->skb_to_tx) { skb = priv->skb_to_tx; priv->skb_to_tx = NULL; - } else + } else { + lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX); return; + } len = skb->len; info = IEEE80211_SKB_CB(skb); @@ -234,6 +265,7 @@ static void lbtf_tx_work(struct work_struct *work) if (priv->surpriseremoved) { dev_kfree_skb_any(skb); + lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX); return; } @@ -247,6 +279,7 @@ static void lbtf_tx_work(struct work_struct *work) ETH_ALEN); txpd->tx_packet_length = cpu_to_le16(len); txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd)); + lbtf_deb_hex(LBTF_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100)); BUG_ON(priv->tx_skb); spin_lock_irq(&priv->driver_lock); priv->tx_skb = skb; @@ -255,7 +288,9 @@ static void lbtf_tx_work(struct work_struct *work) if (err) { dev_kfree_skb_any(skb); priv->tx_skb = NULL; + pr_err("TX error: %d", err); } + lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX); } static int lbtf_op_start(struct ieee80211_hw *hw) @@ -264,6 +299,8 @@ static int lbtf_op_start(struct ieee80211_hw *hw) void *card = priv->card; int ret = -1; + lbtf_deb_enter(LBTF_DEB_MACOPS); + if (!priv->fw_ready) /* Upload firmware */ if (priv->hw_prog_firmware(card)) @@ -284,10 +321,12 @@ static int lbtf_op_start(struct ieee80211_hw *hw) } printk(KERN_INFO "libertastf: Marvell WLAN 802.11 thinfirm adapter\n"); + lbtf_deb_leave(LBTF_DEB_MACOPS); return 0; err_prog_firmware: priv->hw_reset_device(card); + lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programing fw; ret=%d", ret); return ret; } @@ -298,6 +337,9 @@ static void lbtf_op_stop(struct ieee80211_hw *hw) struct sk_buff *skb; struct cmd_ctrl_node *cmdnode; + + lbtf_deb_enter(LBTF_DEB_MACOPS); + /* Flush pending command nodes */ spin_lock_irqsave(&priv->driver_lock, flags); list_for_each_entry(cmdnode, &priv->cmdpendingq, list) { @@ -314,6 +356,7 @@ static void lbtf_op_stop(struct ieee80211_hw *hw) priv->radioon = RADIO_OFF; lbtf_set_radio_control(priv); + lbtf_deb_leave(LBTF_DEB_MACOPS); return; } @@ -321,6 +364,7 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct lbtf_private *priv = hw->priv; + lbtf_deb_enter(LBTF_DEB_MACOPS); if (priv->vif != NULL) return -EOPNOTSUPP; @@ -338,6 +382,7 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw, return -EOPNOTSUPP; } lbtf_set_mac_address(priv, (u8 *) vif->addr); + lbtf_deb_leave(LBTF_DEB_MACOPS); return 0; } @@ -345,6 +390,7 @@ static void lbtf_op_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct lbtf_private *priv = hw->priv; + lbtf_deb_enter(LBTF_DEB_MACOPS); if (priv->vif->type == NL80211_IFTYPE_AP || priv->vif->type == NL80211_IFTYPE_MESH_POINT) @@ -352,17 +398,20 @@ static void lbtf_op_remove_interface(struct ieee80211_hw *hw, lbtf_set_mode(priv, LBTF_PASSIVE_MODE); lbtf_set_bssid(priv, 0, NULL); priv->vif = NULL; + lbtf_deb_leave(LBTF_DEB_MACOPS); } static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed) { struct lbtf_private *priv = hw->priv; struct ieee80211_conf *conf = &hw->conf; + lbtf_deb_enter(LBTF_DEB_MACOPS); if (conf->channel->center_freq != priv->cur_freq) { priv->cur_freq = conf->channel->center_freq; lbtf_set_channel(priv, conf->channel->hw_value); } + lbtf_deb_leave(LBTF_DEB_MACOPS); return 0; } @@ -395,11 +444,16 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw, { struct lbtf_private *priv = hw->priv; int old_mac_control = priv->mac_control; + + lbtf_deb_enter(LBTF_DEB_MACOPS); + changed_flags &= SUPPORTED_FIF_FLAGS; *new_flags &= SUPPORTED_FIF_FLAGS; - if (!changed_flags) + if (!changed_flags) { + lbtf_deb_leave(LBTF_DEB_MACOPS); return; + } if (*new_flags & (FIF_PROMISC_IN_BSS)) priv->mac_control |= CMD_ACT_MAC_PROMISCUOUS_ENABLE; @@ -425,6 +479,8 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw, if (priv->mac_control != old_mac_control) lbtf_set_mac_control(priv); + + lbtf_deb_leave(LBTF_DEB_MACOPS); } static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw, @@ -434,6 +490,7 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw, { struct lbtf_private *priv = hw->priv; struct sk_buff *beacon; + lbtf_deb_enter(LBTF_DEB_MACOPS); if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_INT)) { switch (priv->vif->type) { @@ -464,6 +521,8 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw, priv->preamble = CMD_TYPE_LONG_PREAMBLE; lbtf_set_radio_control(priv); } + + lbtf_deb_leave(LBTF_DEB_MACOPS); } static const struct ieee80211_ops lbtf_ops = { @@ -486,6 +545,8 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) unsigned int flags; struct ieee80211_hdr *hdr; + lbtf_deb_enter(LBTF_DEB_RX); + prxpd = (struct rxpd *) skb->data; stats.flag = 0; @@ -516,7 +577,15 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) } memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats)); + + lbtf_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n", + skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); + lbtf_deb_hex(LBTF_DEB_RX, "RX Data", skb->data, + min_t(unsigned int, skb->len, 100)); + ieee80211_rx_irqsafe(priv->hw, skb); + + lbtf_deb_leave(LBTF_DEB_RX); return 0; } EXPORT_SYMBOL_GPL(lbtf_rx); @@ -533,6 +602,8 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev) struct ieee80211_hw *hw; struct lbtf_private *priv = NULL; + lbtf_deb_enter(LBTF_DEB_MAIN); + hw = ieee80211_alloc_hw(sizeof(struct lbtf_private), &lbtf_ops); if (!hw) goto done; @@ -575,6 +646,7 @@ err_init_adapter: priv = NULL; done: + lbtf_deb_leave_args(LBTF_DEB_MAIN, "priv %p", priv); return priv; } EXPORT_SYMBOL_GPL(lbtf_add_card); @@ -584,6 +656,8 @@ int lbtf_remove_card(struct lbtf_private *priv) { struct ieee80211_hw *hw = priv->hw; + lbtf_deb_enter(LBTF_DEB_MAIN); + priv->surpriseremoved = 1; del_timer(&priv->command_timer); lbtf_free_adapter(priv); @@ -591,6 +665,7 @@ int lbtf_remove_card(struct lbtf_private *priv) ieee80211_unregister_hw(hw); ieee80211_free_hw(hw); + lbtf_deb_leave(LBTF_DEB_MAIN); return 0; } EXPORT_SYMBOL_GPL(lbtf_remove_card); @@ -649,17 +724,21 @@ EXPORT_SYMBOL_GPL(lbtf_bcn_sent); static int __init lbtf_init_module(void) { + lbtf_deb_enter(LBTF_DEB_MAIN); lbtf_wq = create_workqueue("libertastf"); if (lbtf_wq == NULL) { printk(KERN_ERR "libertastf: couldn't create workqueue\n"); return -ENOMEM; } + lbtf_deb_leave(LBTF_DEB_MAIN); return 0; } static void __exit lbtf_exit_module(void) { + lbtf_deb_enter(LBTF_DEB_MAIN); destroy_workqueue(lbtf_wq); + lbtf_deb_leave(LBTF_DEB_MAIN); } module_init(lbtf_init_module); -- cgit v1.2.3 From 5bf1e17a4a3870d4f03dc39f1bec4464bbdf4887 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 26 Apr 2010 15:09:36 +0530 Subject: ath9k_htc: Remove unnecessary powersave restore Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 9c9f3e0d6787..644776a51ac0 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -153,7 +153,6 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, ath_print(common, ATH_DBG_FATAL, "Unable to reset channel (%u Mhz) " "reset status %d\n", channel->center_freq, ret); - ath9k_htc_ps_restore(priv); goto err; } -- cgit v1.2.3 From d439260e04eca5bce88558feecee4369784f2175 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 26 Apr 2010 15:09:39 +0530 Subject: ath9k_htc: Validate TX Endpoint ID Check for the endpoint IDs when processing TX completions and drop the unsupported EPIDs. We can add other endpoints (UAPSD,..) when support is added. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 2c3c51007dd3..08bfe5d81c17 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -244,16 +244,25 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, enum htc_endpoint_id ep_id, bool txok) { struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; + struct ath_common *common = ath9k_hw_common(priv->ah); struct ieee80211_tx_info *tx_info; if (!skb) return; - if (ep_id == priv->mgmt_ep) + if (ep_id == priv->mgmt_ep) { skb_pull(skb, sizeof(struct tx_mgmt_hdr)); - else - /* TODO: Check for cab/uapsd/data */ + } else if ((ep_id == priv->data_bk_ep) || + (ep_id == priv->data_be_ep) || + (ep_id == priv->data_vi_ep) || + (ep_id == priv->data_vo_ep)) { skb_pull(skb, sizeof(struct tx_frame_hdr)); + } else { + ath_print(common, ATH_DBG_FATAL, + "Unsupported TX EPID: %d\n", ep_id); + dev_kfree_skb_any(skb); + return; + } tx_info = IEEE80211_SKB_CB(skb); -- cgit v1.2.3 From 4f824719a2729f1a6bb78de20c4d3b3dbdd81a09 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 26 Apr 2010 15:09:42 +0530 Subject: ath9k_htc: Simplify RX IRQ handler A bunch of validation and processing in the RX IRQ handler can be moved to the RX tasklet. The IRQ handler is already heavy, with the memory allocation for handling stream mode. Also, a memcpy of 40 bytes for every packet can be avoided in the handler. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 44 +++++++++++++-------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 08bfe5d81c17..28abc7d5e909 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -448,10 +448,32 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, struct ieee80211_hw *hw = priv->hw; struct sk_buff *skb = rxbuf->skb; struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath_htc_rx_status *rxstatus; int hdrlen, padpos, padsize; int last_rssi = ATH_RSSI_DUMMY_MARKER; __le16 fc; + if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) { + ath_print(common, ATH_DBG_FATAL, + "Corrupted RX frame, dropping\n"); + goto rx_next; + } + + rxstatus = (struct ath_htc_rx_status *)skb->data; + + if (be16_to_cpu(rxstatus->rs_datalen) - + (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) { + ath_print(common, ATH_DBG_FATAL, + "Corrupted RX data len, dropping " + "(dlen: %d, skblen: %d)\n", + rxstatus->rs_datalen, skb->len); + goto rx_next; + } + + /* Get the RX status information */ + memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); + skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); + hdr = (struct ieee80211_hdr *)skb->data; fc = hdr->frame_control; hdrlen = ieee80211_get_hdrlen_from_skb(skb); @@ -616,8 +638,6 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, struct ath_hw *ah = priv->ah; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; - struct ath_htc_rx_status *rxstatus; - u32 len = 0; spin_lock(&priv->rx.rxbuflock); list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) { @@ -634,27 +654,7 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, goto err; } - len = skb->len; - if (len <= HTC_RX_FRAME_HEADER_SIZE) { - ath_print(common, ATH_DBG_FATAL, - "Corrupted RX frame, dropping\n"); - goto err; - } - - rxstatus = (struct ath_htc_rx_status *)skb->data; - - if (be16_to_cpu(rxstatus->rs_datalen) - - (len - HTC_RX_FRAME_HEADER_SIZE) != 0) { - ath_print(common, ATH_DBG_FATAL, - "Corrupted RX data len, dropping " - "(epid: %d, dlen: %d, skblen: %d)\n", - ep_id, rxstatus->rs_datalen, len); - goto err; - } - spin_lock(&priv->rx.rxbuflock); - memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); - skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); rxbuf->skb = skb; rxbuf->in_process = true; spin_unlock(&priv->rx.rxbuflock); -- cgit v1.2.3 From 2fcb91317360d75efa3cbf4b200c9e7131c6b527 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 26 Apr 2010 15:04:29 -0400 Subject: ath9k_hw: update initvals for AR9003 This synchs up the initvals to the values used on the Atheros HAL for AR9003. This specific change adds support for a new high power module. Signed-off-by: Felix Fietkau Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_initvals.h | 265 +++++++++++------------ 1 file changed, 128 insertions(+), 137 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_initvals.h index e0391b12e533..a131cd10ef29 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_initvals.h @@ -31,7 +31,7 @@ static const u32 ar9300_2p0_radio_postamble[][5] = { static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050da, 0x000050da, 0x000050da, 0x000050da}, + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, @@ -545,7 +545,7 @@ static const u32 ar9300_2p0_soc_postamble[][5] = { }; static const u32 ar9200_merlin_2p0_radio_core[][2] = { - /* Addr common */ + /* Addr allmodes */ {0x00007800, 0x00040000}, {0x00007804, 0xdb005012}, {0x00007808, 0x04924914}, @@ -835,71 +835,71 @@ static const u32 ar9300_2p0_baseband_core[][2] = { static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050da, 0x000050da}, + {0x0000a410, 0x000050db, 0x000050db, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00020220, 0x00020220, 0x00000000, 0x00000000}, {0x0000a504, 0x06020223, 0x06020223, 0x04000002, 0x04000002}, - {0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10022223, 0x10022223, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x17022620, 0x17022620, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1b022622, 0x1b022622, 0x11000400, 0x11000400}, - {0x0000a518, 0x1f022822, 0x1f022822, 0x15000402, 0x15000402}, - {0x0000a51c, 0x24022842, 0x24022842, 0x19000404, 0x19000404}, - {0x0000a520, 0x28042840, 0x28042840, 0x1b000603, 0x1b000603}, - {0x0000a524, 0x2c042842, 0x2c042842, 0x1f000a02, 0x1f000a02}, - {0x0000a528, 0x30042844, 0x30042844, 0x23000a04, 0x23000a04}, - {0x0000a52c, 0x34042846, 0x34042846, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x39042869, 0x39042869, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x3d062869, 0x3d062869, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x44062c69, 0x44062c69, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x48063069, 0x48063069, 0x34001640, 0x34001640}, - {0x0000a540, 0x4c0a3065, 0x4c0a3065, 0x38001660, 0x38001660}, - {0x0000a544, 0x500a3069, 0x500a3069, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x530a3469, 0x530a3469, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x590a7464, 0x590a7464, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x5e0a7865, 0x5e0a7865, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x630a7e66, 0x630a7e66, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x680a7e89, 0x680a7e89, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x6e0a7e8c, 0x6e0a7e8c, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x730e7e8c, 0x730e7e8c, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, + {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, + {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, + {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x34043643, 0x34043643, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x38043a44, 0x38043a44, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x3b043e45, 0x3b043e45, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x40063e46, 0x40063e46, 0x34001640, 0x34001640}, + {0x0000a540, 0x44083e46, 0x44083e46, 0x38001660, 0x38001660}, + {0x0000a544, 0x46083e66, 0x46083e66, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x4b0a3e69, 0x4b0a3e69, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x4f0a5e66, 0x4f0a5e66, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x540a7e66, 0x540a7e66, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x570a7e89, 0x570a7e89, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x5c0e7e8a, 0x5c0e7e8a, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x60127e8b, 0x60127e8b, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x65127ecc, 0x65127ecc, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x6b169ecd, 0x6b169ecd, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x70169f0e, 0x70169f0e, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, {0x0000a580, 0x00820220, 0x00820220, 0x00800000, 0x00800000}, {0x0000a584, 0x06820223, 0x06820223, 0x04800002, 0x04800002}, - {0x0000a588, 0x0b822220, 0x0b822220, 0x08800004, 0x08800004}, - {0x0000a58c, 0x10822223, 0x10822223, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x17822620, 0x17822620, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1b822622, 0x1b822622, 0x11800400, 0x11800400}, - {0x0000a598, 0x1f822822, 0x1f822822, 0x15800402, 0x15800402}, - {0x0000a59c, 0x24822842, 0x24822842, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x28842840, 0x28842840, 0x1b800603, 0x1b800603}, - {0x0000a5a4, 0x2c842842, 0x2c842842, 0x1f800a02, 0x1f800a02}, - {0x0000a5a8, 0x30842844, 0x30842844, 0x23800a04, 0x23800a04}, - {0x0000a5ac, 0x34842846, 0x34842846, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x39842869, 0x39842869, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x3d862869, 0x3d862869, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x44862c69, 0x44862c69, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x48863069, 0x48863069, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x4c8a3065, 0x4c8a3065, 0x38801660, 0x38801660}, - {0x0000a5c4, 0x508a3069, 0x508a3069, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x538a3469, 0x538a3469, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x598a7464, 0x598a7464, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x5e8a7865, 0x5e8a7865, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x638a7e66, 0x638a7e66, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x688a7e89, 0x688a7e89, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x6e8a7e8c, 0x6e8a7e8c, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x738e7e8c, 0x738e7e8c, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004}, + {0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400}, + {0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402}, + {0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x34843643, 0x34843643, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x38843a44, 0x38843a44, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x3b843e45, 0x3b843e45, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x40863e46, 0x40863e46, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x4c8a3065, 0x44883e46, 0x44883e46, 0x38801660}, + {0x0000a5c4, 0x46883e66, 0x46883e66, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x4b8a3e69, 0x4b8a3e69, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x4f8a5e66, 0x4f8a5e66, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x548a7e66, 0x548a7e66, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x578a7e89, 0x578a7e89, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x5c8e7e8a, 0x5c8e7e8a, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x60927e8b, 0x60927e8b, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x65927ecc, 0x65927ecc, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x6b969ecd, 0x6b969ecd, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x70969f0e, 0x70969f0e, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, {0x00016048, 0xad241a61, 0xad241a61, 0xad241a61, 0xad241a61}, {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, @@ -913,71 +913,71 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050da, 0x000050da}, + {0x0000a410, 0x000050db, 0x000050db, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00020220, 0x00020220, 0x00000000, 0x00000000}, {0x0000a504, 0x06020223, 0x06020223, 0x04000002, 0x04000002}, - {0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10022223, 0x10022223, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x17022620, 0x17022620, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1b022622, 0x1b022622, 0x11000400, 0x11000400}, - {0x0000a518, 0x1f022822, 0x1f022822, 0x15000402, 0x15000402}, - {0x0000a51c, 0x24022842, 0x24022842, 0x19000404, 0x19000404}, - {0x0000a520, 0x28042840, 0x28042840, 0x1b000603, 0x1b000603}, - {0x0000a524, 0x2c042842, 0x2c042842, 0x1f000a02, 0x1f000a02}, - {0x0000a528, 0x30042844, 0x30042844, 0x23000a04, 0x23000a04}, - {0x0000a52c, 0x34042846, 0x34042846, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x39042869, 0x39042869, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x3d062869, 0x3d062869, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x44062c69, 0x44062c69, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x48063069, 0x48063069, 0x34001640, 0x34001640}, - {0x0000a540, 0x4c0a3065, 0x4c0a3065, 0x38001660, 0x38001660}, - {0x0000a544, 0x500a3069, 0x500a3069, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x530a3469, 0x530a3469, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x590a7464, 0x590a7464, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x5e0a7865, 0x5e0a7865, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x630a7e66, 0x630a7e66, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x680a7e89, 0x680a7e89, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x6e0a7e8c, 0x6e0a7e8c, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x730e7e8c, 0x730e7e8c, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec}, + {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, + {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, + {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, + {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x34043643, 0x34043643, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x38043a44, 0x38043a44, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x3b043e45, 0x3b043e45, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x40063e46, 0x40063e46, 0x34001640, 0x34001640}, + {0x0000a540, 0x44083e46, 0x44083e46, 0x38001660, 0x38001660}, + {0x0000a544, 0x46083e66, 0x46083e66, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x4b0a3e69, 0x4b0a3e69, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x4f0a5e66, 0x4f0a5e66, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x540a7e66, 0x540a7e66, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x570a7e89, 0x570a7e89, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x5c0e7e8a, 0x5c0e7e8a, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x60127e8b, 0x60127e8b, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x65127ecc, 0x65127ecc, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x6b169ecd, 0x6b169ecd, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x70169f0e, 0x70169f0e, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, {0x0000a580, 0x00820220, 0x00820220, 0x00800000, 0x00800000}, {0x0000a584, 0x06820223, 0x06820223, 0x04800002, 0x04800002}, - {0x0000a588, 0x0b822220, 0x0b822220, 0x08800004, 0x08800004}, - {0x0000a58c, 0x10822223, 0x10822223, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x17822620, 0x17822620, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1b822622, 0x1b822622, 0x11800400, 0x11800400}, - {0x0000a598, 0x1f822822, 0x1f822822, 0x15800402, 0x15800402}, - {0x0000a59c, 0x24822842, 0x24822842, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x28842840, 0x28842840, 0x1b800603, 0x1b800603}, - {0x0000a5a4, 0x2c842842, 0x2c842842, 0x1f800a02, 0x1f800a02}, - {0x0000a5a8, 0x30842844, 0x30842844, 0x23800a04, 0x23800a04}, - {0x0000a5ac, 0x34842846, 0x34842846, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x39842869, 0x39842869, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x3d862869, 0x3d862869, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x44862c69, 0x44862c69, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x48863069, 0x48863069, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x4c8a3065, 0x4c8a3065, 0x38801660, 0x38801660}, - {0x0000a5c4, 0x508a3069, 0x508a3069, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x538a3469, 0x538a3469, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x598a7464, 0x598a7464, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x5e8a7865, 0x5e8a7865, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x638a7e66, 0x638a7e66, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x688a7e89, 0x688a7e89, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x6e8a7e8c, 0x6e8a7e8c, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x738e7e8c, 0x738e7e8c, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec}, + {0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004}, + {0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400}, + {0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402}, + {0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x34843643, 0x34843643, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x38843a44, 0x38843a44, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x3b843e45, 0x3b843e45, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x40863e46, 0x40863e46, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x44883e46, 0x44883e46, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x46883e66, 0x46883e66, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x4b8a3e69, 0x4b8a3e69, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x4f8a5e66, 0x4f8a5e66, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x548a7e66, 0x548a7e66, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x578a7e89, 0x578a7e89, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x5c8e7e8a, 0x5c8e7e8a, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x60927e8b, 0x60927e8b, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x65927ecc, 0x65927ecc, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x6b969ecd, 0x6b969ecd, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x70969f0e, 0x70969f0e, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, {0x00016048, 0x8c001a61, 0x8c001a61, 0x8c001a61, 0x8c001a61}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, @@ -1251,7 +1251,7 @@ static const u32 ar9300Common_rx_gain_table_2p0[][2] = { static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050da, 0x000050da, 0x000050da, 0x000050da}, + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, @@ -1760,31 +1760,22 @@ static const u32 ar9300_2p0_soc_preamble[][2] = { {0x00007038, 0x000004c2}, }; -/* - * PCIE-PHY programming array, to be used prior to entering - * full sleep (holding RTC in reset, PLL is ON in L1 mode) - */ static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p0[][2] = { + /* Addr allmodes */ {0x00004040, 0x08212e5e}, {0x00004040, 0x0008003b}, {0x00004044, 0x00000000}, }; -/* - * PCIE-PHY programming array, to be used when not in - * full sleep (holding RTC in reset) - */ static const u32 ar9300PciePhy_clkreq_enable_L1_2p0[][2] = { + /* Addr allmodes */ {0x00004040, 0x08253e5e}, {0x00004040, 0x0008003b}, {0x00004044, 0x00000000}, }; -/* - * PCIE-PHY programming array, to be used prior to entering - * full sleep (holding RTC in reset) - */ static const u32 ar9300PciePhy_clkreq_disable_L1_2p0[][2] = { + /* Addr allmodes */ {0x00004040, 0x08213e5e}, {0x00004040, 0x0008003b}, {0x00004044, 0x00000000}, -- cgit v1.2.3 From 14bc110463bafc1aa4a51d4443e9dc1a88b58c40 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 26 Apr 2010 15:04:30 -0400 Subject: ath9k_hw: fix pll clock setting for 5ghz on AR9003 Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 137543b2d739..bf8ec687f9e0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -375,16 +375,7 @@ static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah, else if (chan && IS_CHAN_QUARTER_RATE(chan)) pll |= SM(0x2, AR_RTC_9300_PLL_CLKSEL); - if (chan && IS_CHAN_5GHZ(chan)) { - pll |= SM(0x28, AR_RTC_9300_PLL_DIV); - - /* - * When doing fast clock, set PLL to 0x142c - */ - if (IS_CHAN_A_5MHZ_SPACED(chan)) - pll = 0x142c; - } else - pll |= SM(0x2c, AR_RTC_9300_PLL_DIV); + pll |= SM(0x2c, AR_RTC_9300_PLL_DIV); return pll; } -- cgit v1.2.3 From 83937227657545f9e7aa9bfcb4429e81c9135f46 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 26 Apr 2010 15:04:31 -0400 Subject: ath9k_hw: fix typo in the AR9003 EEPROM data structure definition Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index 5fe335e22c89..d8c0318f416f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -265,7 +265,7 @@ struct cal_ctl_edge_pwr { } __packed; struct cal_ctl_data_2g { - struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_5G]; + struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_2G]; } __packed; struct cal_ctl_data_5g { -- cgit v1.2.3 From b360a884834a83ede845733cf344a29eb10dd2e3 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 26 Apr 2010 15:04:32 -0400 Subject: ath9k_hw: disable TX IQ calibration for AR9003 Disable TX IQ calibration, it was prematurely enabled in previous versions. Cc: Paul Shaw Cc: Thomas Hammel Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 3 ++- drivers/net/wireless/ath/ath9k/hw.c | 6 ++++++ drivers/net/wireless/ath/ath9k/hw.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 5e20b4860c7f..5fcafb460877 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -755,7 +755,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, } /* Do Tx IQ Calibration */ - ar9003_hw_tx_iq_cal(ah); + if (ah->config.tx_iq_calibration) + ar9003_hw_tx_iq_cal(ah); /* Revert chainmasks to their original values before NF cal */ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index b6d12e52d30e..40b6e8415946 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -385,6 +385,12 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.rx_intr_mitigation = true; + /* + * Tx IQ Calibration (ah->config.tx_iq_calibration) is only + * used by AR9003, but it is showing reliability issues. + * It will take a while to fix so this is currently disabled. + */ + /* * We need this for PCI devices only (Cardbus, PCI, miniPCI) * _and_ if on non-uniprocessor systems (Multiprocessor/HT). diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index a78e09bab431..6c84d318e31b 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -261,6 +261,7 @@ struct ath9k_ops_config { #define AR_BASE_FREQ_5GHZ 4900 #define AR_SPUR_FEEQ_BOUND_HT40 19 #define AR_SPUR_FEEQ_BOUND_HT20 10 + bool tx_iq_calibration; /* Only available for >= AR9003 */ int spurmode; u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; u8 max_txtrig_level; -- cgit v1.2.3 From e55537240f97635f9a7c42fac224ff80fa637624 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Mon, 26 Apr 2010 15:04:33 -0400 Subject: ath9k_hw: Fix usec to hw clock conversion in 5Ghz for ar9003 Fast clock operation (44Mhz) is enabled for 5Ghz in ar9003, so take care of the conversion from usec to hw clock. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 10 ++++++++-- drivers/net/wireless/ath/ath9k/hw.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 40b6e8415946..7bb700151ca6 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -25,6 +25,7 @@ #define ATH9K_CLOCK_RATE_CCK 22 #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 +#define ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM 44 static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); @@ -90,7 +91,11 @@ static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) return usecs *ATH9K_CLOCK_RATE_CCK; if (conf->channel->band == IEEE80211_BAND_2GHZ) return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM; - return usecs *ATH9K_CLOCK_RATE_5GHZ_OFDM; + + if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK) + return usecs * ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; + else + return usecs * ATH9K_CLOCK_RATE_5GHZ_OFDM; } static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) @@ -2188,7 +2193,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) } if (AR_SREV_9300_20_OR_LATER(ah)) { - pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_LDPC; + pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_LDPC | + ATH9K_HW_CAP_FASTCLOCK; pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH; pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH; pCap->rx_status_len = sizeof(struct ar9003_rxs); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 6c84d318e31b..7a1347b2453f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -198,6 +198,7 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_EDMA = BIT(17), ATH9K_HW_CAP_RAC_SUPPORTED = BIT(18), ATH9K_HW_CAP_LDPC = BIT(19), + ATH9K_HW_CAP_FASTCLOCK = BIT(20), }; enum ath9k_capability_type { -- cgit v1.2.3 From 5b75d0fca5b8cd2657fb240f2112e272a115b2f9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 26 Apr 2010 15:04:34 -0400 Subject: ath9k_hw: update EEPROM data structure for AR9280 Adds read access for the 5 GHz fast clock flag Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom.h | 3 ++- drivers/net/wireless/ath/ath9k/eeprom_def.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index fb9c8c92eabe..21354c15a9a9 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -300,7 +300,8 @@ struct base_eep_header { u32 binBuildNumber; u8 deviceType; u8 pwdclkind; - u8 futureBase_1[2]; + u8 fastClk5g; + u8 divChain; u8 rxGainType; u8 dacHiPwrMode_5G; u8 openLoopPwrCntl; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index cf59799ef307..e591ad6016e5 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -274,6 +274,8 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, return pBase->txMask; case EEP_RX_MASK: return pBase->rxMask; + case EEP_FSTCLK_5G: + return pBase->fastClk5g; case EEP_RXGAIN_TYPE: return pBase->rxGainType; case EEP_TXGAIN_TYPE: -- cgit v1.2.3 From 6b42e8d03bef975085c0397806d00fbd1df67eb8 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 26 Apr 2010 15:04:35 -0400 Subject: ath9k_hw: fix fast clock handling for 5GHz channels Combine multiple checks that were supposed to check for the same conditions, but didn't. Always enable fast PLL clock on AR9280 2.0 Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar5008_phy.c | 5 ++--- drivers/net/wireless/ath/ath9k/ar9002_phy.c | 16 ++++++---------- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 4 ++-- drivers/net/wireless/ath/ath9k/hw.c | 8 ++++++-- drivers/net/wireless/ath/ath9k/hw.h | 5 ++--- 5 files changed, 18 insertions(+), 20 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index de8ce1291a46..b2c17c98bb38 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -850,7 +850,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); - if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { + if (IS_CHAN_A_FAST_CLOCK(ah, chan)) { REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, regWrites); } @@ -892,8 +892,7 @@ static void ar5008_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan) rfMode |= (IS_CHAN_5GHZ(chan)) ? AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; - if ((AR_SREV_9280_20(ah) || AR_SREV_9300_20_OR_LATER(ah)) - && IS_CHAN_A_5MHZ_SPACED(chan)) + if (IS_CHAN_A_FAST_CLOCK(ah, chan)) rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); REG_WRITE(ah, AR_PHY_MODE, rfMode); diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 18cfe1a9781c..ed314e89bfe1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -455,16 +455,12 @@ static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah, pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); if (chan && IS_CHAN_5GHZ(chan)) { - pll |= SM(0x28, AR_RTC_9160_PLL_DIV); - - - if (AR_SREV_9280_20(ah)) { - if (((chan->channel % 20) == 0) - || ((chan->channel % 10) == 0)) - pll = 0x2850; - else - pll = 0x142c; - } + if (IS_CHAN_A_FAST_CLOCK(ah, chan)) + pll = 0x142c; + else if (AR_SREV_9280_20(ah)) + pll = 0x2850; + else + pll |= SM(0x28, AR_RTC_9160_PLL_DIV); } else { pll |= SM(0x2c, AR_RTC_9160_PLL_DIV); } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index bf8ec687f9e0..806f4a54b620 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -583,7 +583,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, * For 5GHz channels requiring Fast Clock, apply * different modal values. */ - if (IS_CHAN_A_5MHZ_SPACED(chan)) + if (IS_CHAN_A_FAST_CLOCK(ah, chan)) REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, regWrites); @@ -613,7 +613,7 @@ static void ar9003_hw_set_rfmode(struct ath_hw *ah, rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; - if (IS_CHAN_A_5MHZ_SPACED(chan)) + if (IS_CHAN_A_FAST_CLOCK(ah, chan)) rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); REG_WRITE(ah, AR_PHY_MODE, rfMode); diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 7bb700151ca6..8f37f1c2a380 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1228,8 +1228,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, (chan->channel != ah->curchan->channel) && ((chan->channelFlags & CHANNEL_ALL) == (ah->curchan->channelFlags & CHANNEL_ALL)) && - !(AR_SREV_9280(ah) || IS_CHAN_A_5MHZ_SPACED(chan) || - IS_CHAN_A_5MHZ_SPACED(ah->curchan))) { + !AR_SREV_9280(ah)) { if (ath9k_hw_channel_change(ah, chan)) { ath9k_hw_loadnf(ah, ah->curchan); @@ -2202,6 +2201,11 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->txs_len = sizeof(struct ar9003_txs); } else { pCap->tx_desc_len = sizeof(struct ath_desc); + if (AR_SREV_9280_20(ah) && + ((ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) <= + AR5416_EEP_MINOR_VER_16) || + ah->eep_ops->get_eeprom(ah, EEP_FSTCLK_5G))) + pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK; } if (AR_SREV_9300_20_OR_LATER(ah)) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7a1347b2453f..bc682da28b2a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -369,10 +369,9 @@ struct ath9k_channel { #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) #define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0) #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) -#define IS_CHAN_A_5MHZ_SPACED(_c) \ +#define IS_CHAN_A_FAST_CLOCK(_ah, _c) \ ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \ - (((_c)->channel % 20) != 0) && \ - (((_c)->channel % 10) != 0)) + ((_ah)->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)) /* These macros check chanmode and not channelFlags */ #define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B) -- cgit v1.2.3 From 7f9f3600695bf68d11cdcf278d39f02eaadc3a00 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 26 Apr 2010 15:04:36 -0400 Subject: ath9k: wake queue after processing edma rx frames Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index b0d345a675fe..3db19172b43b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2290,6 +2290,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) ath_tx_complete_buf(sc, bf, txq, &bf_head, &txs, txok, 0); + ath_wake_mac80211_queue(sc, txq); + spin_lock_bh(&txq->axq_lock); if (!list_empty(&txq->txq_fifo_pending)) { INIT_LIST_HEAD(&bf_head); -- cgit v1.2.3 From 597a94b340f98bf4596ef59e938875afaa1815d6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 26 Apr 2010 15:04:37 -0400 Subject: ath9k_hw: use the configured power limit for AR9003 Since the new AR9003 EEPROM code does tune the card for the configured tx power level, we need to fill in the correct power limits in the TPC part of the DMA descriptor. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 1 + drivers/net/wireless/ath/ath9k/ar9003_mac.c | 3 +++ drivers/net/wireless/ath/ath9k/hw.h | 1 + 3 files changed, 5 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 5d92be47c5a5..79b0e2874731 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -1817,6 +1817,7 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, u8 twiceMaxRegulatoryPower, u8 powerLimit) { + ah->txpower_limit = powerLimit; ar9003_hw_set_target_power_eeprom(ah, chan->channel); ar9003_hw_calibration_apply(ah, chan->channel); } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 7d111fbf8bc5..37ba37481a47 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -311,6 +311,9 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, { struct ar9003_txc *ads = (struct ar9003_txc *) ds; + if (txpower > ah->txpower_limit) + txpower = ah->txpower_limit; + txpower += ah->txpower_indexoffset; if (txpower > 63) txpower = 63; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index bc682da28b2a..77245dff5993 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -719,6 +719,7 @@ struct ath_hw { u32 *addac5416_21; u32 *bank6Temp; + u8 txpower_limit; int16_t txpower_indexoffset; int coverage_class; u32 beacon_interval; -- cgit v1.2.3 From d10baf99ffd1926c30401342779866ae7d73e2c4 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 26 Apr 2010 15:04:38 -0400 Subject: ath9k_hw: Fix typos in tx rate power level parsing for AR9003 Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 79b0e2874731..25dd44d54b72 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -1200,7 +1200,7 @@ static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah, u8 *pFreqBin; if (is2GHz) { - numPiers = AR9300_NUM_5G_20_TARGET_POWERS; + numPiers = AR9300_NUM_2G_20_TARGET_POWERS; pEepromTargetPwr = eep->calTargetPower2G; pFreqBin = eep->calTarget_freqbin_2G; } else { @@ -1236,7 +1236,7 @@ static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah, u8 *pFreqBin; if (is2GHz) { - numPiers = AR9300_NUM_5G_20_TARGET_POWERS; + numPiers = AR9300_NUM_2G_20_TARGET_POWERS; pEepromTargetPwr = eep->calTargetPower2GHT20; pFreqBin = eep->calTarget_freqbin_2GHT20; } else { -- cgit v1.2.3 From 0cf31079e98be01baffb22a2e3ad0cbc58420a41 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 26 Apr 2010 15:04:39 -0400 Subject: ath9k_hw: Fix endian bug in an AR9003 EEPROM field Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 25dd44d54b72..8a79550dff71 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -659,6 +659,9 @@ static void ar9300_swap_eeprom(struct ar9300_eeprom *eep) word = swab16(eep->baseEepHeader.regDmn[1]); eep->baseEepHeader.regDmn[1] = word; + dword = swab32(eep->baseEepHeader.swreg); + eep->baseEepHeader.swreg = dword; + dword = swab32(eep->modalHeader2G.antCtrlCommon); eep->modalHeader2G.antCtrlCommon = dword; -- cgit v1.2.3 From 5d5d44d914623b6122f050ec900ea4016aa3a993 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 26 Apr 2010 15:04:40 -0400 Subject: ath9k_hw: fix noisefloor timeout handling on AR9003 When the noisefloor calibration times out, do not load -50 into the registers, since this might cause rx issues. Instead, leave enough time for the noise floor calibration to complete until the next check. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 806f4a54b620..80431a2f6dc1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1093,6 +1093,7 @@ static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf " "to load: AR_PHY_AGC_CONTROL=0x%x\n", REG_READ(ah, AR_PHY_AGC_CONTROL)); + return; } /* -- cgit v1.2.3 From 5bea40069e46542f5691ec5771edc53e0ca58d71 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 26 Apr 2010 15:04:41 -0400 Subject: ath9k_hw: Fix TX interrupt mitigation settings TX interrupt mitigation reduces the number of interrupts by addressing several interrupt actions (AR_IMR_TXOK, AR_IMR_TXDESC) all in one interrupt so when enabling it discard setting the other interrupts. Without this TX interrupt mitigation would actually increase the number of interrupts two-fold. We still leave TX interrupt mitigation disabled as it is still being tested. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/mac.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 7bbf502563bc..0e425cb4bbb1 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -878,10 +878,12 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, if (ints & ATH9K_INT_TX) { if (ah->config.tx_intr_mitigation) mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM; - if (ah->txok_interrupt_mask) - mask |= AR_IMR_TXOK; - if (ah->txdesc_interrupt_mask) - mask |= AR_IMR_TXDESC; + else { + if (ah->txok_interrupt_mask) + mask |= AR_IMR_TXOK; + if (ah->txdesc_interrupt_mask) + mask |= AR_IMR_TXDESC; + } if (ah->txerr_interrupt_mask) mask |= AR_IMR_TXERR; if (ah->txeol_interrupt_mask) -- cgit v1.2.3 From 8a8572a821e5763525f5e4ac104bc28fd798fd5e Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 27 Apr 2010 13:05:37 +0530 Subject: ath9k_htc: Handle CONF_IDLE during unassociated state to save power. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_main.c | 71 ++++++++++++++++++++------- 2 files changed, 53 insertions(+), 19 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index b771e20075a5..1ae18bbc4d9e 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -379,6 +379,7 @@ struct ath9k_htc_priv { struct mutex htc_pm_lock; unsigned long ps_usecount; bool ps_enabled; + bool ps_idle; struct ath_led radio_led; struct ath_led assoc_led; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 644776a51ac0..ca7f3a78eb11 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -94,8 +94,11 @@ void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv) if (--priv->ps_usecount != 0) goto unlock; - if (priv->ps_enabled) + if (priv->ps_idle) + ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP); + else if (priv->ps_enabled) ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP); + unlock: mutex_unlock(&priv->htc_pm_lock); } @@ -1096,7 +1099,7 @@ fail_tx: return 0; } -static int ath9k_htc_start(struct ieee80211_hw *hw) +static int ath9k_htc_radio_enable(struct ieee80211_hw *hw) { struct ath9k_htc_priv *priv = hw->priv; struct ath_hw *ah = priv->ah; @@ -1112,8 +1115,6 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) "Starting driver with initial channel: %d MHz\n", curchan->center_freq); - mutex_lock(&priv->mutex); - /* setup initial channel */ init_channel = ath9k_cmn_get_curchannel(hw, ah); @@ -1126,7 +1127,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) ath_print(common, ATH_DBG_FATAL, "Unable to reset hardware; reset status %d " "(freq %u MHz)\n", ret, curchan->center_freq); - goto mutex_unlock; + return ret; } ath_update_txpow(priv); @@ -1134,16 +1135,8 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) mode = ath9k_htc_get_curmode(priv, init_channel); htc_mode = cpu_to_be16(mode); WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); - if (ret) - goto mutex_unlock; - WMI_CMD(WMI_ATH_INIT_CMDID); - if (ret) - goto mutex_unlock; - WMI_CMD(WMI_START_RECV_CMDID); - if (ret) - goto mutex_unlock; ath9k_host_rx_init(priv); @@ -1156,12 +1149,22 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) ieee80211_wake_queues(hw); -mutex_unlock: + return ret; +} + +static int ath9k_htc_start(struct ieee80211_hw *hw) +{ + struct ath9k_htc_priv *priv = hw->priv; + int ret = 0; + + mutex_lock(&priv->mutex); + ret = ath9k_htc_radio_enable(hw); mutex_unlock(&priv->mutex); + return ret; } -static void ath9k_htc_stop(struct ieee80211_hw *hw) +static void ath9k_htc_radio_disable(struct ieee80211_hw *hw) { struct ath9k_htc_priv *priv = hw->priv; struct ath_hw *ah = priv->ah; @@ -1169,11 +1172,8 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) int ret = 0; u8 cmd_rsp; - mutex_lock(&priv->mutex); - if (priv->op_flags & OP_INVALID) { ath_print(common, ATH_DBG_ANY, "Device not present\n"); - mutex_unlock(&priv->mutex); return; } @@ -1208,11 +1208,20 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) } priv->op_flags |= OP_INVALID; - mutex_unlock(&priv->mutex); ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); } +static void ath9k_htc_stop(struct ieee80211_hw *hw) +{ + struct ath9k_htc_priv *priv = hw->priv; + + mutex_lock(&priv->mutex); + ath9k_htc_radio_disable(hw); + mutex_unlock(&priv->mutex); +} + + static int ath9k_htc_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -1326,6 +1335,23 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&priv->mutex); + if (changed & IEEE80211_CONF_CHANGE_IDLE) { + bool enable_radio = false; + bool idle = !!(conf->flags & IEEE80211_CONF_IDLE); + + if (!idle && priv->ps_idle) + enable_radio = true; + + priv->ps_idle = idle; + + if (enable_radio) { + ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); + ath9k_htc_radio_enable(hw); + ath_print(common, ATH_DBG_CONFIG, + "not-idle: enabling radio\n"); + } + } + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { struct ieee80211_channel *curchan = hw->conf.channel; int pos = curchan->hw_value; @@ -1369,6 +1395,13 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) } } + if (priv->ps_idle) { + ath_print(common, ATH_DBG_CONFIG, + "idle: disabling radio\n"); + ath9k_htc_radio_disable(hw); + } + + mutex_unlock(&priv->mutex); return 0; -- cgit v1.2.3 From 3a37495268ab45507b4cab9d4cb18c5496ab7a10 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 27 Apr 2010 13:05:38 +0530 Subject: ath9k: Avoid corrupt frames being forwarded to mac80211. If bit 29 is set, MAC H/W can attempt to decrypt the received aggregate with WEP or TKIP, eventhough the received frame may be a CRC failed corrupted frame. If this bit is set, H/W obeys key type in keycache. If it is not set and if the key type in keycache is neither open nor AES, H/W forces key type to be open. But bit 29 should be set to 1 for AsyncFIFO feature to encrypt/decrypt the aggregate with WEP or TKIP. Cc: stable@kernel.org Reported-by: Johan Hovold Signed-off-by: Vivek Natarajan Signed-off-by: Ranga Rao Ravuri Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar5008_initvals.h | 2 +- drivers/net/wireless/ath/ath9k/ar9002_initvals.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h index cd953f6c4628..025c31ac6146 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h @@ -249,7 +249,7 @@ static const u32 ar5416Common[][2] = { { 0x00008258, 0x00000000 }, { 0x0000825c, 0x400000ff }, { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8000010 }, + { 0x00008264, 0x88000010 }, { 0x00008270, 0x00000000 }, { 0x00008274, 0x40000000 }, { 0x00008278, 0x003e4180 }, diff --git a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h index f06313d3bad6..dae7f3304eb8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h @@ -793,7 +793,7 @@ static const u32 ar9280Common_9280_2[][2] = { { 0x00008258, 0x00000000 }, { 0x0000825c, 0x400000ff }, { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8a00010 }, + { 0x00008264, 0x88a00010 }, { 0x00008270, 0x00000000 }, { 0x00008274, 0x40000000 }, { 0x00008278, 0x003e4180 }, @@ -1963,7 +1963,7 @@ static const u32 ar9285Common_9285[][2] = { { 0x00008258, 0x00000000 }, { 0x0000825c, 0x400000ff }, { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8a00010 }, + { 0x00008264, 0x88a00010 }, { 0x00008270, 0x00000000 }, { 0x00008274, 0x40000000 }, { 0x00008278, 0x003e4180 }, @@ -3185,7 +3185,7 @@ static const u32 ar9287Common_9287_1_0[][2] = { { 0x00008258, 0x00000000 }, { 0x0000825c, 0x400000ff }, { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8a00010 }, + { 0x00008264, 0x88a00010 }, { 0x00008270, 0x00000000 }, { 0x00008274, 0x40000000 }, { 0x00008278, 0x003e4180 }, @@ -4973,7 +4973,7 @@ static const u32 ar9271Common_9271[][2] = { { 0x00008258, 0x00000000 }, { 0x0000825c, 0x400000ff }, { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8a00010 }, + { 0x00008264, 0x88a00010 }, { 0x00008270, 0x00000000 }, { 0x00008274, 0x40000000 }, { 0x00008278, 0x003e4180 }, -- cgit v1.2.3 From a060bbfe4ee95d115e8f9705a66894ac34e2c475 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 27 Apr 2010 11:59:34 +0200 Subject: mac80211: give virtual interface to hw_scan When scanning, it is somewhat important to scan on the correct virtual interface. All drivers that currently implement hw_scan only support a single virtual interface, but that may change and then we'd want to be ready. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/at76c50x-usb.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.h | 4 +++- drivers/net/wireless/iwlwifi/iwl-scan.c | 3 ++- drivers/net/wireless/mac80211_hwsim.c | 1 + drivers/net/wireless/wl12xx/wl1251_main.c | 1 + drivers/net/wireless/wl12xx/wl1271_main.c | 1 + 6 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 0fb419936dff..7a626d4e100f 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -1889,6 +1889,7 @@ static void at76_dwork_hw_scan(struct work_struct *work) } static int at76_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct cfg80211_scan_request *req) { struct at76_priv *priv = hw->priv; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index a0cc11ecbe93..727360944859 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -512,7 +512,9 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) void iwl_init_scan_params(struct iwl_priv *priv); int iwl_scan_cancel(struct iwl_priv *priv); int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); -int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); +int iwl_mac_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_scan_request *req); void iwl_internal_short_hw_scan(struct iwl_priv *priv); int iwl_force_reset(struct iwl_priv *priv, int mode); u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 1bc1d29f2a07..447c3018296d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -312,7 +312,8 @@ static int iwl_scan_initiate(struct iwl_priv *priv) } int iwl_mac_hw_scan(struct ieee80211_hw *hw, - struct cfg80211_scan_request *req) + struct ieee80211_vif *vif, + struct cfg80211_scan_request *req) { struct iwl_priv *priv = hw->priv; int ret; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 79bb8833ddb9..d016933d7573 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -973,6 +973,7 @@ static void hw_scan_done(struct work_struct *work) } static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct cfg80211_scan_request *req) { struct hw_scan_done *hsd = kzalloc(sizeof(*hsd), GFP_KERNEL); diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 390cee7e61a1..4d3be80c220e 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -856,6 +856,7 @@ out: } static int wl1251_op_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct cfg80211_scan_request *req) { struct wl1251 *wl = hw->priv; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 283d5dade1ae..08ff6447dcd9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1523,6 +1523,7 @@ out: } static int wl1271_op_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct cfg80211_scan_request *req) { struct wl1271 *wl = hw->priv; -- cgit v1.2.3 From 3377d1b903e50d58a6aecf495092b6e1ffc0cd32 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 26 Apr 2010 16:09:16 -0400 Subject: mwl8k: remove usage of deprecated noise value Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 4e58ebe15580..9af6c9454605 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -749,7 +749,6 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, memset(status, 0, sizeof(*status)); status->signal = -rxd->rssi; - status->noise = -rxd->noise_floor; if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) { status->flag |= RX_FLAG_HT; @@ -851,7 +850,6 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status, memset(status, 0, sizeof(*status)); status->signal = -rxd->rssi; - status->noise = -rxd->noise_level; status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info); status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info); -- cgit v1.2.3 From 5d6566ff356a19fb6ad994717cb937ff88063fa6 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 26 Apr 2010 16:09:18 -0400 Subject: ar9170: remove usage of deprecated noise value Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index fed6695ec04e..cfc6a35a2c6a 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -926,7 +926,6 @@ static void ar9170_rx_phy_status(struct ar9170 *ar, /* TODO: we could do something with phy_errors */ status->signal = ar->noise[0] + phy->rssi_combined; - status->noise = ar->noise[0]; } static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len) -- cgit v1.2.3 From 54c7c91e659f657afa13315189965ecd8ba11d9d Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 26 Apr 2010 16:09:19 -0400 Subject: ath5k: remove usage of deprecated noise value Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index a49ede7b87b1..1f3e5b0986c7 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2029,8 +2029,7 @@ accept: rxs->freq = sc->curchan->center_freq; rxs->band = sc->curband->band; - rxs->noise = sc->ah->ah_noise_floor; - rxs->signal = rxs->noise + rs.rs_rssi; + rxs->signal = sc->ah->ah_noise_floor + rs.rs_rssi; rxs->antenna = rs.rs_antenna; -- cgit v1.2.3 From 32a0a33f198d1c0386a39285ea55564340d2d7d7 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 26 Apr 2010 16:09:21 -0400 Subject: ath9k: remove usage of deprecated noise value Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/common.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 09effdedc8c0..b4424a623cf5 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -212,7 +212,6 @@ int ath9k_cmn_rx_skb_preprocess(struct ath_common *common, rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp); rx_status->band = hw->conf.channel->band; rx_status->freq = hw->conf.channel->center_freq; - rx_status->noise = common->ani.noise_floor; rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; rx_status->antenna = rx_stats->rs_antenna; rx_status->flag |= RX_FLAG_TSFT; -- cgit v1.2.3 From 4a277dd8da28b615f4c683b993e01d71f2e3aaec Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 26 Apr 2010 16:09:22 -0400 Subject: b43: remove usage of deprecated noise value Signed-off-by: John W. Linville --- drivers/net/wireless/b43/xmit.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index eda06529ef5f..e6b0528f3b52 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -610,7 +610,6 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) } /* Link quality statistics */ - status.noise = dev->stats.link_noise; if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) { // s8 rssi = max(rxhdr->power0, rxhdr->power1); //TODO: Find out what the rssi value is (dBm or percentage?) -- cgit v1.2.3 From 83beaacc2a0441d13f2706105b5ffaf945f84594 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 26 Apr 2010 16:09:23 -0400 Subject: b43legacy: remove usage of deprecated noise value Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/xmit.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index 9c8882d9275e..7d177d97f1f7 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c @@ -548,7 +548,6 @@ void b43legacy_rx(struct b43legacy_wldev *dev, (phystat0 & B43legacy_RX_PHYST0_OFDM), (phystat0 & B43legacy_RX_PHYST0_GAINCTL), (phystat3 & B43legacy_RX_PHYST3_TRSTATE)); - status.noise = dev->stats.link_noise; /* change to support A PHY */ if (phystat0 & B43legacy_RX_PHYST0_OFDM) status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false); -- cgit v1.2.3 From 699622a7b5c91cadc08bd77a69711dfbca1df3b1 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 26 Apr 2010 16:09:25 -0400 Subject: libertas_tf: remove usage of deprecated noise value Signed-off-by: John W. Linville --- drivers/net/wireless/libertas_tf/main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 3b1db84addb5..a6b30d778f5c 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -555,7 +555,6 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) stats.freq = priv->cur_freq; stats.band = IEEE80211_BAND_2GHZ; stats.signal = prxpd->snr; - stats.noise = prxpd->nf; /* Marvell rate index has a hole at value 4 */ if (prxpd->rx_rate > 4) --prxpd->rx_rate; -- cgit v1.2.3 From 0cbb3b5e8e047fddabd4769fe497cb9f7e6f39b9 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 26 Apr 2010 16:09:26 -0400 Subject: p54: remove usage of deprecated noise value Signed-off-by: John W. Linville --- drivers/net/wireless/p54/txrx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 2ceff5480355..4e6891099d43 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -350,7 +350,6 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb) rx_status->flag |= RX_FLAG_MMIC_ERROR; rx_status->signal = p54_rssi_to_dbm(priv, hdr->rssi); - rx_status->noise = priv->noise; if (hdr->rate & 0x10) rx_status->flag |= RX_FLAG_SHORTPRE; if (priv->hw->conf.channel->band == IEEE80211_BAND_5GHZ) -- cgit v1.2.3 From 6ca4fed3d4ec9887208ea955861fecde4b7a02a1 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 26 Apr 2010 16:09:27 -0400 Subject: rt2x00: remove usage of deprecated noise value Signed-off-by: John W. Linville Acked-by: Gertjan van Wingerde --- drivers/net/wireless/rt2x00/rt2x00dev.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index b93731b79903..33c2f5fc9dd7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -434,7 +434,6 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, rx_status->mactime = rxdesc.timestamp; rx_status->rate_idx = rate_idx; rx_status->signal = rxdesc.rssi; - rx_status->noise = rxdesc.noise; rx_status->flag = rxdesc.flags; rx_status->antenna = rt2x00dev->link.ant.active.rx; -- cgit v1.2.3 From 446cfaa412beef0dd6cb0edf3b4eaed34d824537 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 26 Apr 2010 16:09:28 -0400 Subject: wl1251: remove usage of deprecated noise value Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_rx.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c index b56732226cc0..295203aff66e 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ b/drivers/net/wireless/wl12xx/wl1251_rx.c @@ -73,12 +73,6 @@ static void wl1251_rx_status(struct wl1251 *wl, status->signal = desc->rssi; - /* - * FIXME: guessing that snr needs to be divided by two, otherwise - * the values don't make any sense - */ - status->noise = desc->rssi - desc->snr / 2; - status->freq = ieee80211_channel_to_frequency(desc->channel); status->flag |= RX_FLAG_TSFT; -- cgit v1.2.3 From ca962557c2f2aa14f8032006ce17ebb4ff73db55 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 28 Apr 2010 12:37:46 -0700 Subject: libertas: fix 8686 firmware loading regression The 'ready' condition was incorrectly evaluated which sometimes lead to failures loading the second-stage firmware on 8686 devices. (This was introduced in "libertas: consolidate SDIO firmware wait code". -- JWL) Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_sdio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 68cc407054e3..094176e92ebe 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -323,7 +323,9 @@ static int if_sdio_wait_status(struct if_sdio_card *card, const u8 condition) timeout = jiffies + HZ; while (1) { status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); - if (ret || (status & condition)) + if (ret) + return ret; + if ((status & condition) == condition) break; if (time_after(jiffies, timeout)) return -ETIMEDOUT; -- cgit v1.2.3 From d10e2e02f5a4382ec97ec08e809469fcaae2f0f7 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 27 Apr 2010 16:57:38 -0400 Subject: rtl8180: use cached queue mapping for skb in rtl8180_tx Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8180_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 2b928ecf47bd..c406cc85878b 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -296,7 +296,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) entry->flags = cpu_to_le32(tx_flags); __skb_queue_tail(&ring->queue, skb); if (ring->entries - skb_queue_len(&ring->queue) < 2) - ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); + ieee80211_stop_queue(dev, prio); spin_unlock_irqrestore(&priv->lock, flags); rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); -- cgit v1.2.3 From 62dad5b0be39aa736fa35e63bf009ab2c574ef8c Mon Sep 17 00:00:00 2001 From: Benoit Papillault Date: Wed, 28 Apr 2010 00:08:24 +0200 Subject: ath9k: Added get_survey callback in order to get channel noise Signed-off-by: Benoit Papillault Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index aad370a7f95b..893b552981a0 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2044,6 +2044,25 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, return ret; } +static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_conf *conf = &hw->conf; + + if (idx != 0) + return -ENOENT; + + survey->channel = conf->channel; + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = common->ani.noise_floor; + + return 0; +} + static void ath9k_sw_scan_start(struct ieee80211_hw *hw) { struct ath_wiphy *aphy = hw->priv; @@ -2115,6 +2134,7 @@ struct ieee80211_ops ath9k_ops = { .set_tsf = ath9k_set_tsf, .reset_tsf = ath9k_reset_tsf, .ampdu_action = ath9k_ampdu_action, + .get_survey = ath9k_get_survey, .sw_scan_start = ath9k_sw_scan_start, .sw_scan_complete = ath9k_sw_scan_complete, .rfkill_poll = ath9k_rfkill_poll_state, -- cgit v1.2.3 From 16092b5cccd6f3a8d1957ca004c97947e07018db Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Wed, 28 Apr 2010 09:49:59 +0300 Subject: wl1271: Improve command polling In testing I noticed that the wl1271 commands fall into two categories. In the first category are "fast" commands, these mostly take only 0 or 1 polls to complete, but occasionally upto 50 (giving a 0.5ms execution time.) In the second category, the command completion takes well more than 0.5ms (from 1.5ms upwards.) This patch fixes command polling such that it is optimal for the fast commands, but also allows sleep for the longer ones. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index b19090334bc0..564526d81279 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -36,7 +36,7 @@ #include "wl1271_cmd.h" #include "wl1271_event.h" -#define WL1271_CMD_POLL_COUNT 5 +#define WL1271_CMD_FAST_POLL_COUNT 50 /* * send command to firmware @@ -76,11 +76,11 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, goto out; } - udelay(10); poll_count++; - if (poll_count == WL1271_CMD_POLL_COUNT) - wl1271_info("cmd polling took over %d cycles", - poll_count); + if (poll_count < WL1271_CMD_FAST_POLL_COUNT) + udelay(10); + else + msleep(1); intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); } -- cgit v1.2.3 From 141418c7ed22849449f39f8938c9cf0eae6c524f Mon Sep 17 00:00:00 2001 From: Saravanan Dhanabal Date: Wed, 28 Apr 2010 09:50:00 +0300 Subject: wl1271: Configure QOS nullfunc template for U-APSD When U-APSD is enabled, device is not sending power save state notifications to AP using QOS nullfunc frames. This patch configures nullfunc templates needed for U-APSD. Signed-off-by: Saravanan Dhanabal Reviewed-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 08ff6447dcd9..c160e5ad1e57 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1707,6 +1707,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (ret < 0) goto out_sleep; + ret = wl1271_build_qos_null_data(wl); + if (ret < 0) + goto out_sleep; + /* filter out all packets not from this BSSID */ wl1271_configure_filters(wl, 0); -- cgit v1.2.3 From 82429d32ca3bae9d67faa32ffbc989be2e63094f Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Wed, 28 Apr 2010 09:50:01 +0300 Subject: wl1271: Rewrite hardware keep-alive handling The driver had a join command without keep-alive restart procedures in the channel changing code. After associated scans, the mac80211 does re-set the current channel, causing the join to occur. This would stop the hardware keep alive. To make the joins safer in this respect, this patch adds a join function that does the hardware-keep-alive magic along the join. This is now invoked in the above mentioned scenario, and also other scenarios. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 91 ++++++++++++++++--------------- 1 file changed, 46 insertions(+), 45 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index c160e5ad1e57..a794d5ed8c60 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1117,14 +1117,13 @@ static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) } } -static int wl1271_join_channel(struct wl1271 *wl, int channel) +static int wl1271_dummy_join(struct wl1271 *wl) { int ret = 0; /* we need to use a dummy BSSID for now */ static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, 0xad, 0xbe, 0xef }; - wl->channel = channel; memcpy(wl->bssid, dummy_bssid, ETH_ALEN); /* pass through frames from all BSS */ @@ -1140,7 +1139,47 @@ out: return ret; } -static int wl1271_unjoin_channel(struct wl1271 *wl) +static int wl1271_join(struct wl1271 *wl) +{ + int ret; + + ret = wl1271_cmd_join(wl, wl->set_bss_type); + if (ret < 0) + goto out; + + set_bit(WL1271_FLAG_JOINED, &wl->flags); + + if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + goto out; + + /* + * The join command disable the keep-alive mode, shut down its process, + * and also clear the template config, so we need to reset it all after + * the join. The acx_aid starts the keep-alive process, and the order + * of the commands below is relevant. + */ + ret = wl1271_acx_keep_alive_mode(wl, true); + if (ret < 0) + goto out; + + ret = wl1271_acx_aid(wl, wl->aid); + if (ret < 0) + goto out; + + ret = wl1271_cmd_build_klv_null_data(wl); + if (ret < 0) + goto out; + + ret = wl1271_acx_keep_alive_config(wl, CMD_TEMPL_KLV_IDX_NULL_DATA, + ACX_KEEP_ALIVE_TPL_VALID); + if (ret < 0) + goto out; + +out: + return ret; +} + +static int wl1271_unjoin(struct wl1271 *wl) { int ret; @@ -1230,7 +1269,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) "failed %d", ret); if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { - ret = wl1271_cmd_join(wl, wl->set_bss_type); + ret = wl1271_join(wl); if (ret < 0) wl1271_warning("cmd join to update channel " "failed %d", ret); @@ -1240,9 +1279,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_IDLE) { if (conf->flags & IEEE80211_CONF_IDLE && test_bit(WL1271_FLAG_JOINED, &wl->flags)) - wl1271_unjoin_channel(wl); + wl1271_unjoin(wl); else if (!(conf->flags & IEEE80211_CONF_IDLE)) - wl1271_join_channel(wl, channel); + wl1271_dummy_join(wl); if (conf->flags & IEEE80211_CONF_IDLE) { wl->rate_set = wl1271_min_rate_get(wl); @@ -1612,7 +1651,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, enum wl1271_cmd_ps_mode mode; struct wl1271 *wl = hw->priv; bool do_join = false; - bool do_keepalive = false; int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); @@ -1755,19 +1793,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, ret = wl1271_cmd_build_probe_req(wl, NULL, 0, NULL, 0, wl->band); - /* Enable the keep-alive feature */ - ret = wl1271_acx_keep_alive_mode(wl, true); - if (ret < 0) - goto out_sleep; - - /* - * This is awkward. The keep-alive configs must be done - * *after* the join command, because otherwise it will - * not work, but it must only be done *once* because - * otherwise the firmware will start complaining. - */ - do_keepalive = true; - /* enable the connection monitoring feature */ ret = wl1271_acx_conn_monit_params(wl, true); if (ret < 0) @@ -1835,35 +1860,11 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } if (do_join) { - ret = wl1271_cmd_join(wl, wl->set_bss_type); + ret = wl1271_join(wl); if (ret < 0) { wl1271_warning("cmd join failed %d", ret); goto out_sleep; } - set_bit(WL1271_FLAG_JOINED, &wl->flags); - } - - /* - * The JOIN operation shuts down the firmware keep-alive as a side - * effect, and the ACX_AID will start the keep-alive as a side effect. - * Hence, for non-IBSS, the ACX_AID must always happen *after* the - * JOIN operation, and the template config after the ACX_AID. - */ - if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { - ret = wl1271_acx_aid(wl, wl->aid); - if (ret < 0) - goto out_sleep; - } - - if (do_keepalive) { - ret = wl1271_cmd_build_klv_null_data(wl); - if (ret < 0) - goto out_sleep; - ret = wl1271_acx_keep_alive_config( - wl, CMD_TEMPL_KLV_IDX_NULL_DATA, - ACX_KEEP_ALIVE_TPL_VALID); - if (ret < 0) - goto out_sleep; } out_sleep: -- cgit v1.2.3 From 23a7a51c5a35b30aa3edcc31a6a57b01c523b4cd Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Wed, 28 Apr 2010 09:50:02 +0300 Subject: wl1271: fix a bunch of sparse warnings A couple of sparse warnings in some rate settings (missing cpu_to_le32) were fixed. Changed the conf_sg_settings struct from le to native endianess. The values are converted to le when copying them to the acx command instead. Reported-by: Johannes Berg Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.c | 2 +- drivers/net/wireless/wl12xx/wl1271_boot.c | 8 ++++---- drivers/net/wireless/wl12xx/wl1271_cmd.c | 4 ++-- drivers/net/wireless/wl12xx/wl1271_conf.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 1a6b2ec1db58..4ed4036d6b68 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -589,7 +589,7 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) /* BT-WLAN coext parameters */ for (i = 0; i < CONF_SG_PARAMS_MAX; i++) - param->params[i] = c->params[i]; + param->params[i] = cpu_to_le32(c->params[i]); param->param_idx = CONF_SG_PARAMS_ALL; ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index f16d15bd5643..7e797157783e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -350,7 +350,7 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) static int wl1271_boot_run_firmware(struct wl1271 *wl) { int loop, ret; - u32 chip_id, interrupt; + u32 chip_id, intr; wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); @@ -367,15 +367,15 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) loop = 0; while (loop++ < INIT_LOOP) { udelay(INIT_LOOP_DELAY); - interrupt = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); + intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); - if (interrupt == 0xffffffff) { + if (intr == 0xffffffff) { wl1271_error("error reading hardware complete " "init indication"); return -EIO; } /* check that ACX_INTR_INIT_COMPLETE is enabled */ - else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) { + else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) { wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, WL1271_ACX_INTR_INIT_COMPLETE); break; diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 564526d81279..4292f8dc2a80 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -317,7 +317,7 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) join->rx_config_options = cpu_to_le32(wl->rx_config); join->rx_filter_options = cpu_to_le32(wl->rx_filter); join->bss_type = bss_type; - join->basic_rate_set = wl->basic_rate_set; + join->basic_rate_set = cpu_to_le32(wl->basic_rate_set); if (wl->band == IEEE80211_BAND_5GHZ) join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; @@ -614,7 +614,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, params->params.scan_options = cpu_to_le16(scan_options); params->params.num_probe_requests = probe_requests; - params->params.tx_rate = rate; + params->params.tx_rate = cpu_to_le32(rate); params->params.tid_trigger = 0; params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index c44307c4bcf8..d046d044b5bd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -401,7 +401,7 @@ enum { }; struct conf_sg_settings { - __le32 params[CONF_SG_PARAMS_MAX]; + u32 params[CONF_SG_PARAMS_MAX]; u8 state; }; -- cgit v1.2.3 From baff8006b58bb7fca5d1ea1825bc8c6486900303 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Wed, 28 Apr 2010 09:58:59 +0200 Subject: rt2x00: rt2800lib: update rfcsr & bbp init code for SoC devices Update the rfcsr and bbp init code for SoC devices to match with the latest Ralink driver. To have better control over which values are used for the register initialization create a new function rt2800_is_305x_soc which checks for SoC interface type, the correct RT chipset and the correct RF chipset. This is based on the assumption that all rt305x SoC devices use a rt2872 and rf3020/rf3021/rf3022. In case an unknown RF chipset is found on a SoC device with a rt2872 don't treat it as rt305x and just print a message. Signed-off-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 43 ++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 12a49e0c4ac5..674609d1a727 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -75,6 +75,23 @@ MODULE_LICENSE("GPL"); rt2800_regbusy_read((__dev), H2M_MAILBOX_CSR, \ H2M_MAILBOX_CSR_OWNER, (__reg)) +static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev) +{ + /* check for rt2872 on SoC */ + if (!rt2x00_is_soc(rt2x00dev) || + !rt2x00_rt(rt2x00dev, RT2872)) + return false; + + /* we know for sure that these rf chipsets are used on rt305x boards */ + if (rt2x00_rf(rt2x00dev, RF3020) || + rt2x00_rf(rt2x00dev, RF3021) || + rt2x00_rf(rt2x00dev, RF3022)) + return true; + + NOTICE(rt2x00dev, "Unknown RF chipset on rt305x\n"); + return false; +} + static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u8 value) { @@ -1555,6 +1572,9 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_wait_bbp_ready(rt2x00dev))) return -EACCES; + if (rt2800_is_305x_soc(rt2x00dev)) + rt2800_bbp_write(rt2x00dev, 31, 0x08); + rt2800_bbp_write(rt2x00dev, 65, 0x2c); rt2800_bbp_write(rt2x00dev, 66, 0x38); @@ -1575,6 +1595,9 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 79, 0x13); rt2800_bbp_write(rt2x00dev, 80, 0x05); rt2800_bbp_write(rt2x00dev, 81, 0x33); + } else if (rt2800_is_305x_soc(rt2x00dev)) { + rt2800_bbp_write(rt2x00dev, 78, 0x0e); + rt2800_bbp_write(rt2x00dev, 80, 0x08); } else { rt2800_bbp_write(rt2x00dev, 81, 0x37); } @@ -1595,12 +1618,16 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) || rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) || rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) || - rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E)) + rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) || + rt2800_is_305x_soc(rt2x00dev)) rt2800_bbp_write(rt2x00dev, 103, 0xc0); else rt2800_bbp_write(rt2x00dev, 103, 0x00); - rt2800_bbp_write(rt2x00dev, 105, 0x05); + if (rt2800_is_305x_soc(rt2x00dev)) + rt2800_bbp_write(rt2x00dev, 105, 0x01); + else + rt2800_bbp_write(rt2x00dev, 105, 0x05); rt2800_bbp_write(rt2x00dev, 106, 0x35); if (rt2x00_rt(rt2x00dev, RT3071) || @@ -1617,11 +1644,6 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 138, value); } - if (rt2x00_rt(rt2x00dev, RT2872)) { - rt2800_bbp_write(rt2x00dev, 31, 0x08); - rt2800_bbp_write(rt2x00dev, 78, 0x0e); - rt2800_bbp_write(rt2x00dev, 80, 0x08); - } for (i = 0; i < EEPROM_BBP_SIZE; i++) { rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); @@ -1708,7 +1730,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) !rt2x00_rt(rt2x00dev, RT3071) && !rt2x00_rt(rt2x00dev, RT3090) && !rt2x00_rt(rt2x00dev, RT3390) && - !(rt2x00_is_soc(rt2x00dev) && rt2x00_rt(rt2x00dev, RT2872))) + !rt2800_is_305x_soc(rt2x00dev)) return 0; /* @@ -1776,7 +1798,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 29, 0x8f); rt2800_rfcsr_write(rt2x00dev, 30, 0x20); rt2800_rfcsr_write(rt2x00dev, 31, 0x0f); - } else if (rt2x00_rt(rt2x00dev, RT2872)) { + } else if (rt2800_is_305x_soc(rt2x00dev)) { rt2800_rfcsr_write(rt2x00dev, 0, 0x50); rt2800_rfcsr_write(rt2x00dev, 1, 0x01); rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); @@ -1807,6 +1829,9 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 27, 0x23); rt2800_rfcsr_write(rt2x00dev, 28, 0x13); rt2800_rfcsr_write(rt2x00dev, 29, 0x83); + rt2800_rfcsr_write(rt2x00dev, 30, 0x00); + rt2800_rfcsr_write(rt2x00dev, 31, 0x00); + return 0; } if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { -- cgit v1.2.3 From f7f7cc47fce6f01c3d3374c51508859c328ad5b2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 28 Apr 2010 11:01:15 +0200 Subject: iwl: cleanup: remove unneeded error handling This is just a cleanup and doesn't change how the code works. debugfs_create_dir() and debugfs_create_file() return an error pointer (-ENODEV) if CONFIG_DEBUG_FS is not enabled, otherwise if an error occurs they return NULL. This is how they are implemented and what it says in the DebugFS documentation. DebugFS can not be compiled as a module. As a result, we only need to check for error pointers and particularly -ENODEV one time to know that DebugFS is enabled. This patch keeps the first check for error pointers and removes the rest. The other reason for this patch, is that it silences some Smatch warnings. Smatch sees the condition "(result != -ENODEV)" and assumes that it's possible for "result" to equal -ENODEV. If it were possible it would lead to an error pointer dereference. But since it's not, we can just remove the check. Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/debugfs.c | 63 ----------------------------- 1 file changed, 63 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c index 48930c1a0f76..c916152bb936 100644 --- a/drivers/net/wireless/iwmc3200wifi/debugfs.c +++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c @@ -442,40 +442,10 @@ int iwm_debugfs_init(struct iwm_priv *iwm) snprintf(devdir, sizeof(devdir), "%s", wiphy_name(iwm_to_wiphy(iwm))); iwm->dbg.devdir = debugfs_create_dir(devdir, iwm->dbg.rootdir); - result = PTR_ERR(iwm->dbg.devdir); - if (IS_ERR(iwm->dbg.devdir) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create devdir: %d\n", result); - goto error; - } - iwm->dbg.dbgdir = debugfs_create_dir("debug", iwm->dbg.devdir); - result = PTR_ERR(iwm->dbg.dbgdir); - if (IS_ERR(iwm->dbg.dbgdir) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create dbgdir: %d\n", result); - goto error; - } - iwm->dbg.rxdir = debugfs_create_dir("rx", iwm->dbg.devdir); - result = PTR_ERR(iwm->dbg.rxdir); - if (IS_ERR(iwm->dbg.rxdir) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create rx dir: %d\n", result); - goto error; - } - iwm->dbg.txdir = debugfs_create_dir("tx", iwm->dbg.devdir); - result = PTR_ERR(iwm->dbg.txdir); - if (IS_ERR(iwm->dbg.txdir) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create tx dir: %d\n", result); - goto error; - } - iwm->dbg.busdir = debugfs_create_dir("bus", iwm->dbg.devdir); - result = PTR_ERR(iwm->dbg.busdir); - if (IS_ERR(iwm->dbg.busdir) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create bus dir: %d\n", result); - goto error; - } - if (iwm->bus_ops->debugfs_init) { result = iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir); if (result < 0) { @@ -484,27 +454,15 @@ int iwm_debugfs_init(struct iwm_priv *iwm) } } - iwm->dbg.dbg_level = IWM_DL_NONE; iwm->dbg.dbg_level_dentry = debugfs_create_file("level", 0200, iwm->dbg.dbgdir, iwm, &fops_iwm_dbg_level); - result = PTR_ERR(iwm->dbg.dbg_level_dentry); - if (IS_ERR(iwm->dbg.dbg_level_dentry) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create dbg_level: %d\n", result); - goto error; - } - iwm->dbg.dbg_modules = IWM_DM_DEFAULT; iwm->dbg.dbg_modules_dentry = debugfs_create_file("modules", 0200, iwm->dbg.dbgdir, iwm, &fops_iwm_dbg_modules); - result = PTR_ERR(iwm->dbg.dbg_modules_dentry); - if (IS_ERR(iwm->dbg.dbg_modules_dentry) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create dbg_modules: %d\n", result); - goto error; - } for (i = 0; i < __IWM_DM_NR; i++) add_dbg_module(iwm->dbg, iwm_debug_module[i].name, @@ -513,39 +471,18 @@ int iwm_debugfs_init(struct iwm_priv *iwm) iwm->dbg.txq_dentry = debugfs_create_file("queues", 0200, iwm->dbg.txdir, iwm, &iwm_debugfs_txq_fops); - result = PTR_ERR(iwm->dbg.txq_dentry); - if (IS_ERR(iwm->dbg.txq_dentry) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create tx queue: %d\n", result); - goto error; - } iwm->dbg.tx_credit_dentry = debugfs_create_file("credits", 0200, iwm->dbg.txdir, iwm, &iwm_debugfs_tx_credit_fops); - result = PTR_ERR(iwm->dbg.tx_credit_dentry); - if (IS_ERR(iwm->dbg.tx_credit_dentry) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create tx credit: %d\n", result); - goto error; - } iwm->dbg.rx_ticket_dentry = debugfs_create_file("tickets", 0200, iwm->dbg.rxdir, iwm, &iwm_debugfs_rx_ticket_fops); - result = PTR_ERR(iwm->dbg.rx_ticket_dentry); - if (IS_ERR(iwm->dbg.rx_ticket_dentry) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create rx ticket: %d\n", result); - goto error; - } iwm->dbg.fw_err_dentry = debugfs_create_file("last_fw_err", 0200, iwm->dbg.dbgdir, iwm, &iwm_debugfs_fw_err_fops); - result = PTR_ERR(iwm->dbg.fw_err_dentry); - if (IS_ERR(iwm->dbg.fw_err_dentry) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create last FW err: %d\n", result); - goto error; - } - return 0; -- cgit v1.2.3 From 28b4c3bf1c4aa306fc5189fc7d556aa780c68e98 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 28 Apr 2010 14:23:15 -0700 Subject: wireless: Fix merge. in your merge in 5c01d5669356e13f0fb468944c1dd4c6a7e978ad you added "int i;" into wl1271_main.c which is unused in that function. This patch fixes the merge problem: Signed-off-by: Hauke Mehrtens Signed-off-by: David S. Miller --- drivers/net/wireless/wl12xx/wl1271_main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 814f300c3f17..e47a58d2cc19 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1311,7 +1311,6 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, struct wl1271_filter_params *fp; struct netdev_hw_addr *ha; struct wl1271 *wl = hw->priv; - int i; if (unlikely(wl->state == WL1271_STATE_OFF)) return 0; -- cgit v1.2.3 From d989ff7cf8d14f1b523f63ba0bf2ec1a9b7c25bc Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 28 Apr 2010 19:14:42 -0400 Subject: rtl8180: fix tx status reporting When reporting Tx status, indicate that only one rate was used. Otherwise, the rate is frozen at rate index 0 (i.e. 1Mb/s). Signed-off-by: John W. Linville Cc: stable@kernel.org --- drivers/net/wireless/rtl818x/rtl8180_dev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index c406cc85878b..4907fef011ad 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -187,6 +187,7 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) info->flags |= IEEE80211_TX_STAT_ACK; info->status.rates[0].count = (flags & 0xFF) + 1; + info->status.rates[1].idx = -1; ieee80211_tx_status_irqsafe(dev, skb); if (ring->entries - skb_queue_len(&ring->queue) == 2) -- cgit v1.2.3 From edfcba15bdfa520d8c64b496c9260a9d9e0b6d18 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 28 Apr 2010 16:12:57 -0400 Subject: libertas_tf: avoid warning about pr_fmt redefinition Also includes a minor cleanup regarding quotation of a standard kernel header file... Signed-off-by: John W. Linville --- drivers/net/wireless/libertas_tf/cmd.c | 3 ++- drivers/net/wireless/libertas_tf/deb_defs.h | 2 -- drivers/net/wireless/libertas_tf/if_usb.c | 3 ++- drivers/net/wireless/libertas_tf/libertas_tf.h | 2 ++ drivers/net/wireless/libertas_tf/main.c | 5 +++-- 5 files changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c index 22645e4028de..eb85019c1081 100644 --- a/drivers/net/wireless/libertas_tf/cmd.c +++ b/drivers/net/wireless/libertas_tf/cmd.c @@ -7,7 +7,8 @@ * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. */ -#include "deb_defs.h" +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "libertas_tf.h" static const struct channel_range channel_ranges[] = { diff --git a/drivers/net/wireless/libertas_tf/deb_defs.h b/drivers/net/wireless/libertas_tf/deb_defs.h index 9a3e92bec5fd..ae753962d8b5 100644 --- a/drivers/net/wireless/libertas_tf/deb_defs.h +++ b/drivers/net/wireless/libertas_tf/deb_defs.h @@ -9,8 +9,6 @@ #define DRV_NAME "libertas_tf" #endif -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #ifdef CONFIG_LIBERTAS_THINFIRM_DEBUG diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index 919451a2ee4a..827b7dc306b0 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c @@ -9,7 +9,8 @@ */ #define DRV_NAME "lbtf_usb" -#include "deb_defs.h" +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "libertas_tf.h" #include "if_usb.h" diff --git a/drivers/net/wireless/libertas_tf/libertas_tf.h b/drivers/net/wireless/libertas_tf/libertas_tf.h index 4cc42dd5a005..fbbaaae7a1ae 100644 --- a/drivers/net/wireless/libertas_tf/libertas_tf.h +++ b/drivers/net/wireless/libertas_tf/libertas_tf.h @@ -13,6 +13,8 @@ #include #include +#include "deb_defs.h" + #ifndef DRV_NAME #define DRV_NAME "libertas_tf" #endif diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index a6b30d778f5c..895b557d664e 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -7,9 +7,10 @@ * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. */ -#include "deb_defs.h" +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include #include "libertas_tf.h" -#include "linux/etherdevice.h" #define DRIVER_RELEASE_VERSION "004.p0" /* thinfirm version: 5.132.X.pX */ -- cgit v1.2.3 From f5c044e53a6b319776c7140b22fee9be3bc1f758 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 30 Apr 2010 15:37:00 -0400 Subject: mac80211: remove deprecated noise field from ieee80211_rx_status Also remove associated IEEE80211_HW_NOISE_DBM from ieee80211_hw_flags. Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/main.c | 3 +-- drivers/net/wireless/ath/ath5k/base.c | 3 +-- drivers/net/wireless/b43/main.c | 3 +-- drivers/net/wireless/b43legacy/main.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 - drivers/net/wireless/mwl8k.c | 4 ++-- drivers/net/wireless/p54/main.c | 3 +-- drivers/net/wireless/wl12xx/wl1251_main.c | 1 - drivers/net/wireless/wl12xx/wl1271_main.c | 1 - 10 files changed, 7 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index cfc6a35a2c6a..dfcc055a827f 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -2550,8 +2550,7 @@ void *ar9170_alloc(size_t priv_size) BIT(NL80211_IFTYPE_ADHOC); ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; + IEEE80211_HW_SIGNAL_DBM; if (modparam_ht) { ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 1f3e5b0986c7..feb7b9ea80ab 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -547,8 +547,7 @@ ath5k_pci_probe(struct pci_dev *pdev, SET_IEEE80211_DEV(hw, &pdev->dev); hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; + IEEE80211_HW_SIGNAL_DBM; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 14cf3bd7ea51..e0575591828c 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4904,8 +4904,7 @@ static int b43_wireless_init(struct ssb_device *dev) /* fill hw info */ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; + IEEE80211_HW_SIGNAL_DBM; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 1d070be5a678..b2df432d3c63 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3768,8 +3768,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev) /* fill hw info */ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; + IEEE80211_HW_SIGNAL_DBM; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c22d3d8c440c..0cd338631592 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2653,7 +2653,6 @@ static int iwl_mac_setup_register(struct iwl_priv *priv) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_SPECTRUM_MGMT; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index e7263ed693c4..c9da39d7c414 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3872,7 +3872,6 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM | IEEE80211_HW_SPECTRUM_MGMT; if (!priv->cfg->broken_powersave) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 9af6c9454605..a90bb6d2e26b 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3981,8 +3981,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, hw->queues = MWL8K_TX_QUEUES; - /* Set rssi and noise values to dBm */ - hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + /* Set rssi values to dBm */ + hw->flags |= IEEE80211_HW_SIGNAL_DBM; hw->vif_data_size = sizeof(struct mwl8k_vif); hw->sta_data_size = sizeof(struct mwl8k_sta); diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 36f4c820ad01..10a4b16f31ce 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -545,8 +545,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_BEACON_FILTER | - IEEE80211_HW_REPORTS_TX_ACK_STATUS | - IEEE80211_HW_NOISE_DBM; + IEEE80211_HW_REPORTS_TX_ACK_STATUS; dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 4d3be80c220e..b70621f63cda 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -1291,7 +1291,6 @@ int wl1251_init_ieee80211(struct wl1251 *wl) wl->hw->channel_change_time = 10000; wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_SUPPORTS_UAPSD; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index a794d5ed8c60..b0837255de6f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -2275,7 +2275,6 @@ int wl1271_init_ieee80211(struct wl1271 *wl) wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval; wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM | IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_UAPSD | -- cgit v1.2.3 From 399dcb8a36edbde45bc27f5e33fd7f57de44bdd5 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 13 Apr 2010 11:28:52 -0700 Subject: iwlwifi: remove get_stats callback function The low level transmission function is performed at uCode layer for all the "agn" NICs, there is no statistics information available for mac80211 get_stats() call. Remove the callback function to avoid misleading information that returned success when indeed it is not supported. Now return "not supported". Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c22d3d8c440c..04d84a68363d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3001,18 +3001,6 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return 0; } -static int iwl_mac_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct iwl_priv *priv = hw->priv; - - priv = hw->priv; - IWL_DEBUG_MAC80211(priv, "enter\n"); - IWL_DEBUG_MAC80211(priv, "leave\n"); - - return 0; -} - static void iwl_mac_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd cmd, @@ -3390,7 +3378,6 @@ static struct ieee80211_ops iwl_hw_ops = { .configure_filter = iwl_configure_filter, .set_key = iwl_mac_set_key, .update_tkip_key = iwl_mac_update_tkip_key, - .get_stats = iwl_mac_get_stats, .conf_tx = iwl_mac_conf_tx, .reset_tsf = iwl_mac_reset_tsf, .bss_info_changed = iwl_bss_info_changed, -- cgit v1.2.3 From f001b300493287a19ebd88fbca56978dabfec55a Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 13 Apr 2010 20:50:16 -0700 Subject: iwlwifi: remove outdated comments IEEE80211_CONF_SHORT_SLOT_TIME is no longer a possible setting in ieee80211_conf->flags Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 457dc196ffdc..1cbc22a180a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2116,10 +2116,6 @@ EXPORT_SYMBOL(iwl_mac_remove_interface); /** * iwl_mac_config - mac80211 config callback - * - * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to - * be set inappropriately and the driver currently sets the hardware up to - * use it whenever needed. */ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) { -- cgit v1.2.3 From cd398c313785cb5f2b8cb2c85e865f06419b1730 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 14 Apr 2010 10:27:00 -0700 Subject: iwlwifi: reset pci retry timeout We removed resetting of PCI_RETRY_TIMEOUT register in merge of suspend resume work. 'Suspend and resume' resets the PCI configuration space, so we have to disable the RETRY_TIMEOUT register again here. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 1cbc22a180a7..1e11706dcf63 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2930,6 +2930,12 @@ int iwl_pci_resume(struct pci_dev *pdev) struct iwl_priv *priv = pci_get_drvdata(pdev); int ret; + /* + * We disable the RETRY_TIMEOUT register (0x41) to keep + * PCI Tx retries from interfering with C3 CPU state. + */ + pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); + pci_set_power_state(pdev, PCI_D0); ret = pci_enable_device(pdev); if (ret) -- cgit v1.2.3 From c2845d010b0e58a17cd2301e657b614962331550 Mon Sep 17 00:00:00 2001 From: Shanyu Zhao Date: Wed, 14 Apr 2010 15:35:14 -0700 Subject: iwlwifi: set correct AC to swq_id for aggregation When starting an aggregation session, the swq_id is generated in function iwl_virtual_agg_queue_num() where the first parameter is supposed to be the Access Class, but it used the tx fifo ID instead. This means the AC value stored in swq_id is incorrect. To test this, look at the tx_queue file in debugfs while transmitting Best Effort flow (ac=2), it shows: hwq 10: read=0 write=0 stop=0 swq_id=0xa9 (ac 1/hwq 10) After this fix, it will show: hwq 10: read=0 write=0 stop=0 swq_id=0xaa (ac 2/hwq 10) Signed-off-by: Shanyu Zhao Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 11661fa28f21..95e263f1d117 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -83,6 +83,15 @@ static inline int get_fifo_from_ac(u8 ac) return ac_to_fifo[ac]; } +static inline int get_ac_from_tid(u16 tid) +{ + if (likely(tid < ARRAY_SIZE(tid_to_ac))) + return tid_to_ac[tid]; + + /* no support for TIDs 8-15 yet */ + return -EINVAL; +} + static inline int get_fifo_from_tid(u16 tid) { if (likely(tid < ARRAY_SIZE(tid_to_ac))) @@ -991,7 +1000,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) tid_data = &priv->stations[sta_id].tid[tid]; *ssn = SEQ_TO_SN(tid_data->seq_number); tid_data->agg.txq_id = txq_id; - priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(tx_fifo, txq_id); + priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(get_ac_from_tid(tid), txq_id); spin_unlock_irqrestore(&priv->sta_lock, flags); ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, -- cgit v1.2.3 From 17f36fc6ef3d1ab15f9d2160a9daa107db0887ca Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 16 Apr 2010 10:03:54 -0700 Subject: iwl3945: add ucode statistics Add general, rx and tx uCode statistics to 3945. This will help in debugging Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/Makefile | 1 + drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c | 500 ++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h | 60 +++ drivers/net/wireless/iwlwifi/iwl-3945.c | 72 +++- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 18 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 5 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 8 files changed, 646 insertions(+), 14 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c create mode 100644 drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 5ed2dcbe6d01..7c7235385513 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -22,5 +22,6 @@ iwlagn-$(CONFIG_IWL5000) += iwl-1000.o # 3945 obj-$(CONFIG_IWL3945) += iwl3945.o iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o +iwl3945-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-3945-debugfs.o ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c new file mode 100644 index 000000000000..6a9c64a50e36 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c @@ -0,0 +1,500 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + +#include "iwl-3945-debugfs.h" + +ssize_t iwl3945_ucode_rx_stats_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + int pos = 0; + char *buf; + int bufsz = sizeof(struct iwl39_statistics_rx_phy) * 40 + + sizeof(struct iwl39_statistics_rx_non_phy) * 40 + 400; + ssize_t ret; + struct iwl39_statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; + struct iwl39_statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; + struct iwl39_statistics_rx_non_phy *general, *accum_general; + struct iwl39_statistics_rx_non_phy *delta_general, *max_general; + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + /* + * The statistic information display here is based on + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + ofdm = &priv->_3945.statistics.rx.ofdm; + cck = &priv->_3945.statistics.rx.cck; + general = &priv->_3945.statistics.rx.general; + accum_ofdm = &priv->_3945.accum_statistics.rx.ofdm; + accum_cck = &priv->_3945.accum_statistics.rx.cck; + accum_general = &priv->_3945.accum_statistics.rx.general; + delta_ofdm = &priv->_3945.delta_statistics.rx.ofdm; + delta_cck = &priv->_3945.delta_statistics.rx.cck; + delta_general = &priv->_3945.delta_statistics.rx.general; + max_ofdm = &priv->_3945.max_delta.rx.ofdm; + max_cck = &priv->_3945.max_delta.rx.cck; + max_general = &priv->_3945.max_delta.rx.general; + + pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); + pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" + "acumulative delta max\n", + "Statistics_Rx - OFDM:"); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "ina_cnt:", le32_to_cpu(ofdm->ina_cnt), + accum_ofdm->ina_cnt, + delta_ofdm->ina_cnt, max_ofdm->ina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "fina_cnt:", + le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, + delta_ofdm->fina_cnt, max_ofdm->fina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "plcp_err:", + le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, + delta_ofdm->plcp_err, max_ofdm->plcp_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "crc32_err:", + le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, + delta_ofdm->crc32_err, max_ofdm->crc32_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "overrun_err:", + le32_to_cpu(ofdm->overrun_err), + accum_ofdm->overrun_err, delta_ofdm->overrun_err, + max_ofdm->overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "early_overrun_err:", + le32_to_cpu(ofdm->early_overrun_err), + accum_ofdm->early_overrun_err, + delta_ofdm->early_overrun_err, + max_ofdm->early_overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "crc32_good:", le32_to_cpu(ofdm->crc32_good), + accum_ofdm->crc32_good, delta_ofdm->crc32_good, + max_ofdm->crc32_good); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "false_alarm_cnt:", + le32_to_cpu(ofdm->false_alarm_cnt), + accum_ofdm->false_alarm_cnt, + delta_ofdm->false_alarm_cnt, + max_ofdm->false_alarm_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "fina_sync_err_cnt:", + le32_to_cpu(ofdm->fina_sync_err_cnt), + accum_ofdm->fina_sync_err_cnt, + delta_ofdm->fina_sync_err_cnt, + max_ofdm->fina_sync_err_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "sfd_timeout:", + le32_to_cpu(ofdm->sfd_timeout), + accum_ofdm->sfd_timeout, + delta_ofdm->sfd_timeout, + max_ofdm->sfd_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "fina_timeout:", + le32_to_cpu(ofdm->fina_timeout), + accum_ofdm->fina_timeout, + delta_ofdm->fina_timeout, + max_ofdm->fina_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "unresponded_rts:", + le32_to_cpu(ofdm->unresponded_rts), + accum_ofdm->unresponded_rts, + delta_ofdm->unresponded_rts, + max_ofdm->unresponded_rts); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "rxe_frame_lmt_ovrun:", + le32_to_cpu(ofdm->rxe_frame_limit_overrun), + accum_ofdm->rxe_frame_limit_overrun, + delta_ofdm->rxe_frame_limit_overrun, + max_ofdm->rxe_frame_limit_overrun); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "sent_ack_cnt:", + le32_to_cpu(ofdm->sent_ack_cnt), + accum_ofdm->sent_ack_cnt, + delta_ofdm->sent_ack_cnt, + max_ofdm->sent_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "sent_cts_cnt:", + le32_to_cpu(ofdm->sent_cts_cnt), + accum_ofdm->sent_cts_cnt, + delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt); + + pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" + "acumulative delta max\n", + "Statistics_Rx - CCK:"); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "ina_cnt:", + le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, + delta_cck->ina_cnt, max_cck->ina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "fina_cnt:", + le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, + delta_cck->fina_cnt, max_cck->fina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "plcp_err:", + le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, + delta_cck->plcp_err, max_cck->plcp_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "crc32_err:", + le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, + delta_cck->crc32_err, max_cck->crc32_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "overrun_err:", + le32_to_cpu(cck->overrun_err), + accum_cck->overrun_err, + delta_cck->overrun_err, max_cck->overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "early_overrun_err:", + le32_to_cpu(cck->early_overrun_err), + accum_cck->early_overrun_err, + delta_cck->early_overrun_err, + max_cck->early_overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "crc32_good:", + le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, + delta_cck->crc32_good, + max_cck->crc32_good); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "false_alarm_cnt:", + le32_to_cpu(cck->false_alarm_cnt), + accum_cck->false_alarm_cnt, + delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "fina_sync_err_cnt:", + le32_to_cpu(cck->fina_sync_err_cnt), + accum_cck->fina_sync_err_cnt, + delta_cck->fina_sync_err_cnt, + max_cck->fina_sync_err_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "sfd_timeout:", + le32_to_cpu(cck->sfd_timeout), + accum_cck->sfd_timeout, + delta_cck->sfd_timeout, max_cck->sfd_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "fina_timeout:", + le32_to_cpu(cck->fina_timeout), + accum_cck->fina_timeout, + delta_cck->fina_timeout, max_cck->fina_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "unresponded_rts:", + le32_to_cpu(cck->unresponded_rts), + accum_cck->unresponded_rts, + delta_cck->unresponded_rts, + max_cck->unresponded_rts); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "rxe_frame_lmt_ovrun:", + le32_to_cpu(cck->rxe_frame_limit_overrun), + accum_cck->rxe_frame_limit_overrun, + delta_cck->rxe_frame_limit_overrun, + max_cck->rxe_frame_limit_overrun); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "sent_ack_cnt:", + le32_to_cpu(cck->sent_ack_cnt), + accum_cck->sent_ack_cnt, + delta_cck->sent_ack_cnt, + max_cck->sent_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "sent_cts_cnt:", + le32_to_cpu(cck->sent_cts_cnt), + accum_cck->sent_cts_cnt, + delta_cck->sent_cts_cnt, + max_cck->sent_cts_cnt); + + pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" + "acumulative delta max\n", + "Statistics_Rx - GENERAL:"); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "bogus_cts:", + le32_to_cpu(general->bogus_cts), + accum_general->bogus_cts, + delta_general->bogus_cts, max_general->bogus_cts); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "bogus_ack:", + le32_to_cpu(general->bogus_ack), + accum_general->bogus_ack, + delta_general->bogus_ack, max_general->bogus_ack); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "non_bssid_frames:", + le32_to_cpu(general->non_bssid_frames), + accum_general->non_bssid_frames, + delta_general->non_bssid_frames, + max_general->non_bssid_frames); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "filtered_frames:", + le32_to_cpu(general->filtered_frames), + accum_general->filtered_frames, + delta_general->filtered_frames, + max_general->filtered_frames); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "non_channel_beacons:", + le32_to_cpu(general->non_channel_beacons), + accum_general->non_channel_beacons, + delta_general->non_channel_beacons, + max_general->non_channel_beacons); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +ssize_t iwl3945_ucode_tx_stats_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + int pos = 0; + char *buf; + int bufsz = (sizeof(struct iwl39_statistics_tx) * 48) + 250; + ssize_t ret; + struct iwl39_statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + /* + * The statistic information display here is based on + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + tx = &priv->_3945.statistics.tx; + accum_tx = &priv->_3945.accum_statistics.tx; + delta_tx = &priv->_3945.delta_statistics.tx; + max_tx = &priv->_3945.max_delta.tx; + pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); + pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" + "acumulative delta max\n", + "Statistics_Tx:"); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "preamble:", + le32_to_cpu(tx->preamble_cnt), + accum_tx->preamble_cnt, + delta_tx->preamble_cnt, max_tx->preamble_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "rx_detected_cnt:", + le32_to_cpu(tx->rx_detected_cnt), + accum_tx->rx_detected_cnt, + delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "bt_prio_defer_cnt:", + le32_to_cpu(tx->bt_prio_defer_cnt), + accum_tx->bt_prio_defer_cnt, + delta_tx->bt_prio_defer_cnt, + max_tx->bt_prio_defer_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "bt_prio_kill_cnt:", + le32_to_cpu(tx->bt_prio_kill_cnt), + accum_tx->bt_prio_kill_cnt, + delta_tx->bt_prio_kill_cnt, + max_tx->bt_prio_kill_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "few_bytes_cnt:", + le32_to_cpu(tx->few_bytes_cnt), + accum_tx->few_bytes_cnt, + delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "cts_timeout:", + le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, + delta_tx->cts_timeout, max_tx->cts_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "ack_timeout:", + le32_to_cpu(tx->ack_timeout), + accum_tx->ack_timeout, + delta_tx->ack_timeout, max_tx->ack_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "expected_ack_cnt:", + le32_to_cpu(tx->expected_ack_cnt), + accum_tx->expected_ack_cnt, + delta_tx->expected_ack_cnt, + max_tx->expected_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "actual_ack_cnt:", + le32_to_cpu(tx->actual_ack_cnt), + accum_tx->actual_ack_cnt, + delta_tx->actual_ack_cnt, + max_tx->actual_ack_cnt); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +ssize_t iwl3945_ucode_general_stats_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + int pos = 0; + char *buf; + int bufsz = sizeof(struct iwl39_statistics_general) * 10 + 300; + ssize_t ret; + struct iwl39_statistics_general *general, *accum_general; + struct iwl39_statistics_general *delta_general, *max_general; + struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; + struct iwl39_statistics_div *div, *accum_div, *delta_div, *max_div; + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + /* + * The statistic information display here is based on + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + general = &priv->_3945.statistics.general; + dbg = &priv->_3945.statistics.general.dbg; + div = &priv->_3945.statistics.general.div; + accum_general = &priv->_3945.accum_statistics.general; + delta_general = &priv->_3945.delta_statistics.general; + max_general = &priv->_3945.max_delta.general; + accum_dbg = &priv->_3945.accum_statistics.general.dbg; + delta_dbg = &priv->_3945.delta_statistics.general.dbg; + max_dbg = &priv->_3945.max_delta.general.dbg; + accum_div = &priv->_3945.accum_statistics.general.div; + delta_div = &priv->_3945.delta_statistics.general.div; + max_div = &priv->_3945.max_delta.general.div; + pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); + pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" + "acumulative delta max\n", + "Statistics_General:"); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "burst_check:", + le32_to_cpu(dbg->burst_check), + accum_dbg->burst_check, + delta_dbg->burst_check, max_dbg->burst_check); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "burst_count:", + le32_to_cpu(dbg->burst_count), + accum_dbg->burst_count, + delta_dbg->burst_count, max_dbg->burst_count); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "sleep_time:", + le32_to_cpu(general->sleep_time), + accum_general->sleep_time, + delta_general->sleep_time, max_general->sleep_time); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "slots_out:", + le32_to_cpu(general->slots_out), + accum_general->slots_out, + delta_general->slots_out, max_general->slots_out); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "slots_idle:", + le32_to_cpu(general->slots_idle), + accum_general->slots_idle, + delta_general->slots_idle, max_general->slots_idle); + pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", + le32_to_cpu(general->ttl_timestamp)); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "tx_on_a:", + le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, + delta_div->tx_on_a, max_div->tx_on_a); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "tx_on_b:", + le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, + delta_div->tx_on_b, max_div->tx_on_b); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "exec_time:", + le32_to_cpu(div->exec_time), accum_div->exec_time, + delta_div->exec_time, max_div->exec_time); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", + "probe_time:", + le32_to_cpu(div->probe_time), accum_div->probe_time, + delta_div->probe_time, max_div->probe_time); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h new file mode 100644 index 000000000000..70809c53c215 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-debug.h" + +#ifdef CONFIG_IWLWIFI_DEBUGFS +ssize_t iwl3945_ucode_rx_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); +ssize_t iwl3945_ucode_tx_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); +ssize_t iwl3945_ucode_general_stats_read(struct file *file, + char __user *user_buf, size_t count, + loff_t *ppos); +#else +static ssize_t iwl3945_ucode_rx_stats_read(struct file *file, + char __user *user_buf, size_t count, + loff_t *ppos) +{ + return 0; +} +static ssize_t iwl3945_ucode_tx_stats_read(struct file *file, + char __user *user_buf, size_t count, + loff_t *ppos) +{ + return 0; +} +static ssize_t iwl3945_ucode_general_stats_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + return 0; +} +#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index d10e59def53e..9dad8672d700 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -49,6 +49,7 @@ #include "iwl-helpers.h" #include "iwl-led.h" #include "iwl-3945-led.h" +#include "iwl-3945-debugfs.h" #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ @@ -292,7 +293,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, * iwl3945_rx_reply_tx - Handle Tx response */ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); u16 sequence = le16_to_cpu(pkt->hdr.sequence); @@ -350,18 +351,81 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, * RX handler implementations * *****************************************************************************/ +#ifdef CONFIG_IWLWIFI_DEBUG +/* + * based on the assumption of all statistics counter are in DWORD + * FIXME: This function is for debugging, do not deal with + * the case of counters roll-over. + */ +static void iwl3945_accumulative_statistics(struct iwl_priv *priv, + __le32 *stats) +{ + int i; + __le32 *prev_stats; + u32 *accum_stats; + u32 *delta, *max_delta; + + prev_stats = (__le32 *)&priv->_3945.statistics; + accum_stats = (u32 *)&priv->_3945.accum_statistics; + delta = (u32 *)&priv->_3945.delta_statistics; + max_delta = (u32 *)&priv->_3945.max_delta; + + for (i = sizeof(__le32); i < sizeof(struct iwl3945_notif_statistics); + i += sizeof(__le32), stats++, prev_stats++, delta++, + max_delta++, accum_stats++) { + if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) { + *delta = (le32_to_cpu(*stats) - + le32_to_cpu(*prev_stats)); + *accum_stats += *delta; + if (*delta > *max_delta) + *max_delta = *delta; + } + } + + /* reset accumulative statistics for "no-counter" type statistics */ + priv->_3945.accum_statistics.general.temperature = + priv->_3945.statistics.general.temperature; + priv->_3945.accum_statistics.general.ttl_timestamp = + priv->_3945.statistics.general.ttl_timestamp; +} +#endif void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); + IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", (int)sizeof(struct iwl3945_notif_statistics), le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); +#ifdef CONFIG_IWLWIFI_DEBUG + iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw); +#endif memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics)); } +void iwl3945_reply_statistics(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + __le32 *flag = (__le32 *)&pkt->u.raw; + + if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) { +#ifdef CONFIG_IWLWIFI_DEBUG + memset(&priv->_3945.accum_statistics, 0, + sizeof(struct iwl3945_notif_statistics)); + memset(&priv->_3945.delta_statistics, 0, + sizeof(struct iwl3945_notif_statistics)); + memset(&priv->_3945.max_delta, 0, + sizeof(struct iwl3945_notif_statistics)); +#endif + IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); + } + iwl3945_hw_rx_statistics(priv, rxb); +} + + /****************************************************************************** * * Misc. internal state and helper functions @@ -2735,6 +2799,12 @@ static struct iwl_lib_ops iwl3945_lib = { .isr = iwl_isr_legacy, .config_ap = iwl3945_config_ap, .add_bcast_station = iwl3945_add_bcast_station, + + .debugfs_ops = { + .rx_stats_read = iwl3945_ucode_rx_stats_read, + .tx_stats_read = iwl3945_ucode_tx_stats_read, + .general_stats_read = iwl3945_ucode_general_stats_read, + }, }; static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index e9674f0a1e94..643adb644bb8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -264,6 +264,8 @@ extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv); extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power); extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); +void iwl3945_reply_statistics(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb); extern void iwl3945_disable_events(struct iwl_priv *priv); extern int iwl4965_get_temperature(const struct iwl_priv *priv); extern void iwl3945_post_associate(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index d789f8db4481..0aedbec9cbc8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1053,10 +1053,8 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; - if (priv->cfg->ops->lib->debugfs_ops.rx_stats_read) - return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file, - user_buf, count, ppos); - return 0; + return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file, + user_buf, count, ppos); } static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, @@ -1064,10 +1062,8 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; - if (priv->cfg->ops->lib->debugfs_ops.tx_stats_read) - return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file, - user_buf, count, ppos); - return 0; + return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file, + user_buf, count, ppos); } static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, @@ -1075,10 +1071,8 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; - if (priv->cfg->ops->lib->debugfs_ops.general_stats_read) - return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file, - user_buf, count, ppos); - return 0; + return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file, + user_buf, count, ppos); } static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index bdc60aae75ec..58c69a5798d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1202,6 +1202,11 @@ struct iwl_priv { struct delayed_work rfkill_poll; struct iwl3945_notif_statistics statistics; +#ifdef CONFIG_IWLWIFI_DEBUG + struct iwl3945_notif_statistics accum_statistics; + struct iwl3945_notif_statistics delta_statistics; + struct iwl3945_notif_statistics max_delta; +#endif u32 sta_supp_rates; int last_rx_rssi; /* From Rx packet statistics */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 789480b89a6e..98055fb5caf0 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -956,7 +956,7 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) * statistics request from the host as well as for the periodic * statistics notifications (after received beacons) from the uCode. */ - priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics; + priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_reply_statistics; priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics; iwl_setup_rx_scan_handlers(priv); -- cgit v1.2.3 From e3a3cd8789e1daf1b5af70d3252cab50cd3824c9 Mon Sep 17 00:00:00 2001 From: Daniel Halperin Date: Sun, 18 Apr 2010 09:27:58 -0700 Subject: iwlwifi: set AMPDU status variables correctly The TX status code is currently abusing the ampdu_ack_map field (a bitmap) to count the number of successfully received frames. The comments in mac80211.h show there are actually three different, relevant variables, of which we are currently using two, both incorrectly. Fix this by making - ampdu_ack_len -> the number of ACKed frames (i.e. successes) - ampdu_ack_map -> the bitmap - ampdu_len -> the total number of frames sent (i.e., attempts) to match the header file (and verified with ath9k's usage) and updating Intel's RS code to match. Signed-off-by: Daniel Halperin Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 10 +++++----- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 8f8d5e3e688d..f01f242659c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -867,14 +867,14 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); rs_collect_tx_data(curr_tbl, rs_index, - info->status.ampdu_ack_len, - info->status.ampdu_ack_map); + info->status.ampdu_len, + info->status.ampdu_ack_len); /* Update success/fail counts if not searching for new mode */ if (lq_sta->stay_in_tbl) { - lq_sta->total_success += info->status.ampdu_ack_map; - lq_sta->total_failed += (info->status.ampdu_ack_len - - info->status.ampdu_ack_map); + lq_sta->total_success += info->status.ampdu_ack_len; + lq_sta->total_failed += (info->status.ampdu_len - + info->status.ampdu_ack_len); } } else { /* diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 95e263f1d117..c2a5c85542bf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -1233,8 +1233,9 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, memset(&info->status, 0, sizeof(info->status)); info->flags |= IEEE80211_TX_STAT_ACK; info->flags |= IEEE80211_TX_STAT_AMPDU; - info->status.ampdu_ack_map = successes; - info->status.ampdu_ack_len = agg->frame_count; + info->status.ampdu_ack_len = successes; + info->status.ampdu_ack_map = bitmap; + info->status.ampdu_len = agg->frame_count; iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); -- cgit v1.2.3 From e517736ab85fcaa4ceebbb572f3e86838097ad0a Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 19 Apr 2010 18:49:40 -0700 Subject: iwlwifi: set hw parameters based on device type Separate the hw_set_hw_params() function to per device based; different devices can have different hardware parameters set, when separate the function based on device type can avoid mistakes, give more flexibilities and easier to read. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-5000.c | 73 +++++++++++++++++++++++---------- drivers/net/wireless/iwlwifi/iwl-6000.c | 70 ++++++++++++++++++++++--------- 2 files changed, 103 insertions(+), 40 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index e43493685271..115d3ea1142f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -200,26 +200,57 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) /* Set initial sensitivity parameters */ /* Set initial calibration set */ - switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { - case CSR_HW_REV_TYPE_5150: - priv->hw_params.sens = &iwl5150_sensitivity; - priv->hw_params.calib_init_cfg = - BIT(IWL_CALIB_DC) | - BIT(IWL_CALIB_LO) | - BIT(IWL_CALIB_TX_IQ) | - BIT(IWL_CALIB_BASE_BAND); - - break; - default: - priv->hw_params.sens = &iwl5000_sensitivity; - priv->hw_params.calib_init_cfg = - BIT(IWL_CALIB_XTAL) | - BIT(IWL_CALIB_LO) | - BIT(IWL_CALIB_TX_IQ) | - BIT(IWL_CALIB_TX_IQ_PERD) | - BIT(IWL_CALIB_BASE_BAND); - break; - } + priv->hw_params.sens = &iwl5000_sensitivity; + priv->hw_params.calib_init_cfg = + BIT(IWL_CALIB_XTAL) | + BIT(IWL_CALIB_LO) | + BIT(IWL_CALIB_TX_IQ) | + BIT(IWL_CALIB_TX_IQ_PERD) | + BIT(IWL_CALIB_BASE_BAND); + + return 0; +} + +static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) +{ + if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && + priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) + priv->cfg->num_of_queues = + priv->cfg->mod_params->num_of_queues; + + priv->hw_params.max_txq_num = priv->cfg->num_of_queues; + priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; + priv->hw_params.scd_bc_tbls_size = + priv->cfg->num_of_queues * + sizeof(struct iwlagn_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); + priv->hw_params.max_stations = IWL5000_STATION_COUNT; + priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; + + priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; + + priv->hw_params.max_bsm_size = 0; + priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | + BIT(IEEE80211_BAND_5GHZ); + priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; + + priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); + priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; + priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; + + if (priv->cfg->ops->lib->temp_ops.set_ct_kill) + priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); + + /* Set initial sensitivity parameters */ + /* Set initial calibration set */ + priv->hw_params.sens = &iwl5150_sensitivity; + priv->hw_params.calib_init_cfg = + BIT(IWL_CALIB_DC) | + BIT(IWL_CALIB_LO) | + BIT(IWL_CALIB_TX_IQ) | + BIT(IWL_CALIB_BASE_BAND); return 0; } @@ -332,7 +363,7 @@ static struct iwl_lib_ops iwl5000_lib = { }; static struct iwl_lib_ops iwl5150_lib = { - .set_hw_params = iwl5000_hw_set_hw_params, + .set_hw_params = iwl5150_hw_set_hw_params, .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 7da23d3ff7b6..c4926506a084 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -176,24 +176,56 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) /* Set initial sensitivity parameters */ /* Set initial calibration set */ priv->hw_params.sens = &iwl6000_sensitivity; - switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { - case CSR_HW_REV_TYPE_6x50: - priv->hw_params.calib_init_cfg = - BIT(IWL_CALIB_XTAL) | - BIT(IWL_CALIB_DC) | - BIT(IWL_CALIB_LO) | - BIT(IWL_CALIB_TX_IQ) | - BIT(IWL_CALIB_BASE_BAND); - - break; - default: - priv->hw_params.calib_init_cfg = - BIT(IWL_CALIB_XTAL) | - BIT(IWL_CALIB_LO) | - BIT(IWL_CALIB_TX_IQ) | - BIT(IWL_CALIB_BASE_BAND); - break; - } + priv->hw_params.calib_init_cfg = + BIT(IWL_CALIB_XTAL) | + BIT(IWL_CALIB_LO) | + BIT(IWL_CALIB_TX_IQ) | + BIT(IWL_CALIB_BASE_BAND); + + return 0; +} + +static int iwl6050_hw_set_hw_params(struct iwl_priv *priv) +{ + if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && + priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) + priv->cfg->num_of_queues = + priv->cfg->mod_params->num_of_queues; + + priv->hw_params.max_txq_num = priv->cfg->num_of_queues; + priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; + priv->hw_params.scd_bc_tbls_size = + priv->cfg->num_of_queues * + sizeof(struct iwlagn_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); + priv->hw_params.max_stations = IWL5000_STATION_COUNT; + priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; + + priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; + + priv->hw_params.max_bsm_size = 0; + priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | + BIT(IEEE80211_BAND_5GHZ); + priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; + + priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); + priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; + priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; + + if (priv->cfg->ops->lib->temp_ops.set_ct_kill) + priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); + + /* Set initial sensitivity parameters */ + /* Set initial calibration set */ + priv->hw_params.sens = &iwl6000_sensitivity; + priv->hw_params.calib_init_cfg = + BIT(IWL_CALIB_XTAL) | + BIT(IWL_CALIB_DC) | + BIT(IWL_CALIB_LO) | + BIT(IWL_CALIB_TX_IQ) | + BIT(IWL_CALIB_BASE_BAND); return 0; } @@ -304,7 +336,7 @@ static const struct iwl_ops iwl6000_ops = { }; static struct iwl_lib_ops iwl6050_lib = { - .set_hw_params = iwl6000_hw_set_hw_params, + .set_hw_params = iwl6050_hw_set_hw_params, .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, -- cgit v1.2.3 From f8478df1eab2f11aefc4b6668c5867949ab96bd7 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 19 Apr 2010 20:39:48 -0700 Subject: iwlwifi: greenfield support only true for 11n devices Greenfield is a 11n feature, remove it from non-11n devices configuration parameters list Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 - drivers/net/wireless/iwlwifi/iwl-6000.c | 3 --- 2 files changed, 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 8431ffce37d3..fb59af2d41c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -282,7 +282,6 @@ struct iwl_cfg iwl1000_bg_cfg = { .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_1000, .shadow_ram_support = false, - .ht_greenfield_support = true, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .support_ct_kill_exit = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index c4926506a084..7acef703253a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -500,7 +500,6 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .pa_type = IWL_PA_INTERNAL, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, - .ht_greenfield_support = true, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .supports_idle = true, @@ -533,7 +532,6 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .pa_type = IWL_PA_INTERNAL, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, - .ht_greenfield_support = true, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .supports_idle = true, @@ -600,7 +598,6 @@ struct iwl_cfg iwl6050_2abg_cfg = { .pa_type = IWL_PA_SYSTEM, .max_ll_items = OTP_MAX_LL_ITEMS_6x50, .shadow_ram_support = true, - .ht_greenfield_support = true, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .supports_idle = true, -- cgit v1.2.3 From 1f55c12cef6d369d76ae13d522edd1c07e667788 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 3 May 2010 14:46:05 -0400 Subject: iwmc3200wifi: cleanup unneeded debugfs error handling "iwl: cleanup: remove unneeded error handling" missed the one in if_sdio_debugfs_init(). I don't think we even need to check -ENODEV ourselves because if DEBUG_FS is not compiled in, all the debugfs utility functions will become no-op. Reported-by: Dan Carpenter Signed-off-by: Zhu Yi Acked-by: Dan Carpenter Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/bus.h | 2 +- drivers/net/wireless/iwmc3200wifi/debug.h | 4 +-- drivers/net/wireless/iwmc3200wifi/debugfs.c | 47 ++++++----------------------- drivers/net/wireless/iwmc3200wifi/sdio.c | 17 ++--------- 4 files changed, 15 insertions(+), 55 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwmc3200wifi/bus.h b/drivers/net/wireless/iwmc3200wifi/bus.h index 836663eec257..62edd5888a7b 100644 --- a/drivers/net/wireless/iwmc3200wifi/bus.h +++ b/drivers/net/wireless/iwmc3200wifi/bus.h @@ -31,7 +31,7 @@ struct iwm_if_ops { int (*disable)(struct iwm_priv *iwm); int (*send_chunk)(struct iwm_priv *iwm, u8* buf, int count); - int (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir); + void (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir); void (*debugfs_exit)(struct iwm_priv *iwm); const char *umac_name; diff --git a/drivers/net/wireless/iwmc3200wifi/debug.h b/drivers/net/wireless/iwmc3200wifi/debug.h index e35c9b693d1f..f98bf125a8ae 100644 --- a/drivers/net/wireless/iwmc3200wifi/debug.h +++ b/drivers/net/wireless/iwmc3200wifi/debug.h @@ -113,10 +113,10 @@ struct iwm_debugfs { }; #ifdef CONFIG_IWM_DEBUG -int iwm_debugfs_init(struct iwm_priv *iwm); +void iwm_debugfs_init(struct iwm_priv *iwm); void iwm_debugfs_exit(struct iwm_priv *iwm); #else -static inline int iwm_debugfs_init(struct iwm_priv *iwm) +static inline void iwm_debugfs_init(struct iwm_priv *iwm) { return 0; } diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c index c916152bb936..b42165c40288 100644 --- a/drivers/net/wireless/iwmc3200wifi/debugfs.c +++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c @@ -47,12 +47,11 @@ static struct { #define add_dbg_module(dbg, name, id, initlevel) \ do { \ - struct dentry *d; \ dbg.dbg_module[id] = (initlevel); \ - d = debugfs_create_x8(name, 0600, dbg.dbgdir, \ - &(dbg.dbg_module[id])); \ - if (!IS_ERR(d)) \ - dbg.dbg_module_dentries[id] = d; \ + dbg.dbg_module_dentries[id] = \ + debugfs_create_x8(name, 0600, \ + dbg.dbgdir, \ + &(dbg.dbg_module[id])); \ } while (0) static int iwm_debugfs_u32_read(void *data, u64 *val) @@ -422,37 +421,19 @@ static const struct file_operations iwm_debugfs_fw_err_fops = { .read = iwm_debugfs_fw_err_read, }; -int iwm_debugfs_init(struct iwm_priv *iwm) +void iwm_debugfs_init(struct iwm_priv *iwm) { - int i, result; - char devdir[16]; + int i; iwm->dbg.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); - result = PTR_ERR(iwm->dbg.rootdir); - if (!result || IS_ERR(iwm->dbg.rootdir)) { - if (result == -ENODEV) { - IWM_ERR(iwm, "DebugFS (CONFIG_DEBUG_FS) not " - "enabled in kernel config\n"); - result = 0; /* No debugfs support */ - } - IWM_ERR(iwm, "Couldn't create rootdir: %d\n", result); - goto error; - } - - snprintf(devdir, sizeof(devdir), "%s", wiphy_name(iwm_to_wiphy(iwm))); - - iwm->dbg.devdir = debugfs_create_dir(devdir, iwm->dbg.rootdir); + iwm->dbg.devdir = debugfs_create_dir(wiphy_name(iwm_to_wiphy(iwm)), + iwm->dbg.rootdir); iwm->dbg.dbgdir = debugfs_create_dir("debug", iwm->dbg.devdir); iwm->dbg.rxdir = debugfs_create_dir("rx", iwm->dbg.devdir); iwm->dbg.txdir = debugfs_create_dir("tx", iwm->dbg.devdir); iwm->dbg.busdir = debugfs_create_dir("bus", iwm->dbg.devdir); - if (iwm->bus_ops->debugfs_init) { - result = iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir); - if (result < 0) { - IWM_ERR(iwm, "Couldn't create bus entry: %d\n", result); - goto error; - } - } + if (iwm->bus_ops->debugfs_init) + iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir); iwm->dbg.dbg_level = IWM_DL_NONE; iwm->dbg.dbg_level_dentry = @@ -471,23 +452,15 @@ int iwm_debugfs_init(struct iwm_priv *iwm) iwm->dbg.txq_dentry = debugfs_create_file("queues", 0200, iwm->dbg.txdir, iwm, &iwm_debugfs_txq_fops); - iwm->dbg.tx_credit_dentry = debugfs_create_file("credits", 0200, iwm->dbg.txdir, iwm, &iwm_debugfs_tx_credit_fops); - iwm->dbg.rx_ticket_dentry = debugfs_create_file("tickets", 0200, iwm->dbg.rxdir, iwm, &iwm_debugfs_rx_ticket_fops); - iwm->dbg.fw_err_dentry = debugfs_create_file("last_fw_err", 0200, iwm->dbg.dbgdir, iwm, &iwm_debugfs_fw_err_fops); - - return 0; - - error: - return result; } void iwm_debugfs_exit(struct iwm_priv *iwm) diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c index a7ec7eac9137..b55f4b7446bc 100644 --- a/drivers/net/wireless/iwmc3200wifi/sdio.c +++ b/drivers/net/wireless/iwmc3200wifi/sdio.c @@ -365,21 +365,13 @@ static const struct file_operations iwm_debugfs_sdio_fops = { .read = iwm_debugfs_sdio_read, }; -static int if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir) +static void if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir) { - int result; struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); hw->cccr_dentry = debugfs_create_file("cccr", 0200, parent_dir, iwm, &iwm_debugfs_sdio_fops); - result = PTR_ERR(hw->cccr_dentry); - if (IS_ERR(hw->cccr_dentry) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create CCCR entry: %d\n", result); - return result; - } - - return 0; } static void if_sdio_debugfs_exit(struct iwm_priv *iwm) @@ -439,11 +431,7 @@ static int iwm_sdio_probe(struct sdio_func *func, hw = iwm_private(iwm); hw->iwm = iwm; - ret = iwm_debugfs_init(iwm); - if (ret < 0) { - IWM_ERR(iwm, "Debugfs registration failed\n"); - goto if_free; - } + iwm_debugfs_init(iwm); sdio_set_drvdata(func, hw); @@ -472,7 +460,6 @@ static int iwm_sdio_probe(struct sdio_func *func, destroy_workqueue(hw->isr_wq); debugfs_exit: iwm_debugfs_exit(iwm); - if_free: iwm_if_free(iwm); return ret; } -- cgit v1.2.3 From 91639c76bfd9d27ac54a3c521a2559d02f409ebe Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 28 Apr 2010 17:00:52 -0400 Subject: rt2x00: remove now unused noise field from struct rxdone_entry_desc Signed-off-by: John W. Linville Acked-by: Gertjan van Wingerde --- drivers/net/wireless/rt2x00/rt2800pci.c | 4 ---- drivers/net/wireless/rt2x00/rt2800usb.c | 4 ---- drivers/net/wireless/rt2x00/rt2x00queue.h | 2 -- 3 files changed, 10 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 0e52f174896c..89281d78f04d 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -895,10 +895,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) + rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2; - rxdesc->noise = - (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) + - rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2; - rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT); /* diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index a71615606c37..6f2a945cd45c 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -645,10 +645,6 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) + rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2; - rxdesc->noise = - (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) + - rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2; - rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index c1e482bb37b3..f519aba4ff0f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -183,7 +183,6 @@ enum rxdone_entry_desc_flags { * @timestamp: RX Timestamp * @signal: Signal of the received frame. * @rssi: RSSI of the received frame. - * @noise: Measured noise during frame reception. * @size: Data size of the received frame. * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags). * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags). @@ -197,7 +196,6 @@ struct rxdone_entry_desc { u64 timestamp; int signal; int rssi; - int noise; int size; int flags; int dev_flags; -- cgit v1.2.3 From 354b4f04f2aa9d9652ecd5a4cdace784c7cfcca8 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Apr 2010 15:56:06 -0400 Subject: b43: Added get_survey callback in order to get channel noise Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index e0575591828c..f6019828ed3f 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4570,6 +4570,23 @@ static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw) mutex_unlock(&wl->mutex); } +static int b43_op_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) +{ + struct b43_wl *wl = hw_to_b43_wl(hw); + struct b43_wldev *dev = wl->current_dev; + struct ieee80211_conf *conf = &hw->conf; + + if (idx != 0) + return -ENOENT; + + survey->channel = conf->channel; + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = dev->stats.link_noise; + + return 0; +} + static const struct ieee80211_ops b43_hw_ops = { .tx = b43_op_tx, .conf_tx = b43_op_conf_tx, @@ -4589,6 +4606,7 @@ static const struct ieee80211_ops b43_hw_ops = { .sta_notify = b43_op_sta_notify, .sw_scan_start = b43_op_sw_scan_start_notifier, .sw_scan_complete = b43_op_sw_scan_complete_notifier, + .get_survey = b43_op_get_survey, .rfkill_poll = b43_rfkill_poll, }; -- cgit v1.2.3 From c7ab1a4dcb8fb63364e9460b1182da6eae5f0d16 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Apr 2010 15:56:25 -0400 Subject: b43legacy: Added get_survey callback in order to get channel noise Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/main.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index b2df432d3c63..9304dc0f2f66 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3481,6 +3481,23 @@ static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw, return 0; } +static int b43legacy_op_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) +{ + struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); + struct b43legacy_wldev *dev = wl->current_dev; + struct ieee80211_conf *conf = &hw->conf; + + if (idx != 0) + return -ENOENT; + + survey->channel = conf->channel; + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = dev->stats.link_noise; + + return 0; +} + static const struct ieee80211_ops b43legacy_hw_ops = { .tx = b43legacy_op_tx, .conf_tx = b43legacy_op_conf_tx, @@ -3493,6 +3510,7 @@ static const struct ieee80211_ops b43legacy_hw_ops = { .start = b43legacy_op_start, .stop = b43legacy_op_stop, .set_tim = b43legacy_op_beacon_set_tim, + .get_survey = b43legacy_op_get_survey, .rfkill_poll = b43legacy_rfkill_poll, }; -- cgit v1.2.3 From b42f2074dedef559ecf72dce61a6501f9f9b273a Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sat, 1 May 2010 14:05:38 +0100 Subject: orinoco: add hermes_ops Pave the way for introducing USB alternative functions. Force callers to dereference ops instead of providing wrappers. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/airport.c | 2 +- drivers/net/wireless/orinoco/cfg.c | 2 +- drivers/net/wireless/orinoco/fw.c | 2 +- drivers/net/wireless/orinoco/hermes.c | 52 ++++++++++--------- drivers/net/wireless/orinoco/hermes.h | 50 +++++++++++-------- drivers/net/wireless/orinoco/hermes_dld.c | 34 ++++++------- drivers/net/wireless/orinoco/hw.c | 63 +++++++++++------------ drivers/net/wireless/orinoco/main.c | 83 ++++++++++++++++--------------- drivers/net/wireless/orinoco/wext.c | 6 +-- 9 files changed, 154 insertions(+), 140 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c index c60df2c1aca3..ea23c4fdbf62 100644 --- a/drivers/net/wireless/orinoco/airport.c +++ b/drivers/net/wireless/orinoco/airport.c @@ -195,7 +195,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match) ssleep(1); /* Reset it before we get the interrupt */ - hermes_init(hw); + hw->ops->init(hw); if (request_irq(card->irq, orinoco_interrupt, 0, DRIVER_NAME, priv)) { printk(KERN_ERR PFX "Couldn't get IRQ %d\n", card->irq); diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c index 90dd4d0595c3..81d228de9e5d 100644 --- a/drivers/net/wireless/orinoco/cfg.c +++ b/drivers/net/wireless/orinoco/cfg.c @@ -189,7 +189,7 @@ static int orinoco_set_channel(struct wiphy *wiphy, if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { /* Fast channel change - no commit if successful */ hermes_t *hw = &priv->hw; - err = hermes_docmd_wait(hw, HERMES_CMD_TEST | + err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST | HERMES_TEST_SET_CHANNEL, channel, NULL); } diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c index cfa72962052b..07c79e5de32d 100644 --- a/drivers/net/wireless/orinoco/fw.c +++ b/drivers/net/wireless/orinoco/fw.c @@ -259,7 +259,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw, } /* Reset hermes chip and make sure it responds */ - ret = hermes_init(hw); + ret = hw->ops->init(hw); /* hermes_reset() should return 0 with the secondary firmware */ if (secondary && ret != 0) diff --git a/drivers/net/wireless/orinoco/hermes.c b/drivers/net/wireless/orinoco/hermes.c index 1a2fca76fd3c..a7df5240779c 100644 --- a/drivers/net/wireless/orinoco/hermes.c +++ b/drivers/net/wireless/orinoco/hermes.c @@ -70,6 +70,7 @@ #endif /* ! HERMES_DEBUG */ +static const struct hermes_ops hermes_ops_local; /* * Internal functions @@ -111,9 +112,9 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0, */ /* For doing cmds that wipe the magic constant in SWSUPPORT0 */ -int hermes_doicmd_wait(hermes_t *hw, u16 cmd, - u16 parm0, u16 parm1, u16 parm2, - struct hermes_response *resp) +static int hermes_doicmd_wait(hermes_t *hw, u16 cmd, + u16 parm0, u16 parm1, u16 parm2, + struct hermes_response *resp) { int err = 0; int k; @@ -163,17 +164,17 @@ int hermes_doicmd_wait(hermes_t *hw, u16 cmd, out: return err; } -EXPORT_SYMBOL(hermes_doicmd_wait); void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing) { hw->iobase = address; hw->reg_spacing = reg_spacing; hw->inten = 0x0; + hw->ops = &hermes_ops_local; } EXPORT_SYMBOL(hermes_struct_init); -int hermes_init(hermes_t *hw) +static int hermes_init(hermes_t *hw) { u16 reg; int err = 0; @@ -217,7 +218,6 @@ int hermes_init(hermes_t *hw) return err; } -EXPORT_SYMBOL(hermes_init); /* Issue a command to the chip, and (busy!) wait for it to * complete. @@ -228,8 +228,8 @@ EXPORT_SYMBOL(hermes_init); * > 0 on error returned by the firmware * * Callable from any context, but locking is your problem. */ -int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, - struct hermes_response *resp) +static int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, + struct hermes_response *resp) { int err; int k; @@ -291,9 +291,8 @@ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, out: return err; } -EXPORT_SYMBOL(hermes_docmd_wait); -int hermes_allocate(hermes_t *hw, u16 size, u16 *fid) +static int hermes_allocate(hermes_t *hw, u16 size, u16 *fid) { int err = 0; int k; @@ -333,7 +332,6 @@ int hermes_allocate(hermes_t *hw, u16 size, u16 *fid) return 0; } -EXPORT_SYMBOL(hermes_allocate); /* Set up a BAP to read a particular chunk of data from card's internal buffer. * @@ -403,8 +401,8 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset) * 0 on success * > 0 on error from firmware */ -int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, - u16 id, u16 offset) +static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, + u16 id, u16 offset) { int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; int err = 0; @@ -422,7 +420,6 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, out: return err; } -EXPORT_SYMBOL(hermes_bap_pread); /* Write a block of data to the chip's buffer, via the * BAP. Synchronization/serialization is the caller's problem. @@ -432,8 +429,8 @@ EXPORT_SYMBOL(hermes_bap_pread); * 0 on success * > 0 on error from firmware */ -int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, - u16 id, u16 offset) +static int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, + u16 id, u16 offset) { int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; int err = 0; @@ -451,7 +448,6 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, out: return err; } -EXPORT_SYMBOL(hermes_bap_pwrite); /* Read a Length-Type-Value record from the card. * @@ -461,8 +457,8 @@ EXPORT_SYMBOL(hermes_bap_pwrite); * practice. * * Callable from user or bh context. */ -int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, - u16 *length, void *buf) +static int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, + u16 *length, void *buf) { int err = 0; int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; @@ -505,10 +501,9 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, return 0; } -EXPORT_SYMBOL(hermes_read_ltv); -int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, - u16 length, const void *value) +static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, + u16 length, const void *value) { int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; int err = 0; @@ -533,4 +528,15 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, return err; } -EXPORT_SYMBOL(hermes_write_ltv); + +/* Hermes operations for local buses */ +static const struct hermes_ops hermes_ops_local = { + .init = hermes_init, + .cmd_wait = hermes_docmd_wait, + .init_cmd_wait = hermes_doicmd_wait, + .allocate = hermes_allocate, + .read_ltv = hermes_read_ltv, + .write_ltv = hermes_write_ltv, + .bap_pread = hermes_bap_pread, + .bap_pwrite = hermes_bap_pwrite +}; diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h index 2dddbb597c4d..18b268c54dfe 100644 --- a/drivers/net/wireless/orinoco/hermes.h +++ b/drivers/net/wireless/orinoco/hermes.h @@ -374,6 +374,27 @@ struct hermes_multicast { /* Timeouts */ #define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */ +struct hermes; + +/* Functions to access hardware */ +struct hermes_ops { + int (*init)(struct hermes *hw); + int (*cmd_wait)(struct hermes *hw, u16 cmd, u16 parm0, + struct hermes_response *resp); + int (*init_cmd_wait)(struct hermes *hw, u16 cmd, + u16 parm0, u16 parm1, u16 parm2, + struct hermes_response *resp); + int (*allocate)(struct hermes *hw, u16 size, u16 *fid); + int (*read_ltv)(struct hermes *hw, int bap, u16 rid, unsigned buflen, + u16 *length, void *buf); + int (*write_ltv)(struct hermes *hw, int bap, u16 rid, + u16 length, const void *value); + int (*bap_pread)(struct hermes *hw, int bap, void *buf, int len, + u16 id, u16 offset); + int (*bap_pwrite)(struct hermes *hw, int bap, const void *buf, + int len, u16 id, u16 offset); +}; + /* Basic control structure */ typedef struct hermes { void __iomem *iobase; @@ -381,6 +402,7 @@ typedef struct hermes { #define HERMES_16BIT_REGSPACING 0 #define HERMES_32BIT_REGSPACING 1 u16 inten; /* Which interrupts should be enabled? */ + const struct hermes_ops *ops; } hermes_t; /* Register access convenience macros */ @@ -394,22 +416,6 @@ typedef struct hermes { /* Function prototypes */ void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing); -int hermes_init(hermes_t *hw); -int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, - struct hermes_response *resp); -int hermes_doicmd_wait(hermes_t *hw, u16 cmd, - u16 parm0, u16 parm1, u16 parm2, - struct hermes_response *resp); -int hermes_allocate(hermes_t *hw, u16 size, u16 *fid); - -int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, - u16 id, u16 offset); -int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, - u16 id, u16 offset); -int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen, - u16 *length, void *buf); -int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, - u16 length, const void *value); /* Inline functions */ @@ -426,13 +432,13 @@ static inline void hermes_set_irqmask(hermes_t *hw, u16 events) static inline int hermes_enable_port(hermes_t *hw, int port) { - return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8), + return hw->ops->cmd_wait(hw, HERMES_CMD_ENABLE | (port << 8), 0, NULL); } static inline int hermes_disable_port(hermes_t *hw, int port) { - return hermes_docmd_wait(hw, HERMES_CMD_DISABLE | (port << 8), + return hw->ops->cmd_wait(hw, HERMES_CMD_DISABLE | (port << 8), 0, NULL); } @@ -440,7 +446,7 @@ static inline int hermes_disable_port(hermes_t *hw, int port) * information frame in __orinoco_ev_info() */ static inline int hermes_inquire(hermes_t *hw, u16 rid) { - return hermes_docmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL); + return hw->ops->cmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL); } #define HERMES_BYTES_TO_RECLEN(n) ((((n)+1)/2) + 1) @@ -475,10 +481,10 @@ static inline void hermes_clear_words(struct hermes *hw, int off, } #define HERMES_READ_RECORD(hw, bap, rid, buf) \ - (hermes_read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf))) + (hw->ops->read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf))) #define HERMES_WRITE_RECORD(hw, bap, rid, buf) \ - (hermes_write_ltv((hw), (bap), (rid), \ - HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf))) + (hw->ops->write_ltv((hw), (bap), (rid), \ + HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf))) static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word) { diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c index fb157eb889ca..8f22e2026a82 100644 --- a/drivers/net/wireless/orinoco/hermes_dld.c +++ b/drivers/net/wireless/orinoco/hermes_dld.c @@ -293,7 +293,7 @@ int hermes_read_pda(hermes_t *hw, /* PDA of spectrum symbol is in eeprom */ /* Issue command to read EEPROM */ - ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL); + ret = hw->ops->cmd_wait(hw, HERMES_CMD_READMIF, 0, NULL); if (ret) return ret; } else { @@ -408,16 +408,16 @@ int hermesi_program_init(hermes_t *hw, u32 offset) /* Acknowledge any outstanding command */ hermes_write_regn(hw, EVACK, 0xFFFF); - /* Using doicmd_wait rather than docmd_wait */ - err = hermes_doicmd_wait(hw, - 0x0100 | HERMES_CMD_INIT, - 0, 0, 0, NULL); + /* Using init_cmd_wait rather than cmd_wait */ + err = hw->ops->init_cmd_wait(hw, + 0x0100 | HERMES_CMD_INIT, + 0, 0, 0, NULL); if (err) return err; - err = hermes_doicmd_wait(hw, - 0x0000 | HERMES_CMD_INIT, - 0, 0, 0, NULL); + err = hw->ops->init_cmd_wait(hw, + 0x0000 | HERMES_CMD_INIT, + 0, 0, 0, NULL); if (err) return err; @@ -428,12 +428,12 @@ int hermesi_program_init(hermes_t *hw, u32 offset) return err; pr_debug(PFX "Enabling volatile, EP 0x%08x\n", offset); - err = hermes_doicmd_wait(hw, - HERMES_PROGRAM_ENABLE_VOLATILE, - offset & 0xFFFFu, - offset >> 16, - 0, - NULL); + err = hw->ops->init_cmd_wait(hw, + HERMES_PROGRAM_ENABLE_VOLATILE, + offset & 0xFFFFu, + offset >> 16, + 0, + NULL); pr_debug(PFX "PROGRAM_ENABLE returned %d\n", err); return err; @@ -451,7 +451,7 @@ int hermesi_program_end(hermes_t *hw) int rc = 0; int err; - rc = hermes_docmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp); + rc = hw->ops->cmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp); pr_debug(PFX "PROGRAM_DISABLE returned %d, " "r0 0x%04x, r1 0x%04x, r2 0x%04x\n", @@ -468,8 +468,8 @@ int hermesi_program_end(hermes_t *hw) hermes_write_regn(hw, EVACK, 0xFFFF); /* Reinitialise, ignoring return */ - (void) hermes_doicmd_wait(hw, 0x0000 | HERMES_CMD_INIT, - 0, 0, 0, NULL); + (void) hw->ops->init_cmd_wait(hw, 0x0000 | HERMES_CMD_INIT, + 0, 0, 0, NULL); return rc ? rc : err; } diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index 24ea4b4d487e..9c86acc42794 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c @@ -177,9 +177,9 @@ int determine_fw_capabilities(struct orinoco_private *priv, /* 3Com MAC : 00:50:DA:* */ memset(tmp, 0, sizeof(tmp)); /* Get the Symbol firmware version */ - err = hermes_read_ltv(hw, USER_BAP, - HERMES_RID_SECONDARYVERSION_SYMBOL, - SYMBOL_MAX_VER_LEN, NULL, &tmp); + err = hw->ops->read_ltv(hw, USER_BAP, + HERMES_RID_SECONDARYVERSION_SYMBOL, + SYMBOL_MAX_VER_LEN, NULL, &tmp); if (err) { dev_warn(dev, "Error %d reading Symbol firmware info. " "Wildly guessing capabilities...\n", err); @@ -286,8 +286,8 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr) u16 reclen; /* Get the MAC address */ - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, - ETH_ALEN, NULL, dev_addr); + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, + ETH_ALEN, NULL, dev_addr); if (err) { dev_warn(dev, "Failed to read MAC address!\n"); goto out; @@ -296,8 +296,8 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr) dev_dbg(dev, "MAC address %pM\n", dev_addr); /* Get the station name */ - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME, - sizeof(nickbuf), &reclen, &nickbuf); + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME, + sizeof(nickbuf), &reclen, &nickbuf); if (err) { dev_err(dev, "failed to read station name\n"); goto out; @@ -413,11 +413,11 @@ int orinoco_hw_allocate_fid(struct orinoco_private *priv) struct hermes *hw = &priv->hw; int err; - err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); + err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid); if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) { /* Try workaround for old Symbol firmware bug */ priv->nicbuf_size = TX_NICBUF_SIZE_BUG; - err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); + err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid); dev_warn(dev, "Firmware ALLOC bug detected " "(old Symbol firmware?). Work around %s\n", @@ -463,8 +463,9 @@ int orinoco_hw_program_rids(struct orinoco_private *priv) struct hermes_idstring idbuf; /* Set the MAC address */ - err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, - HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr); + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, + HERMES_BYTES_TO_RECLEN(ETH_ALEN), + dev->dev_addr); if (err) { printk(KERN_ERR "%s: Error %d setting MAC address\n", dev->name, err); @@ -527,7 +528,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv) idbuf.len = cpu_to_le16(strlen(priv->desired_essid)); memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val)); /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */ - err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID, + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID, HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2), &idbuf); if (err) { @@ -535,7 +536,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv) dev->name, err); return err; } - err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID, + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID, HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2), &idbuf); if (err) { @@ -547,9 +548,9 @@ int orinoco_hw_program_rids(struct orinoco_private *priv) /* Set the station name */ idbuf.len = cpu_to_le16(strlen(priv->nick)); memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val)); - err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME, - HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2), - &idbuf); + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME, + HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2), + &idbuf); if (err) { printk(KERN_ERR "%s: Error %d setting nickname\n", dev->name, err); @@ -664,12 +665,12 @@ int orinoco_hw_program_rids(struct orinoco_private *priv) if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { /* Enable monitor mode */ dev->type = ARPHRD_IEEE80211; - err = hermes_docmd_wait(hw, HERMES_CMD_TEST | + err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST | HERMES_TEST_MONITOR, 0, NULL); } else { /* Disable monitor mode */ dev->type = ARPHRD_ETHER; - err = hermes_docmd_wait(hw, HERMES_CMD_TEST | + err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST | HERMES_TEST_STOP, 0, NULL); } if (err) @@ -695,8 +696,8 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc) if ((key < 0) || (key >= 4)) return -EINVAL; - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV, - sizeof(tsc_arr), NULL, &tsc_arr); + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV, + sizeof(tsc_arr), NULL, &tsc_arr); if (!err) memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0])); @@ -875,7 +876,7 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv) memcpy(key, priv->keys[i].key, priv->keys[i].key_len); - err = hermes_write_ltv(hw, USER_BAP, + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDEFAULTKEY0 + i, HERMES_BYTES_TO_RECLEN(keylen), key); @@ -1092,7 +1093,7 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, memcpy(mclist.addr[i++], p->dmi_addr, ETH_ALEN); } - err = hermes_write_ltv(hw, USER_BAP, + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES, HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN), &mclist); @@ -1134,15 +1135,15 @@ int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID : HERMES_RID_CNFDESIREDSSID; - err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf), - NULL, &essidbuf); + err = hw->ops->read_ltv(hw, USER_BAP, rid, sizeof(essidbuf), + NULL, &essidbuf); if (err) goto fail_unlock; } else { *active = 0; - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID, - sizeof(essidbuf), NULL, &essidbuf); + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID, + sizeof(essidbuf), NULL, &essidbuf); if (err) goto fail_unlock; } @@ -1213,8 +1214,8 @@ int orinoco_hw_get_bitratelist(struct orinoco_private *priv, if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES, - sizeof(list), NULL, &list); + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES, + sizeof(list), NULL, &list); orinoco_unlock(priv, &flags); if (err) @@ -1281,7 +1282,7 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv, idbuf.len = cpu_to_le16(len); memcpy(idbuf.val, ssid->ssid, len); - err = hermes_write_ltv(hw, USER_BAP, + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFSCANSSID_AGERE, HERMES_BYTES_TO_RECLEN(len + 2), &idbuf); @@ -1345,8 +1346,8 @@ int orinoco_hw_get_current_bssid(struct orinoco_private *priv, hermes_t *hw = &priv->hw; int err; - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, - ETH_ALEN, NULL, addr); + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, + ETH_ALEN, NULL, addr); return err; } diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index b42634c614b5..d90951f731ef 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -399,8 +399,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) memset(&desc, 0, sizeof(desc)); *txcntl = cpu_to_le16(tx_control); - err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), - txfid, 0); + err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), + txfid, 0); if (err) { if (net_ratelimit()) printk(KERN_ERR "%s: Error %d writing Tx " @@ -413,8 +413,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) memset(&desc, 0, sizeof(desc)); desc.tx_control = cpu_to_le16(tx_control); - err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), - txfid, 0); + err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), + txfid, 0); if (err) { if (net_ratelimit()) printk(KERN_ERR "%s: Error %d writing Tx " @@ -457,8 +457,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) memcpy(eh, &hdr, sizeof(hdr)); } - err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len, - txfid, HERMES_802_3_OFFSET); + err = hw->ops->bap_pwrite(hw, USER_BAP, skb->data, skb->len, + txfid, HERMES_802_3_OFFSET); if (err) { printk(KERN_ERR "%s: Error %d writing packet to BAP\n", dev->name, err); @@ -489,8 +489,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic); /* Write the MIC */ - err = hermes_bap_pwrite(hw, USER_BAP, &mic_buf[0], len, - txfid, HERMES_802_3_OFFSET + offset); + err = hw->ops->bap_pwrite(hw, USER_BAP, &mic_buf[0], len, + txfid, HERMES_802_3_OFFSET + offset); if (err) { printk(KERN_ERR "%s: Error %d writing MIC to BAP\n", dev->name, err); @@ -501,7 +501,7 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) /* Finally, we actually initiate the send */ netif_stop_queue(dev); - err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, + err = hw->ops->cmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, txfid, NULL); if (err) { netif_start_queue(dev); @@ -571,9 +571,9 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) return; /* Nothing's really happened */ /* Read part of the frame header - we need status and addr1 */ - err = hermes_bap_pread(hw, IRQ_BAP, &hdr, - sizeof(struct hermes_txexc_data), - fid, 0); + err = hw->ops->bap_pread(hw, IRQ_BAP, &hdr, + sizeof(struct hermes_txexc_data), + fid, 0); hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); stats->tx_errors++; @@ -763,9 +763,9 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, /* If any, copy the data from the card to the skb */ if (datalen > 0) { - err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen), - ALIGN(datalen, 2), rxfid, - HERMES_802_2_OFFSET); + err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, datalen), + ALIGN(datalen, 2), rxfid, + HERMES_802_2_OFFSET); if (err) { printk(KERN_ERR "%s: error %d reading monitor frame\n", dev->name, err); @@ -813,8 +813,8 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) rxfid = hermes_read_regn(hw, RXFID); - err = hermes_bap_pread(hw, IRQ_BAP, desc, sizeof(*desc), - rxfid, 0); + err = hw->ops->bap_pread(hw, IRQ_BAP, desc, sizeof(*desc), + rxfid, 0); if (err) { printk(KERN_ERR "%s: error %d reading Rx descriptor. " "Frame dropped.\n", dev->name, err); @@ -881,9 +881,9 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) nothing is removed. 2 is for aligning the IP header. */ skb_reserve(skb, ETH_HLEN + 2); - err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length), - ALIGN(length, 2), rxfid, - HERMES_802_2_OFFSET); + err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, length), + ALIGN(length, 2), rxfid, + HERMES_802_2_OFFSET); if (err) { printk(KERN_ERR "%s: error %d reading frame. " "Frame dropped.\n", dev->name, err); @@ -1144,9 +1144,9 @@ static void orinoco_join_ap(struct work_struct *work) goto out; /* Read scan results from the firmware */ - err = hermes_read_ltv(hw, USER_BAP, - HERMES_RID_SCANRESULTSTABLE, - MAX_SCAN_LEN, &len, buf); + err = hw->ops->read_ltv(hw, USER_BAP, + HERMES_RID_SCANRESULTSTABLE, + MAX_SCAN_LEN, &len, buf); if (err) { printk(KERN_ERR "%s: Cannot read scan results\n", dev->name); @@ -1193,8 +1193,8 @@ static void orinoco_send_bssid_wevent(struct orinoco_private *priv) union iwreq_data wrqu; int err; - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, - ETH_ALEN, NULL, wrqu.ap_addr.sa_data); + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, + ETH_ALEN, NULL, wrqu.ap_addr.sa_data); if (err != 0) return; @@ -1216,8 +1216,8 @@ static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv) if (!priv->has_wpa) return; - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO, - sizeof(buf), NULL, &buf); + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO, + sizeof(buf), NULL, &buf); if (err != 0) return; @@ -1246,8 +1246,9 @@ static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv) if (!priv->has_wpa) return; - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO, - sizeof(buf), NULL, &buf); + err = hw->ops->read_ltv(hw, USER_BAP, + HERMES_RID_CURRENT_ASSOC_RESP_INFO, + sizeof(buf), NULL, &buf); if (err != 0) return; @@ -1370,8 +1371,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) infofid = hermes_read_regn(hw, INFOFID); /* Read the info frame header - don't try too hard */ - err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info), - infofid, 0); + err = hw->ops->bap_pread(hw, IRQ_BAP, &info, sizeof(info), + infofid, 0); if (err) { printk(KERN_ERR "%s: error %d reading info frame. " "Frame dropped.\n", dev->name, err); @@ -1392,8 +1393,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) len = sizeof(tallies); } - err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len, - infofid, sizeof(info)); + err = hw->ops->bap_pread(hw, IRQ_BAP, &tallies, len, + infofid, sizeof(info)); if (err) break; @@ -1428,8 +1429,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) break; } - err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len, - infofid, sizeof(info)); + err = hw->ops->bap_pread(hw, IRQ_BAP, &linkstatus, len, + infofid, sizeof(info)); if (err) break; newstatus = le16_to_cpu(linkstatus.linkstatus); @@ -1493,8 +1494,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) } /* Read scan data */ - err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len, - infofid, sizeof(info)); + err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) buf, len, + infofid, sizeof(info)); if (err) { kfree(buf); qabort_scan(priv); @@ -1546,8 +1547,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) break; /* Read scan data */ - err = hermes_bap_pread(hw, IRQ_BAP, (void *) bss, len, - infofid, sizeof(info)); + err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) bss, len, + infofid, sizeof(info)); if (err) kfree(bss); else @@ -1646,7 +1647,7 @@ static int orinoco_reinit_firmware(struct orinoco_private *priv) struct hermes *hw = &priv->hw; int err; - err = hermes_init(hw); + err = hw->ops->init(hw); if (priv->do_fw_download && !err) { err = orinoco_download(priv); if (err) @@ -1983,7 +1984,7 @@ int orinoco_init(struct orinoco_private *priv) priv->nicbuf_size = IEEE80211_MAX_FRAME_LEN + ETH_HLEN; /* Initialize the firmware */ - err = hermes_init(hw); + err = hw->ops->init(hw); if (err != 0) { dev_err(dev, "Failed to initialize firmware (err = %d)\n", err); diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index d261423ecf62..b7fef250237b 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c @@ -457,7 +457,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { /* Fast channel change - no commit if successful */ hermes_t *hw = &priv->hw; - err = hermes_docmd_wait(hw, HERMES_CMD_TEST | + err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST | HERMES_TEST_SET_CHANNEL, chan, NULL); } @@ -1272,8 +1272,8 @@ static int orinoco_ioctl_getrid(struct net_device *dev, if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length, - extra); + err = hw->ops->read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length, + extra); if (err) goto out; -- cgit v1.2.3 From 593ef09c9e70c92c0d76c67a1c03a5d44d3aec82 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sat, 1 May 2010 14:05:39 +0100 Subject: orinoco: allow driver to specify netdev_ops Allow the main drivers to specify a custom version of the net_device_ops structure. This is required by orinoco_usb to supply a separate transmit function. Export existing net_device_ops callbacks so that the drivers can reuse some of the existing code. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/airport.c | 2 +- drivers/net/wireless/orinoco/main.c | 28 +++++++++++++++++++-------- drivers/net/wireless/orinoco/orinoco.h | 11 ++++++++++- drivers/net/wireless/orinoco/orinoco_cs.c | 2 +- drivers/net/wireless/orinoco/orinoco_nortel.c | 2 +- drivers/net/wireless/orinoco/orinoco_pci.c | 2 +- drivers/net/wireless/orinoco/orinoco_plx.c | 2 +- drivers/net/wireless/orinoco/orinoco_tmd.c | 2 +- drivers/net/wireless/orinoco/spectrum_cs.c | 2 +- 9 files changed, 37 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c index ea23c4fdbf62..7dac5adb6c1c 100644 --- a/drivers/net/wireless/orinoco/airport.c +++ b/drivers/net/wireless/orinoco/airport.c @@ -210,7 +210,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match) } /* Register an interface with the stack */ - if (orinoco_if_add(priv, phys_addr, card->irq) != 0) { + if (orinoco_if_add(priv, phys_addr, card->irq, NULL) != 0) { printk(KERN_ERR PFX "orinoco_if_add() failed\n"); goto failed; } diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index d90951f731ef..7acb6bc3ebff 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -253,7 +253,7 @@ void set_port_type(struct orinoco_private *priv) /* Device methods */ /********************************************************************/ -static int orinoco_open(struct net_device *dev) +int orinoco_open(struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); unsigned long flags; @@ -271,8 +271,9 @@ static int orinoco_open(struct net_device *dev) return err; } +EXPORT_SYMBOL(orinoco_open); -static int orinoco_stop(struct net_device *dev) +int orinoco_stop(struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); int err = 0; @@ -290,15 +291,17 @@ static int orinoco_stop(struct net_device *dev) return err; } +EXPORT_SYMBOL(orinoco_stop); -static struct net_device_stats *orinoco_get_stats(struct net_device *dev) +struct net_device_stats *orinoco_get_stats(struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); return &priv->stats; } +EXPORT_SYMBOL(orinoco_get_stats); -static void orinoco_set_multicast_list(struct net_device *dev) +void orinoco_set_multicast_list(struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); unsigned long flags; @@ -312,8 +315,9 @@ static void orinoco_set_multicast_list(struct net_device *dev) __orinoco_set_multicast_list(dev); orinoco_unlock(priv, &flags); } +EXPORT_SYMBOL(orinoco_set_multicast_list); -static int orinoco_change_mtu(struct net_device *dev, int new_mtu) +int orinoco_change_mtu(struct net_device *dev, int new_mtu) { struct orinoco_private *priv = ndev_priv(dev); @@ -329,6 +333,7 @@ static int orinoco_change_mtu(struct net_device *dev, int new_mtu) return 0; } +EXPORT_SYMBOL(orinoco_change_mtu); /********************************************************************/ /* Tx path */ @@ -614,7 +619,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) netif_wake_queue(dev); } -static void orinoco_tx_timeout(struct net_device *dev) +void orinoco_tx_timeout(struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); struct net_device_stats *stats = &priv->stats; @@ -629,6 +634,7 @@ static void orinoco_tx_timeout(struct net_device *dev) schedule_work(&priv->reset_work); } +EXPORT_SYMBOL(orinoco_tx_timeout); /********************************************************************/ /* Rx path (data frames) */ @@ -2192,7 +2198,8 @@ EXPORT_SYMBOL(alloc_orinocodev); */ int orinoco_if_add(struct orinoco_private *priv, unsigned long base_addr, - unsigned int irq) + unsigned int irq, + const struct net_device_ops *ops) { struct wiphy *wiphy = priv_to_wiphy(priv); struct wireless_dev *wdev; @@ -2211,12 +2218,17 @@ int orinoco_if_add(struct orinoco_private *priv, /* Setup / override net_device fields */ dev->ieee80211_ptr = wdev; - dev->netdev_ops = &orinoco_netdev_ops; dev->watchdog_timeo = HZ; /* 1 second timeout */ dev->wireless_handlers = &orinoco_handler_def; #ifdef WIRELESS_SPY dev->wireless_data = &priv->wireless_data; #endif + /* Default to standard ops if not set */ + if (ops) + dev->netdev_ops = ops; + else + dev->netdev_ops = &orinoco_netdev_ops; + /* we use the default eth_mac_addr for setting the MAC addr */ /* Reserve space in skb for the SNAP header */ diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index ff6b7b1d421d..f1901d6e6af8 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h @@ -190,12 +190,21 @@ extern void free_orinocodev(struct orinoco_private *priv); extern int orinoco_init(struct orinoco_private *priv); extern int orinoco_if_add(struct orinoco_private *priv, unsigned long base_addr, - unsigned int irq); + unsigned int irq, + const struct net_device_ops *ops); extern void orinoco_if_del(struct orinoco_private *priv); extern int orinoco_up(struct orinoco_private *priv); extern void orinoco_down(struct orinoco_private *priv); extern irqreturn_t orinoco_interrupt(int irq, void *dev_id); +/* Common ndo functions exported for reuse by orinoco_usb */ +int orinoco_open(struct net_device *dev); +int orinoco_stop(struct net_device *dev); +struct net_device_stats *orinoco_get_stats(struct net_device *dev); +void orinoco_set_multicast_list(struct net_device *dev); +int orinoco_change_mtu(struct net_device *dev, int new_mtu); +void orinoco_tx_timeout(struct net_device *dev); + /********************************************************************/ /* Locking and synchronization functions */ /********************************************************************/ diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index fdc961379170..525f74e68294 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -296,7 +296,7 @@ orinoco_cs_config(struct pcmcia_device *link) /* Register an interface with the stack */ if (orinoco_if_add(priv, link->io.BasePort1, - link->irq.AssignedIRQ) != 0) { + link->irq.AssignedIRQ, NULL) != 0) { printk(KERN_ERR PFX "orinoco_if_add() failed\n"); goto failed; } diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c index 075f446b3139..bc3ea0b67a4f 100644 --- a/drivers/net/wireless/orinoco/orinoco_nortel.c +++ b/drivers/net/wireless/orinoco/orinoco_nortel.c @@ -220,7 +220,7 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev, goto fail; } - err = orinoco_if_add(priv, 0, 0); + err = orinoco_if_add(priv, 0, 0, NULL); if (err) { printk(KERN_ERR PFX "orinoco_if_add() failed\n"); goto fail; diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c index bda5317cc596..468197f86673 100644 --- a/drivers/net/wireless/orinoco/orinoco_pci.c +++ b/drivers/net/wireless/orinoco/orinoco_pci.c @@ -170,7 +170,7 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, goto fail; } - err = orinoco_if_add(priv, 0, 0); + err = orinoco_if_add(priv, 0, 0, NULL); if (err) { printk(KERN_ERR PFX "orinoco_if_add() failed\n"); goto fail; diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c index e0d5874ab42f..9358f4d2307b 100644 --- a/drivers/net/wireless/orinoco/orinoco_plx.c +++ b/drivers/net/wireless/orinoco/orinoco_plx.c @@ -259,7 +259,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, goto fail; } - err = orinoco_if_add(priv, 0, 0); + err = orinoco_if_add(priv, 0, 0, NULL); if (err) { printk(KERN_ERR PFX "orinoco_if_add() failed\n"); goto fail; diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c index 88cbc7902aa0..784605f0af15 100644 --- a/drivers/net/wireless/orinoco/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco/orinoco_tmd.c @@ -156,7 +156,7 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, goto fail; } - err = orinoco_if_add(priv, 0, 0); + err = orinoco_if_add(priv, 0, 0, NULL); if (err) { printk(KERN_ERR PFX "orinoco_if_add() failed\n"); goto fail; diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index 59bda240fdc2..77b58717d185 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c @@ -374,7 +374,7 @@ spectrum_cs_config(struct pcmcia_device *link) /* Register an interface with the stack */ if (orinoco_if_add(priv, link->io.BasePort1, - link->irq.AssignedIRQ) != 0) { + link->irq.AssignedIRQ, NULL) != 0) { printk(KERN_ERR PFX "orinoco_if_add() failed\n"); goto failed; } -- cgit v1.2.3 From bcad6e80f3fb0d6724c3814cf32258bbcf1d67db Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sat, 1 May 2010 14:05:40 +0100 Subject: orinoco: encapsulate driver locking Local bus and USB drivers will need to do locking differently. The original orinoco_usb patches had a boolean variable controlling whether spin_lock_bh was used, or irq based locking. This version provides wrappers for the lock functions and the drivers specify the functions pointers needed. This will introduce a performance penalty, but I'm not expecting it to be noticable. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/airport.c | 4 ++-- drivers/net/wireless/orinoco/hermes.c | 28 +++++++++++++++++++++++++++- drivers/net/wireless/orinoco/hermes.h | 4 ++++ drivers/net/wireless/orinoco/main.c | 20 ++++++++++---------- drivers/net/wireless/orinoco/orinoco.h | 16 +++++++++++++--- drivers/net/wireless/orinoco/orinoco_cs.c | 4 ++-- drivers/net/wireless/orinoco/spectrum_cs.c | 4 ++-- 7 files changed, 60 insertions(+), 20 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c index 7dac5adb6c1c..9bcee10c9308 100644 --- a/drivers/net/wireless/orinoco/airport.c +++ b/drivers/net/wireless/orinoco/airport.c @@ -77,9 +77,9 @@ airport_resume(struct macio_dev *mdev) enable_irq(card->irq); - spin_lock_irqsave(&priv->lock, flags); + priv->hw.ops->lock_irqsave(&priv->lock, &flags); err = orinoco_up(priv); - spin_unlock_irqrestore(&priv->lock, flags); + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags); return err; } diff --git a/drivers/net/wireless/orinoco/hermes.c b/drivers/net/wireless/orinoco/hermes.c index a7df5240779c..845693fb25f3 100644 --- a/drivers/net/wireless/orinoco/hermes.c +++ b/drivers/net/wireless/orinoco/hermes.c @@ -529,6 +529,28 @@ static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, return err; } +static void hermes_lock_irqsave(spinlock_t *lock, + unsigned long *flags) __acquires(lock) +{ + spin_lock_irqsave(lock, *flags); +} + +static void hermes_unlock_irqrestore(spinlock_t *lock, + unsigned long *flags) __releases(lock) +{ + spin_unlock_irqrestore(lock, *flags); +} + +static void hermes_lock_irq(spinlock_t *lock) __acquires(lock) +{ + spin_lock_irq(lock); +} + +static void hermes_unlock_irq(spinlock_t *lock) __releases(lock) +{ + spin_unlock_irq(lock); +} + /* Hermes operations for local buses */ static const struct hermes_ops hermes_ops_local = { .init = hermes_init, @@ -538,5 +560,9 @@ static const struct hermes_ops hermes_ops_local = { .read_ltv = hermes_read_ltv, .write_ltv = hermes_write_ltv, .bap_pread = hermes_bap_pread, - .bap_pwrite = hermes_bap_pwrite + .bap_pwrite = hermes_bap_pwrite, + .lock_irqsave = hermes_lock_irqsave, + .unlock_irqrestore = hermes_unlock_irqrestore, + .lock_irq = hermes_lock_irq, + .unlock_irq = hermes_unlock_irq, }; diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h index 18b268c54dfe..9e21ecdb4e70 100644 --- a/drivers/net/wireless/orinoco/hermes.h +++ b/drivers/net/wireless/orinoco/hermes.h @@ -393,6 +393,10 @@ struct hermes_ops { u16 id, u16 offset); int (*bap_pwrite)(struct hermes *hw, int bap, const void *buf, int len, u16 id, u16 offset); + void (*lock_irqsave)(spinlock_t *lock, unsigned long *flags); + void (*unlock_irqrestore)(spinlock_t *lock, unsigned long *flags); + void (*lock_irq)(spinlock_t *lock); + void (*unlock_irq)(spinlock_t *lock); }; /* Basic control structure */ diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 7acb6bc3ebff..36c4ba865c7c 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -281,13 +281,13 @@ int orinoco_stop(struct net_device *dev) /* We mustn't use orinoco_lock() here, because we need to be able to close the interface even if hw_unavailable is set (e.g. as we're released after a PC Card removal) */ - spin_lock_irq(&priv->lock); + orinoco_lock_irq(priv); priv->open = 0; err = __orinoco_down(priv); - spin_unlock_irq(&priv->lock); + orinoco_unlock_irq(priv); return err; } @@ -1741,7 +1741,7 @@ void orinoco_reset(struct work_struct *work) } /* This has to be called from user context */ - spin_lock_irq(&priv->lock); + orinoco_lock_irq(priv); priv->hw_unavailable--; @@ -1756,7 +1756,7 @@ void orinoco_reset(struct work_struct *work) dev->trans_start = jiffies; } - spin_unlock_irq(&priv->lock); + orinoco_unlock_irq(priv); return; disable: @@ -2073,9 +2073,9 @@ int orinoco_init(struct orinoco_private *priv) /* Make the hardware available, as long as it hasn't been * removed elsewhere (e.g. by PCMCIA hot unplug) */ - spin_lock_irq(&priv->lock); + orinoco_lock_irq(priv); priv->hw_unavailable--; - spin_unlock_irq(&priv->lock); + orinoco_unlock_irq(priv); dev_dbg(dev, "Ready\n"); @@ -2317,7 +2317,7 @@ int orinoco_up(struct orinoco_private *priv) unsigned long flags; int err; - spin_lock_irqsave(&priv->lock, flags); + priv->hw.ops->lock_irqsave(&priv->lock, &flags); err = orinoco_reinit_firmware(priv); if (err) { @@ -2337,7 +2337,7 @@ int orinoco_up(struct orinoco_private *priv) } exit: - spin_unlock_irqrestore(&priv->lock, flags); + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags); return 0; } @@ -2349,7 +2349,7 @@ void orinoco_down(struct orinoco_private *priv) unsigned long flags; int err; - spin_lock_irqsave(&priv->lock, flags); + priv->hw.ops->lock_irqsave(&priv->lock, &flags); err = __orinoco_down(priv); if (err) printk(KERN_WARNING "%s: Error %d downing interface\n", @@ -2357,7 +2357,7 @@ void orinoco_down(struct orinoco_private *priv) netif_device_detach(dev); priv->hw_unavailable++; - spin_unlock_irqrestore(&priv->lock, flags); + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags); } EXPORT_SYMBOL(orinoco_down); diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index f1901d6e6af8..80a1386ce0b4 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h @@ -212,11 +212,11 @@ void orinoco_tx_timeout(struct net_device *dev); static inline int orinoco_lock(struct orinoco_private *priv, unsigned long *flags) { - spin_lock_irqsave(&priv->lock, *flags); + priv->hw.ops->lock_irqsave(&priv->lock, flags); if (priv->hw_unavailable) { DEBUG(1, "orinoco_lock() called with hw_unavailable (dev=%p)\n", priv->ndev); - spin_unlock_irqrestore(&priv->lock, *flags); + priv->hw.ops->unlock_irqrestore(&priv->lock, flags); return -EBUSY; } return 0; @@ -225,7 +225,17 @@ static inline int orinoco_lock(struct orinoco_private *priv, static inline void orinoco_unlock(struct orinoco_private *priv, unsigned long *flags) { - spin_unlock_irqrestore(&priv->lock, *flags); + priv->hw.ops->unlock_irqrestore(&priv->lock, flags); +} + +static inline void orinoco_lock_irq(struct orinoco_private *priv) +{ + priv->hw.ops->lock_irq(&priv->lock); +} + +static inline void orinoco_unlock_irq(struct orinoco_private *priv) +{ + priv->hw.ops->unlock_irq(&priv->lock); } /*** Navigate from net_device to orinoco_private ***/ diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index 525f74e68294..f99b13ba92b3 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -327,9 +327,9 @@ orinoco_cs_release(struct pcmcia_device *link) /* We're committed to taking the device away now, so mark the * hardware as unavailable */ - spin_lock_irqsave(&priv->lock, flags); + priv->hw.ops->lock_irqsave(&priv->lock, &flags); priv->hw_unavailable++; - spin_unlock_irqrestore(&priv->lock, flags); + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags); pcmcia_disable_device(link); if (priv->hw.iobase) diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index 77b58717d185..b4f68ef771e4 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c @@ -405,9 +405,9 @@ spectrum_cs_release(struct pcmcia_device *link) /* We're committed to taking the device away now, so mark the * hardware as unavailable */ - spin_lock_irqsave(&priv->lock, flags); + priv->hw.ops->lock_irqsave(&priv->lock, &flags); priv->hw_unavailable++; - spin_unlock_irqrestore(&priv->lock, flags); + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags); pcmcia_disable_device(link); if (priv->hw.iobase) -- cgit v1.2.3 From 9afac70a7305817b22327ac23cf2d0eb72388229 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sat, 1 May 2010 14:05:41 +0100 Subject: orinoco: add orinoco_usb driver This driver uses the core orinoco modules for the bulk of the functionality. The low level hermes routines (for local bus cards) are replaced, the driver supplies its own ndo_xmit_start function, and locking is done with the _bh variant. Some recent functionality is not available to the USB cards yet (firmware loading and WPA). Out-of-tree driver originally written by Manuel Estrada Sainz. Thanks to Mark Davis for supplying hardware to test the updates. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/Kconfig | 7 + drivers/net/wireless/orinoco/Makefile | 1 + drivers/net/wireless/orinoco/hermes.h | 1 + drivers/net/wireless/orinoco/main.c | 6 +- drivers/net/wireless/orinoco/orinoco.h | 3 + drivers/net/wireless/orinoco/orinoco_usb.c | 1680 ++++++++++++++++++++++++++++ 6 files changed, 1696 insertions(+), 2 deletions(-) create mode 100644 drivers/net/wireless/orinoco/orinoco_usb.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/orinoco/Kconfig b/drivers/net/wireless/orinoco/Kconfig index 6116b546861d..60819bcf4377 100644 --- a/drivers/net/wireless/orinoco/Kconfig +++ b/drivers/net/wireless/orinoco/Kconfig @@ -132,3 +132,10 @@ config PCMCIA_SPECTRUM This driver requires firmware download on startup. Utilities for downloading Symbol firmware are available at + +config ORINOCO_USB + tristate "Agere Orinoco USB support" + depends on USB && HERMES + select FW_LOADER + ---help--- + This driver is for USB versions of the Agere Orinoco card. diff --git a/drivers/net/wireless/orinoco/Makefile b/drivers/net/wireless/orinoco/Makefile index e6452698eba9..bfdefb85abcd 100644 --- a/drivers/net/wireless/orinoco/Makefile +++ b/drivers/net/wireless/orinoco/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o +obj-$(CONFIG_ORINOCO_USB) += orinoco_usb.o # Orinoco should be endian clean. ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h index 9e21ecdb4e70..aed14ff2d235 100644 --- a/drivers/net/wireless/orinoco/hermes.h +++ b/drivers/net/wireless/orinoco/hermes.h @@ -407,6 +407,7 @@ typedef struct hermes { #define HERMES_32BIT_REGSPACING 1 u16 inten; /* Which interrupts should be enabled? */ const struct hermes_ops *ops; + void *priv; } hermes_t; /* Register access convenience macros */ diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 36c4ba865c7c..7c9faa4c079e 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -797,7 +797,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, stats->rx_dropped++; } -static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) +void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) { struct orinoco_private *priv = ndev_priv(dev); struct net_device_stats *stats = &priv->stats; @@ -918,6 +918,7 @@ update_stats: out: kfree(desc); } +EXPORT_SYMBOL(__orinoco_ev_rx); static void orinoco_rx(struct net_device *dev, struct hermes_rx_descriptor *desc, @@ -1359,7 +1360,7 @@ static void orinoco_process_scan_results(struct work_struct *work) spin_unlock_irqrestore(&priv->scan_lock, flags); } -static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) +void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) { struct orinoco_private *priv = ndev_priv(dev); u16 infofid; @@ -1577,6 +1578,7 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) return; } +EXPORT_SYMBOL(__orinoco_ev_info); static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw) { diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index 80a1386ce0b4..e9f415a56d4d 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h @@ -197,6 +197,9 @@ extern int orinoco_up(struct orinoco_private *priv); extern void orinoco_down(struct orinoco_private *priv); extern irqreturn_t orinoco_interrupt(int irq, void *dev_id); +extern void __orinoco_ev_info(struct net_device *dev, hermes_t *hw); +extern void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw); + /* Common ndo functions exported for reuse by orinoco_usb */ int orinoco_open(struct net_device *dev); int orinoco_stop(struct net_device *dev); diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c new file mode 100644 index 000000000000..ce0069de5c46 --- /dev/null +++ b/drivers/net/wireless/orinoco/orinoco_usb.c @@ -0,0 +1,1680 @@ +/* + * USB Orinoco driver + * + * Copyright (c) 2003 Manuel Estrada Sainz + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License version 2 (the "GPL"), in + * which case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use your + * version of this file under the MPL, indicate your decision by + * deleting the provisions above and replace them with the notice and + * other provisions required by the GPL. If you do not delete the + * provisions above, a recipient may use your version of this file + * under either the MPL or the GPL. + * + * Queueing code based on linux-wlan-ng 0.2.1-pre5 + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * + * The license is the same as above. + * + * Initialy based on USB Skeleton driver - 0.7 + * + * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * NOTE: The original USB Skeleton driver is GPL, but all that code is + * gone so MPL/GPL applies. + */ + +#define DRIVER_NAME "orinoco_usb" +#define PFX DRIVER_NAME ": " + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "orinoco.h" + +#ifndef URB_ASYNC_UNLINK +#define URB_ASYNC_UNLINK 0 +#endif + +/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */ +static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; +#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2) + +struct header_struct { + /* 802.3 */ + u8 dest[ETH_ALEN]; + u8 src[ETH_ALEN]; + __be16 len; + /* 802.2 */ + u8 dsap; + u8 ssap; + u8 ctrl; + /* SNAP */ + u8 oui[3]; + __be16 ethertype; +} __attribute__ ((packed)); + +struct ez_usb_fw { + u16 size; + const u8 *code; +}; + +static struct ez_usb_fw firmware = { + .size = 0, + .code = NULL, +}; + +#ifdef CONFIG_USB_DEBUG +static int debug = 1; +#else +static int debug; +#endif + +/* Debugging macros */ +#undef dbg +#define dbg(format, arg...) \ + do { if (debug) printk(KERN_DEBUG PFX "%s: " format "\n", \ + __func__ , ## arg); } while (0) +#undef err +#define err(format, arg...) \ + do { printk(KERN_ERR PFX format "\n", ## arg); } while (0) + +/* Module paramaters */ +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug enabled or not"); + +MODULE_FIRMWARE("orinoco_ezusb_fw"); + +/* + * Under some conditions, the card gets stuck and stops paying attention + * to the world (i.e. data communication stalls) until we do something to + * it. Sending an INQ_TALLIES command seems to be enough and should be + * harmless otherwise. This behaviour has been observed when using the + * driver on a systemimager client during installation. In the past a + * timer was used to send INQ_TALLIES commands when there was no other + * activity, but it was troublesome and was removed. + */ + +#define USB_COMPAQ_VENDOR_ID 0x049f /* Compaq Computer Corp. */ +#define USB_COMPAQ_WL215_ID 0x001f /* Compaq WL215 USB Adapter */ +#define USB_COMPAQ_W200_ID 0x0076 /* Compaq W200 USB Adapter */ +#define USB_HP_WL215_ID 0x0082 /* Compaq WL215 USB Adapter */ + +#define USB_MELCO_VENDOR_ID 0x0411 +#define USB_BUFFALO_L11_ID 0x0006 /* BUFFALO WLI-USB-L11 */ +#define USB_BUFFALO_L11G_WR_ID 0x000B /* BUFFALO WLI-USB-L11G-WR */ +#define USB_BUFFALO_L11G_ID 0x000D /* BUFFALO WLI-USB-L11G */ + +#define USB_LUCENT_VENDOR_ID 0x047E /* Lucent Technologies */ +#define USB_LUCENT_ORINOCO_ID 0x0300 /* Lucent/Agere Orinoco USB Client */ + +#define USB_AVAYA8_VENDOR_ID 0x0D98 +#define USB_AVAYAE_VENDOR_ID 0x0D9E +#define USB_AVAYA_WIRELESS_ID 0x0300 /* Avaya Wireless USB Card */ + +#define USB_AGERE_VENDOR_ID 0x0D4E /* Agere Systems */ +#define USB_AGERE_MODEL0801_ID 0x1000 /* Wireless USB Card Model 0801 */ +#define USB_AGERE_MODEL0802_ID 0x1001 /* Wireless USB Card Model 0802 */ +#define USB_AGERE_REBRANDED_ID 0x047A /* WLAN USB Card */ + +#define USB_ELSA_VENDOR_ID 0x05CC +#define USB_ELSA_AIRLANCER_ID 0x3100 /* ELSA AirLancer USB-11 */ + +#define USB_LEGEND_VENDOR_ID 0x0E7C +#define USB_LEGEND_JOYNET_ID 0x0300 /* Joynet WLAN USB Card */ + +#define USB_SAMSUNG_VENDOR_ID 0x04E8 +#define USB_SAMSUNG_SEW2001U1_ID 0x5002 /* Samsung SEW-2001u Card */ +#define USB_SAMSUNG_SEW2001U2_ID 0x5B11 /* Samsung SEW-2001u Card */ +#define USB_SAMSUNG_SEW2003U_ID 0x7011 /* Samsung SEW-2003U Card */ + +#define USB_IGATE_VENDOR_ID 0x0681 +#define USB_IGATE_IGATE_11M_ID 0x0012 /* I-GATE 11M USB Card */ + +#define USB_FUJITSU_VENDOR_ID 0x0BF8 +#define USB_FUJITSU_E1100_ID 0x1002 /* connect2AIR WLAN E-1100 USB */ + +#define USB_2WIRE_VENDOR_ID 0x1630 +#define USB_2WIRE_WIRELESS_ID 0xff81 /* 2Wire Wireless USB adapter */ + + +#define EZUSB_REQUEST_FW_TRANS 0xA0 +#define EZUSB_REQUEST_TRIGER 0xAA +#define EZUSB_REQUEST_TRIG_AC 0xAC +#define EZUSB_CPUCS_REG 0x7F92 + +#define EZUSB_RID_TX 0x0700 +#define EZUSB_RID_RX 0x0701 +#define EZUSB_RID_INIT1 0x0702 +#define EZUSB_RID_ACK 0x0710 +#define EZUSB_RID_DOCMD 0x0860 + +/* Recognize info frames */ +#define EZUSB_IS_INFO(id) ((id >= 0xF000) && (id <= 0xF2FF)) + +#define EZUSB_MAGIC 0x0210 + +#define EZUSB_FRAME_DATA 1 +#define EZUSB_FRAME_CONTROL 2 + +#define DEF_TIMEOUT (3*HZ) + +#define BULK_BUF_SIZE 2048 + +#define FW_BUF_SIZE 64 +#define FW_VAR_OFFSET_PTR 0x359 +#define FW_VAR_VALUE 0 +#define FW_HOLE_START 0x100 +#define FW_HOLE_END 0x300 + +struct ezusb_packet { + __le16 magic; /* 0x0210 */ + u8 req_reply_count; + u8 ans_reply_count; + __le16 frame_type; /* 0x01 for data frames, 0x02 otherwise */ + __le16 size; /* transport size */ + __le16 crc; /* CRC up to here */ + __le16 hermes_len; + __le16 hermes_rid; + u8 data[0]; +} __attribute__ ((packed)); + +/* Table of devices that work or may work with this driver */ +static struct usb_device_id ezusb_table[] = { + {USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_COMPAQ_WL215_ID)}, + {USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_HP_WL215_ID)}, + {USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_COMPAQ_W200_ID)}, + {USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11_ID)}, + {USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11G_WR_ID)}, + {USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11G_ID)}, + {USB_DEVICE(USB_LUCENT_VENDOR_ID, USB_LUCENT_ORINOCO_ID)}, + {USB_DEVICE(USB_AVAYA8_VENDOR_ID, USB_AVAYA_WIRELESS_ID)}, + {USB_DEVICE(USB_AVAYAE_VENDOR_ID, USB_AVAYA_WIRELESS_ID)}, + {USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_MODEL0801_ID)}, + {USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_MODEL0802_ID)}, + {USB_DEVICE(USB_ELSA_VENDOR_ID, USB_ELSA_AIRLANCER_ID)}, + {USB_DEVICE(USB_LEGEND_VENDOR_ID, USB_LEGEND_JOYNET_ID)}, + {USB_DEVICE_VER(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2001U1_ID, + 0, 0)}, + {USB_DEVICE(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2001U2_ID)}, + {USB_DEVICE(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2003U_ID)}, + {USB_DEVICE(USB_IGATE_VENDOR_ID, USB_IGATE_IGATE_11M_ID)}, + {USB_DEVICE(USB_FUJITSU_VENDOR_ID, USB_FUJITSU_E1100_ID)}, + {USB_DEVICE(USB_2WIRE_VENDOR_ID, USB_2WIRE_WIRELESS_ID)}, + {USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_REBRANDED_ID)}, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, ezusb_table); + +/* Structure to hold all of our device specific stuff */ +struct ezusb_priv { + struct usb_device *udev; + struct net_device *dev; + struct mutex mtx; + spinlock_t req_lock; + struct list_head req_pending; + struct list_head req_active; + spinlock_t reply_count_lock; + u16 hermes_reg_fake[0x40]; + u8 *bap_buf; + struct urb *read_urb; + int read_pipe; + int write_pipe; + u8 reply_count; +}; + +enum ezusb_state { + EZUSB_CTX_START, + EZUSB_CTX_QUEUED, + EZUSB_CTX_REQ_SUBMITTED, + EZUSB_CTX_REQ_COMPLETE, + EZUSB_CTX_RESP_RECEIVED, + EZUSB_CTX_REQ_TIMEOUT, + EZUSB_CTX_REQ_FAILED, + EZUSB_CTX_RESP_TIMEOUT, + EZUSB_CTX_REQSUBMIT_FAIL, + EZUSB_CTX_COMPLETE, +}; + +struct request_context { + struct list_head list; + atomic_t refcount; + struct completion done; /* Signals that CTX is dead */ + int killed; + struct urb *outurb; /* OUT for req pkt */ + struct ezusb_priv *upriv; + struct ezusb_packet *buf; + int buf_length; + struct timer_list timer; /* Timeout handling */ + enum ezusb_state state; /* Current state */ + /* the RID that we will wait for */ + u16 out_rid; + u16 in_rid; +}; + + +/* Forward declarations */ +static void ezusb_ctx_complete(struct request_context *ctx); +static void ezusb_req_queue_run(struct ezusb_priv *upriv); +static void ezusb_bulk_in_callback(struct urb *urb); + +static inline u8 ezusb_reply_inc(u8 count) +{ + if (count < 0x7F) + return count + 1; + else + return 1; +} + +static void ezusb_request_context_put(struct request_context *ctx) +{ + if (!atomic_dec_and_test(&ctx->refcount)) + return; + + WARN_ON(!ctx->done.done); + BUG_ON(ctx->outurb->status == -EINPROGRESS); + BUG_ON(timer_pending(&ctx->timer)); + usb_free_urb(ctx->outurb); + kfree(ctx->buf); + kfree(ctx); +} + +static inline void ezusb_mod_timer(struct ezusb_priv *upriv, + struct timer_list *timer, + unsigned long expire) +{ + if (!upriv->udev) + return; + mod_timer(timer, expire); +} + +static void ezusb_request_timerfn(u_long _ctx) +{ + struct request_context *ctx = (void *) _ctx; + + ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK; + if (usb_unlink_urb(ctx->outurb) == -EINPROGRESS) { + ctx->state = EZUSB_CTX_REQ_TIMEOUT; + } else { + ctx->state = EZUSB_CTX_RESP_TIMEOUT; + dbg("couldn't unlink"); + atomic_inc(&ctx->refcount); + ctx->killed = 1; + ezusb_ctx_complete(ctx); + ezusb_request_context_put(ctx); + } +}; + +static struct request_context *ezusb_alloc_ctx(struct ezusb_priv *upriv, + u16 out_rid, u16 in_rid) +{ + struct request_context *ctx; + + ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC); + if (!ctx) + return NULL; + + memset(ctx, 0, sizeof(*ctx)); + + ctx->buf = kmalloc(BULK_BUF_SIZE, GFP_ATOMIC); + if (!ctx->buf) { + kfree(ctx); + return NULL; + } + ctx->outurb = usb_alloc_urb(0, GFP_ATOMIC); + if (!ctx->outurb) { + kfree(ctx->buf); + kfree(ctx); + return NULL; + } + + ctx->upriv = upriv; + ctx->state = EZUSB_CTX_START; + ctx->out_rid = out_rid; + ctx->in_rid = in_rid; + + atomic_set(&ctx->refcount, 1); + init_completion(&ctx->done); + + init_timer(&ctx->timer); + ctx->timer.function = ezusb_request_timerfn; + ctx->timer.data = (u_long) ctx; + return ctx; +} + + +/* Hopefully the real complete_all will soon be exported, in the mean + * while this should work. */ +static inline void ezusb_complete_all(struct completion *comp) +{ + complete(comp); + complete(comp); + complete(comp); + complete(comp); +} + +static void ezusb_ctx_complete(struct request_context *ctx) +{ + struct ezusb_priv *upriv = ctx->upriv; + unsigned long flags; + + spin_lock_irqsave(&upriv->req_lock, flags); + + list_del_init(&ctx->list); + if (upriv->udev) { + spin_unlock_irqrestore(&upriv->req_lock, flags); + ezusb_req_queue_run(upriv); + spin_lock_irqsave(&upriv->req_lock, flags); + } + + switch (ctx->state) { + case EZUSB_CTX_COMPLETE: + case EZUSB_CTX_REQSUBMIT_FAIL: + case EZUSB_CTX_REQ_FAILED: + case EZUSB_CTX_REQ_TIMEOUT: + case EZUSB_CTX_RESP_TIMEOUT: + spin_unlock_irqrestore(&upriv->req_lock, flags); + + if ((ctx->out_rid == EZUSB_RID_TX) && upriv->dev) { + struct net_device *dev = upriv->dev; + struct orinoco_private *priv = ndev_priv(dev); + struct net_device_stats *stats = &priv->stats; + + if (ctx->state != EZUSB_CTX_COMPLETE) + stats->tx_errors++; + else + stats->tx_packets++; + + netif_wake_queue(dev); + } + ezusb_complete_all(&ctx->done); + ezusb_request_context_put(ctx); + break; + + default: + spin_unlock_irqrestore(&upriv->req_lock, flags); + if (!upriv->udev) { + /* This is normal, as all request contexts get flushed + * when the device is disconnected */ + err("Called, CTX not terminating, but device gone"); + ezusb_complete_all(&ctx->done); + ezusb_request_context_put(ctx); + break; + } + + err("Called, CTX not in terminating state."); + /* Things are really bad if this happens. Just leak + * the CTX because it may still be linked to the + * queue or the OUT urb may still be active. + * Just leaking at least prevents an Oops or Panic. + */ + break; + } +} + +/** + * ezusb_req_queue_run: + * Description: + * Note: Only one active CTX at any one time, because there's no + * other (reliable) way to match the response URB to the correct + * CTX. + **/ +static void ezusb_req_queue_run(struct ezusb_priv *upriv) +{ + unsigned long flags; + struct request_context *ctx; + int result; + + spin_lock_irqsave(&upriv->req_lock, flags); + + if (!list_empty(&upriv->req_active)) + goto unlock; + + if (list_empty(&upriv->req_pending)) + goto unlock; + + ctx = + list_entry(upriv->req_pending.next, struct request_context, + list); + + if (!ctx->upriv->udev) + goto unlock; + + /* We need to split this off to avoid a race condition */ + list_move_tail(&ctx->list, &upriv->req_active); + + if (ctx->state == EZUSB_CTX_QUEUED) { + atomic_inc(&ctx->refcount); + result = usb_submit_urb(ctx->outurb, GFP_ATOMIC); + if (result) { + ctx->state = EZUSB_CTX_REQSUBMIT_FAIL; + + spin_unlock_irqrestore(&upriv->req_lock, flags); + + err("Fatal, failed to submit command urb." + " error=%d\n", result); + + ezusb_ctx_complete(ctx); + ezusb_request_context_put(ctx); + goto done; + } + + ctx->state = EZUSB_CTX_REQ_SUBMITTED; + ezusb_mod_timer(ctx->upriv, &ctx->timer, + jiffies + DEF_TIMEOUT); + } + + unlock: + spin_unlock_irqrestore(&upriv->req_lock, flags); + + done: + return; +} + +static void ezusb_req_enqueue_run(struct ezusb_priv *upriv, + struct request_context *ctx) +{ + unsigned long flags; + + spin_lock_irqsave(&upriv->req_lock, flags); + + if (!ctx->upriv->udev) { + spin_unlock_irqrestore(&upriv->req_lock, flags); + goto done; + } + atomic_inc(&ctx->refcount); + list_add_tail(&ctx->list, &upriv->req_pending); + spin_unlock_irqrestore(&upriv->req_lock, flags); + + ctx->state = EZUSB_CTX_QUEUED; + ezusb_req_queue_run(upriv); + + done: + return; +} + +static void ezusb_request_out_callback(struct urb *urb) +{ + unsigned long flags; + enum ezusb_state state; + struct request_context *ctx = urb->context; + struct ezusb_priv *upriv = ctx->upriv; + + spin_lock_irqsave(&upriv->req_lock, flags); + + del_timer(&ctx->timer); + + if (ctx->killed) { + spin_unlock_irqrestore(&upriv->req_lock, flags); + pr_warning("interrupt called with dead ctx"); + goto out; + } + + state = ctx->state; + + if (urb->status == 0) { + switch (state) { + case EZUSB_CTX_REQ_SUBMITTED: + if (ctx->in_rid) { + ctx->state = EZUSB_CTX_REQ_COMPLETE; + /* reply URB still pending */ + ezusb_mod_timer(upriv, &ctx->timer, + jiffies + DEF_TIMEOUT); + spin_unlock_irqrestore(&upriv->req_lock, + flags); + break; + } + /* fall through */ + case EZUSB_CTX_RESP_RECEIVED: + /* IN already received before this OUT-ACK */ + ctx->state = EZUSB_CTX_COMPLETE; + spin_unlock_irqrestore(&upriv->req_lock, flags); + ezusb_ctx_complete(ctx); + break; + + default: + spin_unlock_irqrestore(&upriv->req_lock, flags); + err("Unexpected state(0x%x, %d) in OUT URB", + state, urb->status); + break; + } + } else { + /* If someone cancels the OUT URB then its status + * should be either -ECONNRESET or -ENOENT. + */ + switch (state) { + case EZUSB_CTX_REQ_SUBMITTED: + case EZUSB_CTX_RESP_RECEIVED: + ctx->state = EZUSB_CTX_REQ_FAILED; + /* fall through */ + + case EZUSB_CTX_REQ_FAILED: + case EZUSB_CTX_REQ_TIMEOUT: + spin_unlock_irqrestore(&upriv->req_lock, flags); + + ezusb_ctx_complete(ctx); + break; + + default: + spin_unlock_irqrestore(&upriv->req_lock, flags); + + err("Unexpected state(0x%x, %d) in OUT URB", + state, urb->status); + break; + } + } + out: + ezusb_request_context_put(ctx); +} + +static void ezusb_request_in_callback(struct ezusb_priv *upriv, + struct urb *urb) +{ + struct ezusb_packet *ans = urb->transfer_buffer; + struct request_context *ctx = NULL; + enum ezusb_state state; + unsigned long flags; + + /* Find the CTX on the active queue that requested this URB */ + spin_lock_irqsave(&upriv->req_lock, flags); + if (upriv->udev) { + struct list_head *item; + + list_for_each(item, &upriv->req_active) { + struct request_context *c; + int reply_count; + + c = list_entry(item, struct request_context, list); + reply_count = + ezusb_reply_inc(c->buf->req_reply_count); + if ((ans->ans_reply_count == reply_count) + && (le16_to_cpu(ans->hermes_rid) == c->in_rid)) { + ctx = c; + break; + } + dbg("Skipped (0x%x/0x%x) (%d/%d)", + le16_to_cpu(ans->hermes_rid), + c->in_rid, ans->ans_reply_count, reply_count); + } + } + + if (ctx == NULL) { + spin_unlock_irqrestore(&upriv->req_lock, flags); + err("%s: got unexpected RID: 0x%04X", __func__, + le16_to_cpu(ans->hermes_rid)); + ezusb_req_queue_run(upriv); + return; + } + + /* The data we want is in the in buffer, exchange */ + urb->transfer_buffer = ctx->buf; + ctx->buf = (void *) ans; + ctx->buf_length = urb->actual_length; + + state = ctx->state; + switch (state) { + case EZUSB_CTX_REQ_SUBMITTED: + /* We have received our response URB before + * our request has been acknowledged. Do NOT + * destroy our CTX yet, because our OUT URB + * is still alive ... + */ + ctx->state = EZUSB_CTX_RESP_RECEIVED; + spin_unlock_irqrestore(&upriv->req_lock, flags); + + /* Let the machine continue running. */ + break; + + case EZUSB_CTX_REQ_COMPLETE: + /* This is the usual path: our request + * has already been acknowledged, and + * we have now received the reply. + */ + ctx->state = EZUSB_CTX_COMPLETE; + + /* Stop the intimer */ + del_timer(&ctx->timer); + spin_unlock_irqrestore(&upriv->req_lock, flags); + + /* Call the completion handler */ + ezusb_ctx_complete(ctx); + break; + + default: + spin_unlock_irqrestore(&upriv->req_lock, flags); + + pr_warning("Matched IN URB, unexpected context state(0x%x)", + state); + /* Throw this CTX away and try submitting another */ + del_timer(&ctx->timer); + ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK; + usb_unlink_urb(ctx->outurb); + ezusb_req_queue_run(upriv); + break; + } /* switch */ +} + + +static void ezusb_req_ctx_wait(struct ezusb_priv *upriv, + struct request_context *ctx) +{ + switch (ctx->state) { + case EZUSB_CTX_QUEUED: + case EZUSB_CTX_REQ_SUBMITTED: + case EZUSB_CTX_REQ_COMPLETE: + case EZUSB_CTX_RESP_RECEIVED: + if (in_atomic()) { + /* If we get called from a timer, timeout timers don't + * get the chance to run themselves. So we make sure + * that we don't sleep for ever */ + int msecs = DEF_TIMEOUT * (1000 / HZ); + while (!ctx->done.done && msecs--) + udelay(1000); + } else { + wait_event_interruptible(ctx->done.wait, + ctx->done.done); + } + break; + default: + /* Done or failed - nothing to wait for */ + break; + } +} + +static inline u16 build_crc(struct ezusb_packet *data) +{ + u16 crc = 0; + u8 *bytes = (u8 *)data; + int i; + + for (i = 0; i < 8; i++) + crc = (crc << 1) + bytes[i]; + + return crc; +} + +/** + * ezusb_fill_req: + * + * if data == NULL and length > 0 the data is assumed to be already in + * the target buffer and only the header is filled. + * + */ +static int ezusb_fill_req(struct ezusb_packet *req, u16 length, u16 rid, + const void *data, u16 frame_type, u8 reply_count) +{ + int total_size = sizeof(*req) + length; + + BUG_ON(total_size > BULK_BUF_SIZE); + + req->magic = cpu_to_le16(EZUSB_MAGIC); + req->req_reply_count = reply_count; + req->ans_reply_count = 0; + req->frame_type = cpu_to_le16(frame_type); + req->size = cpu_to_le16(length + 4); + req->crc = cpu_to_le16(build_crc(req)); + req->hermes_len = cpu_to_le16(HERMES_BYTES_TO_RECLEN(length)); + req->hermes_rid = cpu_to_le16(rid); + if (data) + memcpy(req->data, data, length); + return total_size; +} + +static int ezusb_submit_in_urb(struct ezusb_priv *upriv) +{ + int retval = 0; + void *cur_buf = upriv->read_urb->transfer_buffer; + + if (upriv->read_urb->status == -EINPROGRESS) { + dbg("urb busy, not resubmiting"); + retval = -EBUSY; + goto exit; + } + usb_fill_bulk_urb(upriv->read_urb, upriv->udev, upriv->read_pipe, + cur_buf, BULK_BUF_SIZE, + ezusb_bulk_in_callback, upriv); + upriv->read_urb->transfer_flags = 0; + retval = usb_submit_urb(upriv->read_urb, GFP_ATOMIC); + if (retval) + err("%s submit failed %d", __func__, retval); + + exit: + return retval; +} + +static inline int ezusb_8051_cpucs(struct ezusb_priv *upriv, int reset) +{ + u8 res_val = reset; /* avoid argument promotion */ + + if (!upriv->udev) { + err("%s: !upriv->udev", __func__); + return -EFAULT; + } + return usb_control_msg(upriv->udev, + usb_sndctrlpipe(upriv->udev, 0), + EZUSB_REQUEST_FW_TRANS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | + USB_DIR_OUT, EZUSB_CPUCS_REG, 0, &res_val, + sizeof(res_val), DEF_TIMEOUT); +} + +static int ezusb_firmware_download(struct ezusb_priv *upriv, + struct ez_usb_fw *fw) +{ + u8 fw_buffer[FW_BUF_SIZE]; + int retval, addr; + int variant_offset; + + /* + * This byte is 1 and should be replaced with 0. The offset is + * 0x10AD in version 0.0.6. The byte in question should follow + * the end of the code pointed to by the jump in the beginning + * of the firmware. Also, it is read by code located at 0x358. + */ + variant_offset = be16_to_cpup((__be16 *) &fw->code[FW_VAR_OFFSET_PTR]); + if (variant_offset >= fw->size) { + printk(KERN_ERR PFX "Invalid firmware variant offset: " + "0x%04x\n", variant_offset); + retval = -EINVAL; + goto fail; + } + + retval = ezusb_8051_cpucs(upriv, 1); + if (retval < 0) + goto fail; + for (addr = 0; addr < fw->size; addr += FW_BUF_SIZE) { + /* 0x100-0x300 should be left alone, it contains card + * specific data, like USB enumeration information */ + if ((addr >= FW_HOLE_START) && (addr < FW_HOLE_END)) + continue; + + memcpy(fw_buffer, &fw->code[addr], FW_BUF_SIZE); + if (variant_offset >= addr && + variant_offset < addr + FW_BUF_SIZE) { + dbg("Patching card_variant byte at 0x%04X", + variant_offset); + fw_buffer[variant_offset - addr] = FW_VAR_VALUE; + } + retval = usb_control_msg(upriv->udev, + usb_sndctrlpipe(upriv->udev, 0), + EZUSB_REQUEST_FW_TRANS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE + | USB_DIR_OUT, + addr, 0x0, + fw_buffer, FW_BUF_SIZE, + DEF_TIMEOUT); + + if (retval < 0) + goto fail; + } + retval = ezusb_8051_cpucs(upriv, 0); + if (retval < 0) + goto fail; + + goto exit; + fail: + printk(KERN_ERR PFX "Firmware download failed, error %d\n", + retval); + exit: + return retval; +} + +static int ezusb_access_ltv(struct ezusb_priv *upriv, + struct request_context *ctx, + u16 length, const void *data, u16 frame_type, + void *ans_buff, int ans_size, u16 *ans_length) +{ + int req_size; + int retval = 0; + enum ezusb_state state; + + BUG_ON(in_irq()); + + if (!upriv->udev) { + dbg("Device disconnected"); + return -ENODEV; + } + + if (upriv->read_urb->status != -EINPROGRESS) + err("%s: in urb not pending", __func__); + + /* protect upriv->reply_count, guarantee sequential numbers */ + spin_lock_bh(&upriv->reply_count_lock); + req_size = ezusb_fill_req(ctx->buf, length, ctx->out_rid, data, + frame_type, upriv->reply_count); + usb_fill_bulk_urb(ctx->outurb, upriv->udev, upriv->write_pipe, + ctx->buf, req_size, + ezusb_request_out_callback, ctx); + + if (ctx->in_rid) + upriv->reply_count = ezusb_reply_inc(upriv->reply_count); + + ezusb_req_enqueue_run(upriv, ctx); + + spin_unlock_bh(&upriv->reply_count_lock); + + if (ctx->in_rid) + ezusb_req_ctx_wait(upriv, ctx); + + state = ctx->state; + switch (state) { + case EZUSB_CTX_COMPLETE: + retval = ctx->outurb->status; + break; + + case EZUSB_CTX_QUEUED: + case EZUSB_CTX_REQ_SUBMITTED: + if (!ctx->in_rid) + break; + default: + err("%s: Unexpected context state %d", __func__, + state); + /* fall though */ + case EZUSB_CTX_REQ_TIMEOUT: + case EZUSB_CTX_REQ_FAILED: + case EZUSB_CTX_RESP_TIMEOUT: + case EZUSB_CTX_REQSUBMIT_FAIL: + printk(KERN_ERR PFX "Access failed, resetting (state %d," + " reply_count %d)\n", state, upriv->reply_count); + upriv->reply_count = 0; + if (state == EZUSB_CTX_REQ_TIMEOUT + || state == EZUSB_CTX_RESP_TIMEOUT) { + printk(KERN_ERR PFX "ctx timed out\n"); + retval = -ETIMEDOUT; + } else { + printk(KERN_ERR PFX "ctx failed\n"); + retval = -EFAULT; + } + goto exit; + break; + } + if (ctx->in_rid) { + struct ezusb_packet *ans = ctx->buf; + int exp_len; + + if (ans->hermes_len != 0) + exp_len = le16_to_cpu(ans->hermes_len) * 2 + 12; + else + exp_len = 14; + + if (exp_len != ctx->buf_length) { + err("%s: length mismatch for RID 0x%04x: " + "expected %d, got %d", __func__, + ctx->in_rid, exp_len, ctx->buf_length); + retval = -EIO; + goto exit; + } + + if (ans_buff) + memcpy(ans_buff, ans->data, + min_t(int, exp_len, ans_size)); + if (ans_length) + *ans_length = le16_to_cpu(ans->hermes_len); + } + exit: + ezusb_request_context_put(ctx); + return retval; +} + +static int ezusb_write_ltv(hermes_t *hw, int bap, u16 rid, + u16 length, const void *data) +{ + struct ezusb_priv *upriv = hw->priv; + u16 frame_type; + struct request_context *ctx; + + if (length == 0) + return -EINVAL; + + length = HERMES_RECLEN_TO_BYTES(length); + + /* On memory mapped devices HERMES_RID_CNFGROUPADDRESSES can be + * set to be empty, but the USB bridge doesn't like it */ + if (length == 0) + return 0; + + ctx = ezusb_alloc_ctx(upriv, rid, EZUSB_RID_ACK); + if (!ctx) + return -ENOMEM; + + if (rid == EZUSB_RID_TX) + frame_type = EZUSB_FRAME_DATA; + else + frame_type = EZUSB_FRAME_CONTROL; + + return ezusb_access_ltv(upriv, ctx, length, data, frame_type, + NULL, 0, NULL); +} + +static int ezusb_read_ltv(hermes_t *hw, int bap, u16 rid, + unsigned bufsize, u16 *length, void *buf) +{ + struct ezusb_priv *upriv = hw->priv; + struct request_context *ctx; + + if ((bufsize < 0) || (bufsize % 2)) + return -EINVAL; + + ctx = ezusb_alloc_ctx(upriv, rid, rid); + if (!ctx) + return -ENOMEM; + + return ezusb_access_ltv(upriv, ctx, 0, NULL, EZUSB_FRAME_CONTROL, + buf, bufsize, length); +} + +static int ezusb_doicmd_wait(hermes_t *hw, u16 cmd, u16 parm0, u16 parm1, + u16 parm2, struct hermes_response *resp) +{ + struct ezusb_priv *upriv = hw->priv; + struct request_context *ctx; + + __le16 data[4] = { + cpu_to_le16(cmd), + cpu_to_le16(parm0), + cpu_to_le16(parm1), + cpu_to_le16(parm2), + }; + dbg("0x%04X, parm0 0x%04X, parm1 0x%04X, parm2 0x%04X", + cmd, parm0, parm1, parm2); + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_DOCMD, EZUSB_RID_ACK); + if (!ctx) + return -ENOMEM; + + return ezusb_access_ltv(upriv, ctx, sizeof(data), &data, + EZUSB_FRAME_CONTROL, NULL, 0, NULL); +} + +static int ezusb_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, + struct hermes_response *resp) +{ + struct ezusb_priv *upriv = hw->priv; + struct request_context *ctx; + + __le16 data[4] = { + cpu_to_le16(cmd), + cpu_to_le16(parm0), + 0, + 0, + }; + dbg("0x%04X, parm0 0x%04X", cmd, parm0); + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_DOCMD, EZUSB_RID_ACK); + if (!ctx) + return -ENOMEM; + + return ezusb_access_ltv(upriv, ctx, sizeof(data), &data, + EZUSB_FRAME_CONTROL, NULL, 0, NULL); +} + +static int ezusb_bap_pread(struct hermes *hw, int bap, + void *buf, int len, u16 id, u16 offset) +{ + struct ezusb_priv *upriv = hw->priv; + struct ezusb_packet *ans = (void *) upriv->read_urb->transfer_buffer; + int actual_length = upriv->read_urb->actual_length; + + if (id == EZUSB_RID_RX) { + if ((sizeof(*ans) + offset + len) > actual_length) { + printk(KERN_ERR PFX "BAP read beyond buffer end " + "in rx frame\n"); + return -EINVAL; + } + memcpy(buf, ans->data + offset, len); + return 0; + } + + if (EZUSB_IS_INFO(id)) { + /* Include 4 bytes for length/type */ + if ((sizeof(*ans) + offset + len - 4) > actual_length) { + printk(KERN_ERR PFX "BAP read beyond buffer end " + "in info frame\n"); + return -EFAULT; + } + memcpy(buf, ans->data + offset - 4, len); + } else { + printk(KERN_ERR PFX "Unexpected fid 0x%04x\n", id); + return -EINVAL; + } + + return 0; +} + +static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct orinoco_private *priv = ndev_priv(dev); + struct net_device_stats *stats = &priv->stats; + struct ezusb_priv *upriv = priv->card; + int err = 0; + char *p; + struct ethhdr *eh; + int len, data_len, data_off; + __le16 tx_control; + unsigned long flags; + struct request_context *ctx; + u8 *buf; + int tx_size; + + if (!netif_running(dev)) { + printk(KERN_ERR "%s: Tx on stopped device!\n", + dev->name); + return NETDEV_TX_BUSY; + } + + if (netif_queue_stopped(dev)) { + printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", + dev->name); + return NETDEV_TX_BUSY; + } + + if (orinoco_lock(priv, &flags) != 0) { + printk(KERN_ERR + "%s: orinoco_xmit() called while hw_unavailable\n", + dev->name); + return NETDEV_TX_BUSY; + } + + if (!netif_carrier_ok(dev) || + (priv->iw_mode == NL80211_IFTYPE_MONITOR)) { + /* Oops, the firmware hasn't established a connection, + silently drop the packet (this seems to be the + safest approach). */ + stats->tx_errors++; + orinoco_unlock(priv, &flags); + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0); + if (!ctx) + goto fail; + + memset(ctx->buf, 0, BULK_BUF_SIZE); + buf = ctx->buf->data; + + /* Length of the packet body */ + /* FIXME: what if the skb is smaller than this? */ + len = max_t(int, skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN); + + eh = (struct ethhdr *) skb->data; + + tx_control = cpu_to_le16(0); + memcpy(buf, &tx_control, sizeof(tx_control)); + buf += sizeof(tx_control); + /* Encapsulate Ethernet-II frames */ + if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ + struct header_struct *hdr = (void *) buf; + buf += sizeof(*hdr); + data_len = len; + data_off = sizeof(tx_control) + sizeof(*hdr); + p = skb->data + ETH_HLEN; + + /* 802.3 header */ + memcpy(hdr->dest, eh->h_dest, ETH_ALEN); + memcpy(hdr->src, eh->h_source, ETH_ALEN); + hdr->len = htons(data_len + ENCAPS_OVERHEAD); + + /* 802.2 header */ + memcpy(&hdr->dsap, &encaps_hdr, sizeof(encaps_hdr)); + + hdr->ethertype = eh->h_proto; + } else { /* IEEE 802.3 frame */ + data_len = len + ETH_HLEN; + data_off = sizeof(tx_control); + p = skb->data; + } + + memcpy(buf, p, data_len); + buf += data_len; + + /* Finally, we actually initiate the send */ + netif_stop_queue(dev); + + /* The card may behave better if we send evenly sized usb transfers */ + tx_size = ALIGN(buf - ctx->buf->data, 2); + + err = ezusb_access_ltv(upriv, ctx, tx_size, NULL, + EZUSB_FRAME_DATA, NULL, 0, NULL); + + if (err) { + netif_start_queue(dev); + if (net_ratelimit()) + printk(KERN_ERR "%s: Error %d transmitting packet\n", + dev->name, err); + stats->tx_errors++; + goto fail; + } + + dev->trans_start = jiffies; + stats->tx_bytes += data_off + data_len; + + orinoco_unlock(priv, &flags); + + dev_kfree_skb(skb); + + return NETDEV_TX_OK; + + fail: + orinoco_unlock(priv, &flags); + return NETDEV_TX_BUSY; +} + +static int ezusb_allocate(struct hermes *hw, u16 size, u16 *fid) +{ + *fid = EZUSB_RID_TX; + return 0; +} + + +static int ezusb_hard_reset(struct orinoco_private *priv) +{ + struct ezusb_priv *upriv = priv->card; + int retval = ezusb_8051_cpucs(upriv, 1); + + if (retval < 0) { + err("Failed to reset"); + return retval; + } + + retval = ezusb_8051_cpucs(upriv, 0); + if (retval < 0) { + err("Failed to unreset"); + return retval; + } + + dbg("sending control message"); + retval = usb_control_msg(upriv->udev, + usb_sndctrlpipe(upriv->udev, 0), + EZUSB_REQUEST_TRIGER, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | + USB_DIR_OUT, 0x0, 0x0, NULL, 0, + DEF_TIMEOUT); + if (retval < 0) { + err("EZUSB_REQUEST_TRIGER failed retval %d", retval); + return retval; + } +#if 0 + dbg("Sending EZUSB_REQUEST_TRIG_AC"); + retval = usb_control_msg(upriv->udev, + usb_sndctrlpipe(upriv->udev, 0), + EZUSB_REQUEST_TRIG_AC, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | + USB_DIR_OUT, 0x00FA, 0x0, NULL, 0, + DEF_TIMEOUT); + if (retval < 0) { + err("EZUSB_REQUEST_TRIG_AC failed retval %d", retval); + return retval; + } +#endif + + return 0; +} + + +static int ezusb_init(hermes_t *hw) +{ + struct ezusb_priv *upriv = hw->priv; + int retval; + + BUG_ON(in_interrupt()); + BUG_ON(!upriv); + + upriv->reply_count = 0; + /* Write the MAGIC number on the simulated registers to keep + * orinoco.c happy */ + hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC); + hermes_write_regn(hw, RXFID, EZUSB_RID_RX); + + usb_kill_urb(upriv->read_urb); + ezusb_submit_in_urb(upriv); + + retval = ezusb_write_ltv(hw, 0, EZUSB_RID_INIT1, + HERMES_BYTES_TO_RECLEN(2), "\x10\x00"); + if (retval < 0) { + printk(KERN_ERR PFX "EZUSB_RID_INIT1 error %d\n", retval); + return retval; + } + + retval = ezusb_docmd_wait(hw, HERMES_CMD_INIT, 0, NULL); + if (retval < 0) { + printk(KERN_ERR PFX "HERMES_CMD_INIT error %d\n", retval); + return retval; + } + + return 0; +} + +static void ezusb_bulk_in_callback(struct urb *urb) +{ + struct ezusb_priv *upriv = (struct ezusb_priv *) urb->context; + struct ezusb_packet *ans = urb->transfer_buffer; + u16 crc; + u16 hermes_rid; + + if (upriv->udev == NULL) { + dbg("disconnected"); + return; + } + + if (urb->status == -ETIMEDOUT) { + /* When a device gets unplugged we get this every time + * we resubmit, flooding the logs. Since we don't use + * USB timeouts, it shouldn't happen any other time*/ + pr_warning("%s: urb timed out, not resubmiting", __func__); + return; + } + if (urb->status == -ECONNABORTED) { + pr_warning("%s: connection abort, resubmiting urb", + __func__); + goto resubmit; + } + if ((urb->status == -EILSEQ) + || (urb->status == -ENOENT) + || (urb->status == -ECONNRESET)) { + dbg("status %d, not resubmiting", urb->status); + return; + } + if (urb->status) + dbg("status: %d length: %d", + urb->status, urb->actual_length); + if (urb->actual_length < sizeof(*ans)) { + err("%s: short read, ignoring", __func__); + goto resubmit; + } + crc = build_crc(ans); + if (le16_to_cpu(ans->crc) != crc) { + err("CRC error, ignoring packet"); + goto resubmit; + } + + hermes_rid = le16_to_cpu(ans->hermes_rid); + if ((hermes_rid != EZUSB_RID_RX) && !EZUSB_IS_INFO(hermes_rid)) { + ezusb_request_in_callback(upriv, urb); + } else if (upriv->dev) { + struct net_device *dev = upriv->dev; + struct orinoco_private *priv = ndev_priv(dev); + hermes_t *hw = &priv->hw; + + if (hermes_rid == EZUSB_RID_RX) { + __orinoco_ev_rx(dev, hw); + } else { + hermes_write_regn(hw, INFOFID, + le16_to_cpu(ans->hermes_rid)); + __orinoco_ev_info(dev, hw); + } + } + + resubmit: + if (upriv->udev) + ezusb_submit_in_urb(upriv); +} + +static inline void ezusb_delete(struct ezusb_priv *upriv) +{ + struct net_device *dev; + struct list_head *item; + struct list_head *tmp_item; + unsigned long flags; + + BUG_ON(in_interrupt()); + BUG_ON(!upriv); + + dev = upriv->dev; + mutex_lock(&upriv->mtx); + + upriv->udev = NULL; /* No timer will be rearmed from here */ + + usb_kill_urb(upriv->read_urb); + + spin_lock_irqsave(&upriv->req_lock, flags); + list_for_each_safe(item, tmp_item, &upriv->req_active) { + struct request_context *ctx; + int err; + + ctx = list_entry(item, struct request_context, list); + atomic_inc(&ctx->refcount); + + ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK; + err = usb_unlink_urb(ctx->outurb); + + spin_unlock_irqrestore(&upriv->req_lock, flags); + if (err == -EINPROGRESS) + wait_for_completion(&ctx->done); + + del_timer_sync(&ctx->timer); + /* FIXME: there is an slight chance for the irq handler to + * be running */ + if (!list_empty(&ctx->list)) + ezusb_ctx_complete(ctx); + + ezusb_request_context_put(ctx); + spin_lock_irqsave(&upriv->req_lock, flags); + } + spin_unlock_irqrestore(&upriv->req_lock, flags); + + list_for_each_safe(item, tmp_item, &upriv->req_pending) + ezusb_ctx_complete(list_entry(item, + struct request_context, list)); + + if (upriv->read_urb->status == -EINPROGRESS) + printk(KERN_ERR PFX "Some URB in progress\n"); + + mutex_unlock(&upriv->mtx); + + kfree(upriv->read_urb->transfer_buffer); + if (upriv->bap_buf != NULL) + kfree(upriv->bap_buf); + if (upriv->read_urb != NULL) + usb_free_urb(upriv->read_urb); + if (upriv->dev) { + struct orinoco_private *priv = ndev_priv(upriv->dev); + orinoco_if_del(priv); + free_orinocodev(priv); + } +} + +static void ezusb_lock_irqsave(spinlock_t *lock, + unsigned long *flags) __acquires(lock) +{ + spin_lock_bh(lock); +} + +static void ezusb_unlock_irqrestore(spinlock_t *lock, + unsigned long *flags) __releases(lock) +{ + spin_unlock_bh(lock); +} + +static void ezusb_lock_irq(spinlock_t *lock) __acquires(lock) +{ + spin_lock_bh(lock); +} + +static void ezusb_unlock_irq(spinlock_t *lock) __releases(lock) +{ + spin_unlock_bh(lock); +} + +static const struct hermes_ops ezusb_ops = { + .init = ezusb_init, + .cmd_wait = ezusb_docmd_wait, + .init_cmd_wait = ezusb_doicmd_wait, + .allocate = ezusb_allocate, + .read_ltv = ezusb_read_ltv, + .write_ltv = ezusb_write_ltv, + .bap_pread = ezusb_bap_pread, + .lock_irqsave = ezusb_lock_irqsave, + .unlock_irqrestore = ezusb_unlock_irqrestore, + .lock_irq = ezusb_lock_irq, + .unlock_irq = ezusb_unlock_irq, +}; + +static const struct net_device_ops ezusb_netdev_ops = { + .ndo_open = orinoco_open, + .ndo_stop = orinoco_stop, + .ndo_start_xmit = ezusb_xmit, + .ndo_set_multicast_list = orinoco_set_multicast_list, + .ndo_change_mtu = orinoco_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_tx_timeout = orinoco_tx_timeout, + .ndo_get_stats = orinoco_get_stats, +}; + +static int ezusb_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(interface); + struct orinoco_private *priv; + hermes_t *hw; + struct ezusb_priv *upriv = NULL; + struct usb_interface_descriptor *iface_desc; + struct usb_endpoint_descriptor *ep; + const struct firmware *fw_entry; + int retval = 0; + int i; + + priv = alloc_orinocodev(sizeof(*upriv), &udev->dev, + ezusb_hard_reset, NULL); + if (!priv) { + err("Couldn't allocate orinocodev"); + goto exit; + } + + hw = &priv->hw; + + upriv = priv->card; + + mutex_init(&upriv->mtx); + spin_lock_init(&upriv->reply_count_lock); + + spin_lock_init(&upriv->req_lock); + INIT_LIST_HEAD(&upriv->req_pending); + INIT_LIST_HEAD(&upriv->req_active); + + upriv->udev = udev; + + hw->iobase = (void __force __iomem *) &upriv->hermes_reg_fake; + hw->reg_spacing = HERMES_16BIT_REGSPACING; + hw->priv = upriv; + hw->ops = &ezusb_ops; + + /* set up the endpoint information */ + /* check out the endpoints */ + + iface_desc = &interface->altsetting[0].desc; + for (i = 0; i < iface_desc->bNumEndpoints; ++i) { + ep = &interface->altsetting[0].endpoint[i].desc; + + if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + == USB_DIR_IN) && + ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_BULK)) { + /* we found a bulk in endpoint */ + if (upriv->read_urb != NULL) { + pr_warning("Found a second bulk in ep, ignored"); + continue; + } + + upriv->read_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!upriv->read_urb) { + err("No free urbs available"); + goto error; + } + if (le16_to_cpu(ep->wMaxPacketSize) != 64) + pr_warning("bulk in: wMaxPacketSize!= 64"); + if (ep->bEndpointAddress != (2 | USB_DIR_IN)) + pr_warning("bulk in: bEndpointAddress: %d", + ep->bEndpointAddress); + upriv->read_pipe = usb_rcvbulkpipe(udev, + ep-> + bEndpointAddress); + upriv->read_urb->transfer_buffer = + kmalloc(BULK_BUF_SIZE, GFP_KERNEL); + if (!upriv->read_urb->transfer_buffer) { + err("Couldn't allocate IN buffer"); + goto error; + } + } + + if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + == USB_DIR_OUT) && + ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_BULK)) { + /* we found a bulk out endpoint */ + if (upriv->bap_buf != NULL) { + pr_warning("Found a second bulk out ep, ignored"); + continue; + } + + if (le16_to_cpu(ep->wMaxPacketSize) != 64) + pr_warning("bulk out: wMaxPacketSize != 64"); + if (ep->bEndpointAddress != 2) + pr_warning("bulk out: bEndpointAddress: %d", + ep->bEndpointAddress); + upriv->write_pipe = usb_sndbulkpipe(udev, + ep-> + bEndpointAddress); + upriv->bap_buf = kmalloc(BULK_BUF_SIZE, GFP_KERNEL); + if (!upriv->bap_buf) { + err("Couldn't allocate bulk_out_buffer"); + goto error; + } + } + } + if (!upriv->bap_buf || !upriv->read_urb) { + err("Didn't find the required bulk endpoints"); + goto error; + } + + if (request_firmware(&fw_entry, "orinoco_ezusb_fw", + &interface->dev) == 0) { + firmware.size = fw_entry->size; + firmware.code = fw_entry->data; + } + if (firmware.size && firmware.code) { + ezusb_firmware_download(upriv, &firmware); + } else { + err("No firmware to download"); + goto error; + } + + if (ezusb_hard_reset(priv) < 0) { + err("Cannot reset the device"); + goto error; + } + + /* If the firmware is already downloaded orinoco.c will call + * ezusb_init but if the firmware is not already there, that will make + * the kernel very unstable, so we try initializing here and quit in + * case of error */ + if (ezusb_init(hw) < 0) { + err("Couldn't initialize the device"); + err("Firmware may not be downloaded or may be wrong."); + goto error; + } + + /* Initialise the main driver */ + if (orinoco_init(priv) != 0) { + err("orinoco_init() failed\n"); + goto error; + } + + if (orinoco_if_add(priv, 0, 0, &ezusb_netdev_ops) != 0) { + upriv->dev = NULL; + err("%s: orinoco_if_add() failed", __func__); + goto error; + } + upriv->dev = priv->ndev; + + goto exit; + + error: + ezusb_delete(upriv); + if (upriv->dev) { + /* upriv->dev was 0, so ezusb_delete() didn't free it */ + free_orinocodev(priv); + } + upriv = NULL; + retval = -EFAULT; + exit: + if (fw_entry) { + firmware.code = NULL; + firmware.size = 0; + release_firmware(fw_entry); + } + usb_set_intfdata(interface, upriv); + return retval; +} + + +static void ezusb_disconnect(struct usb_interface *intf) +{ + struct ezusb_priv *upriv = usb_get_intfdata(intf); + usb_set_intfdata(intf, NULL); + ezusb_delete(upriv); + printk(KERN_INFO PFX "Disconnected\n"); +} + + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver orinoco_driver = { + .name = DRIVER_NAME, + .probe = ezusb_probe, + .disconnect = ezusb_disconnect, + .id_table = ezusb_table, +}; + +/* Can't be declared "const" or the whole __initdata section will + * become const */ +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION + " (Manuel Estrada Sainz)"; + +static int __init ezusb_module_init(void) +{ + int err; + + printk(KERN_DEBUG "%s\n", version); + + /* register this driver with the USB subsystem */ + err = usb_register(&orinoco_driver); + if (err < 0) { + printk(KERN_ERR PFX "usb_register failed, error %d\n", + err); + return err; + } + + return 0; +} + +static void __exit ezusb_module_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&orinoco_driver); +} + + +module_init(ezusb_module_init); +module_exit(ezusb_module_exit); + +MODULE_AUTHOR("Manuel Estrada Sainz"); +MODULE_DESCRIPTION + ("Driver for Orinoco wireless LAN cards using EZUSB bridge"); +MODULE_LICENSE("Dual MPL/GPL"); -- cgit v1.2.3 From fc97431a50962e66c052ec6909d4b2582efd3554 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sat, 1 May 2010 14:05:42 +0100 Subject: orinoco_usb: avoid in_atomic We expect to be either in process contect or soft interrupt context. So use in_softirq instead. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/orinoco_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index ce0069de5c46..8e1b31cbd375 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c @@ -701,7 +701,7 @@ static void ezusb_req_ctx_wait(struct ezusb_priv *upriv, case EZUSB_CTX_REQ_SUBMITTED: case EZUSB_CTX_REQ_COMPLETE: case EZUSB_CTX_RESP_RECEIVED: - if (in_atomic()) { + if (in_softirq()) { /* If we get called from a timer, timeout timers don't * get the chance to run themselves. So we make sure * that we don't sleep for ever */ -- cgit v1.2.3 From 07cefe7ac983374ee4c369f1d4aee3093bf3b44f Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sat, 1 May 2010 14:05:43 +0100 Subject: orinoco_usb: implement fw download This involves some refactorring of the common fw download code to substitute ezusb versions of various functions. Note that WPA-enabled firmwares (9.xx series) will not work fully with orinoco_usb yet. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/fw.c | 8 +- drivers/net/wireless/orinoco/hermes.c | 208 ++++++++++++++++++++++++ drivers/net/wireless/orinoco/hermes.h | 7 + drivers/net/wireless/orinoco/hermes_dld.c | 243 ++--------------------------- drivers/net/wireless/orinoco/orinoco_usb.c | 120 ++++++++++++++ drivers/net/wireless/orinoco/spectrum_cs.c | 1 + 6 files changed, 349 insertions(+), 238 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c index 07c79e5de32d..94c0853f6814 100644 --- a/drivers/net/wireless/orinoco/fw.c +++ b/drivers/net/wireless/orinoco/fw.c @@ -121,7 +121,7 @@ orinoco_dl_firmware(struct orinoco_private *priv, dev_dbg(dev, "Attempting to download firmware %s\n", firmware); /* Read current plug data */ - err = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 0); + err = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size); dev_dbg(dev, "Read PDA returned %d\n", err); if (err) goto free; @@ -148,7 +148,7 @@ orinoco_dl_firmware(struct orinoco_private *priv, } /* Enable aux port to allow programming */ - err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point)); + err = hw->ops->program_init(hw, le32_to_cpu(hdr->entry_point)); dev_dbg(dev, "Program init returned %d\n", err); if (err != 0) goto abort; @@ -176,7 +176,7 @@ orinoco_dl_firmware(struct orinoco_private *priv, goto abort; /* Tell card we've finished */ - err = hermesi_program_end(hw); + err = hw->ops->program_end(hw); dev_dbg(dev, "Program end returned %d\n", err); if (err != 0) goto abort; @@ -223,7 +223,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw, if (!pda) return -ENOMEM; - ret = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 1); + ret = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size); if (ret) goto free; } diff --git a/drivers/net/wireless/orinoco/hermes.c b/drivers/net/wireless/orinoco/hermes.c index 845693fb25f3..6c6a23e08df6 100644 --- a/drivers/net/wireless/orinoco/hermes.c +++ b/drivers/net/wireless/orinoco/hermes.c @@ -51,6 +51,26 @@ #define CMD_COMPL_TIMEOUT (20000) /* in iterations of ~10us */ #define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */ +/* + * AUX port access. To unlock the AUX port write the access keys to the + * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL + * register. Then read it and make sure it's HERMES_AUX_ENABLED. + */ +#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */ +#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */ +#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */ +#define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */ + +#define HERMES_AUX_PW0 0xFE01 +#define HERMES_AUX_PW1 0xDC23 +#define HERMES_AUX_PW2 0xBA45 + +/* HERMES_CMD_DOWNLD */ +#define HERMES_PROGRAM_DISABLE (0x0000 | HERMES_CMD_DOWNLD) +#define HERMES_PROGRAM_ENABLE_VOLATILE (0x0100 | HERMES_CMD_DOWNLD) +#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD) +#define HERMES_PROGRAM_NON_VOLATILE (0x0300 | HERMES_CMD_DOWNLD) + /* * Debugging helpers */ @@ -170,6 +190,7 @@ void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing) hw->iobase = address; hw->reg_spacing = reg_spacing; hw->inten = 0x0; + hw->eeprom_pda = false; hw->ops = &hermes_ops_local; } EXPORT_SYMBOL(hermes_struct_init); @@ -529,6 +550,189 @@ static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, return err; } +/*** Hermes AUX control ***/ + +static inline void +hermes_aux_setaddr(hermes_t *hw, u32 addr) +{ + hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7)); + hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F)); +} + +static inline int +hermes_aux_control(hermes_t *hw, int enabled) +{ + int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED; + int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE; + int i; + + /* Already open? */ + if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state) + return 0; + + hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0); + hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1); + hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2); + hermes_write_reg(hw, HERMES_CONTROL, action); + + for (i = 0; i < 20; i++) { + udelay(10); + if (hermes_read_reg(hw, HERMES_CONTROL) == + desired_state) + return 0; + } + + return -EBUSY; +} + +/*** Hermes programming ***/ + +/* About to start programming data (Hermes I) + * offset is the entry point + * + * Spectrum_cs' Symbol fw does not require this + * wl_lkm Agere fw does + * Don't know about intersil + */ +static int hermesi_program_init(hermes_t *hw, u32 offset) +{ + int err; + + /* Disable interrupts?*/ + /*hw->inten = 0x0;*/ + /*hermes_write_regn(hw, INTEN, 0);*/ + /*hermes_set_irqmask(hw, 0);*/ + + /* Acknowledge any outstanding command */ + hermes_write_regn(hw, EVACK, 0xFFFF); + + /* Using init_cmd_wait rather than cmd_wait */ + err = hw->ops->init_cmd_wait(hw, + 0x0100 | HERMES_CMD_INIT, + 0, 0, 0, NULL); + if (err) + return err; + + err = hw->ops->init_cmd_wait(hw, + 0x0000 | HERMES_CMD_INIT, + 0, 0, 0, NULL); + if (err) + return err; + + err = hermes_aux_control(hw, 1); + pr_debug("AUX enable returned %d\n", err); + + if (err) + return err; + + pr_debug("Enabling volatile, EP 0x%08x\n", offset); + err = hw->ops->init_cmd_wait(hw, + HERMES_PROGRAM_ENABLE_VOLATILE, + offset & 0xFFFFu, + offset >> 16, + 0, + NULL); + pr_debug("PROGRAM_ENABLE returned %d\n", err); + + return err; +} + +/* Done programming data (Hermes I) + * + * Spectrum_cs' Symbol fw does not require this + * wl_lkm Agere fw does + * Don't know about intersil + */ +static int hermesi_program_end(hermes_t *hw) +{ + struct hermes_response resp; + int rc = 0; + int err; + + rc = hw->ops->cmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp); + + pr_debug("PROGRAM_DISABLE returned %d, " + "r0 0x%04x, r1 0x%04x, r2 0x%04x\n", + rc, resp.resp0, resp.resp1, resp.resp2); + + if ((rc == 0) && + ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD)) + rc = -EIO; + + err = hermes_aux_control(hw, 0); + pr_debug("AUX disable returned %d\n", err); + + /* Acknowledge any outstanding command */ + hermes_write_regn(hw, EVACK, 0xFFFF); + + /* Reinitialise, ignoring return */ + (void) hw->ops->init_cmd_wait(hw, 0x0000 | HERMES_CMD_INIT, + 0, 0, 0, NULL); + + return rc ? rc : err; +} + +static int hermes_program_bytes(struct hermes *hw, const char *data, + u32 addr, u32 len) +{ + /* wl lkm splits the programming into chunks of 2000 bytes. + * This restriction appears to come from USB. The PCMCIA + * adapters can program the whole lot in one go */ + hermes_aux_setaddr(hw, addr); + hermes_write_bytes(hw, HERMES_AUXDATA, data, len); + return 0; +} + +/* Read PDA from the adapter */ +static int hermes_read_pda(hermes_t *hw, __le16 *pda, u32 pda_addr, u16 pda_len) +{ + int ret; + u16 pda_size; + u16 data_len = pda_len; + __le16 *data = pda; + + if (hw->eeprom_pda) { + /* PDA of spectrum symbol is in eeprom */ + + /* Issue command to read EEPROM */ + ret = hw->ops->cmd_wait(hw, HERMES_CMD_READMIF, 0, NULL); + if (ret) + return ret; + } else { + /* wl_lkm does not include PDA size in the PDA area. + * We will pad the information into pda, so other routines + * don't have to be modified */ + pda[0] = cpu_to_le16(pda_len - 2); + /* Includes CFG_PROD_DATA but not itself */ + pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */ + data_len = pda_len - 4; + data = pda + 2; + } + + /* Open auxiliary port */ + ret = hermes_aux_control(hw, 1); + pr_debug("AUX enable returned %d\n", ret); + if (ret) + return ret; + + /* Read PDA */ + hermes_aux_setaddr(hw, pda_addr); + hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2); + + /* Close aux port */ + ret = hermes_aux_control(hw, 0); + pr_debug("AUX disable returned %d\n", ret); + + /* Check PDA length */ + pda_size = le16_to_cpu(pda[0]); + pr_debug("Actual PDA length %d, Max allowed %d\n", + pda_size, pda_len); + if (pda_size > pda_len) + return -EINVAL; + + return 0; +} + static void hermes_lock_irqsave(spinlock_t *lock, unsigned long *flags) __acquires(lock) { @@ -561,6 +765,10 @@ static const struct hermes_ops hermes_ops_local = { .write_ltv = hermes_write_ltv, .bap_pread = hermes_bap_pread, .bap_pwrite = hermes_bap_pwrite, + .read_pda = hermes_read_pda, + .program_init = hermesi_program_init, + .program_end = hermesi_program_end, + .program = hermes_program_bytes, .lock_irqsave = hermes_lock_irqsave, .unlock_irqrestore = hermes_unlock_irqrestore, .lock_irq = hermes_lock_irq, diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h index aed14ff2d235..9ca34e722b45 100644 --- a/drivers/net/wireless/orinoco/hermes.h +++ b/drivers/net/wireless/orinoco/hermes.h @@ -393,6 +393,12 @@ struct hermes_ops { u16 id, u16 offset); int (*bap_pwrite)(struct hermes *hw, int bap, const void *buf, int len, u16 id, u16 offset); + int (*read_pda)(struct hermes *hw, __le16 *pda, + u32 pda_addr, u16 pda_len); + int (*program_init)(struct hermes *hw, u32 entry_point); + int (*program_end)(struct hermes *hw); + int (*program)(struct hermes *hw, const char *buf, + u32 addr, u32 len); void (*lock_irqsave)(spinlock_t *lock, unsigned long *flags); void (*unlock_irqrestore)(spinlock_t *lock, unsigned long *flags); void (*lock_irq)(spinlock_t *lock); @@ -406,6 +412,7 @@ typedef struct hermes { #define HERMES_16BIT_REGSPACING 0 #define HERMES_32BIT_REGSPACING 1 u16 inten; /* Which interrupts should be enabled? */ + bool eeprom_pda; const struct hermes_ops *ops; void *priv; } hermes_t; diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c index 8f22e2026a82..6da85e75fce0 100644 --- a/drivers/net/wireless/orinoco/hermes_dld.c +++ b/drivers/net/wireless/orinoco/hermes_dld.c @@ -46,37 +46,11 @@ #define PFX "hermes_dld: " -/* - * AUX port access. To unlock the AUX port write the access keys to the - * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL - * register. Then read it and make sure it's HERMES_AUX_ENABLED. - */ -#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */ -#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */ -#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */ -#define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */ - -#define HERMES_AUX_PW0 0xFE01 -#define HERMES_AUX_PW1 0xDC23 -#define HERMES_AUX_PW2 0xBA45 - -/* HERMES_CMD_DOWNLD */ -#define HERMES_PROGRAM_DISABLE (0x0000 | HERMES_CMD_DOWNLD) -#define HERMES_PROGRAM_ENABLE_VOLATILE (0x0100 | HERMES_CMD_DOWNLD) -#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD) -#define HERMES_PROGRAM_NON_VOLATILE (0x0300 | HERMES_CMD_DOWNLD) - /* End markers used in dblocks */ #define PDI_END 0x00000000 /* End of PDA */ #define BLOCK_END 0xFFFFFFFF /* Last image block */ #define TEXT_END 0x1A /* End of text header */ -/* Limit the amout we try to download in a single shot. - * Size is in bytes. - */ -#define MAX_DL_SIZE 1024 -#define LIMIT_PROGRAM_SIZE 0 - /* * The following structures have little-endian fields denoted by * the leading underscore. Don't access them directly - use inline @@ -165,41 +139,6 @@ pdi_len(const struct pdi *pdi) return 2 * (le16_to_cpu(pdi->len) - 1); } -/*** Hermes AUX control ***/ - -static inline void -hermes_aux_setaddr(hermes_t *hw, u32 addr) -{ - hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7)); - hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F)); -} - -static inline int -hermes_aux_control(hermes_t *hw, int enabled) -{ - int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED; - int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE; - int i; - - /* Already open? */ - if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state) - return 0; - - hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0); - hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1); - hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2); - hermes_write_reg(hw, HERMES_CONTROL, action); - - for (i = 0; i < 20; i++) { - udelay(10); - if (hermes_read_reg(hw, HERMES_CONTROL) == - desired_state) - return 0; - } - - return -EBUSY; -} - /*** Plug Data Functions ***/ /* @@ -271,62 +210,7 @@ hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr, return -EINVAL; /* do the actual plugging */ - hermes_aux_setaddr(hw, pdr_addr(pdr)); - hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi)); - - return 0; -} - -/* Read PDA from the adapter */ -int hermes_read_pda(hermes_t *hw, - __le16 *pda, - u32 pda_addr, - u16 pda_len, - int use_eeprom) /* can we get this into hw? */ -{ - int ret; - u16 pda_size; - u16 data_len = pda_len; - __le16 *data = pda; - - if (use_eeprom) { - /* PDA of spectrum symbol is in eeprom */ - - /* Issue command to read EEPROM */ - ret = hw->ops->cmd_wait(hw, HERMES_CMD_READMIF, 0, NULL); - if (ret) - return ret; - } else { - /* wl_lkm does not include PDA size in the PDA area. - * We will pad the information into pda, so other routines - * don't have to be modified */ - pda[0] = cpu_to_le16(pda_len - 2); - /* Includes CFG_PROD_DATA but not itself */ - pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */ - data_len = pda_len - 4; - data = pda + 2; - } - - /* Open auxiliary port */ - ret = hermes_aux_control(hw, 1); - pr_debug(PFX "AUX enable returned %d\n", ret); - if (ret) - return ret; - - /* read PDA from EEPROM */ - hermes_aux_setaddr(hw, pda_addr); - hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2); - - /* Close aux port */ - ret = hermes_aux_control(hw, 0); - pr_debug(PFX "AUX disable returned %d\n", ret); - - /* Check PDA length */ - pda_size = le16_to_cpu(pda[0]); - pr_debug(PFX "Actual PDA length %d, Max allowed %d\n", - pda_size, pda_len); - if (pda_size > pda_len) - return -EINVAL; + hw->ops->program(hw, pdi->data, pdr_addr(pdr), pdi_len(pdi)); return 0; } @@ -389,101 +273,13 @@ hermes_blocks_length(const char *first_block, const void *end) /*** Hermes programming ***/ -/* About to start programming data (Hermes I) - * offset is the entry point - * - * Spectrum_cs' Symbol fw does not require this - * wl_lkm Agere fw does - * Don't know about intersil - */ -int hermesi_program_init(hermes_t *hw, u32 offset) -{ - int err; - - /* Disable interrupts?*/ - /*hw->inten = 0x0;*/ - /*hermes_write_regn(hw, INTEN, 0);*/ - /*hermes_set_irqmask(hw, 0);*/ - - /* Acknowledge any outstanding command */ - hermes_write_regn(hw, EVACK, 0xFFFF); - - /* Using init_cmd_wait rather than cmd_wait */ - err = hw->ops->init_cmd_wait(hw, - 0x0100 | HERMES_CMD_INIT, - 0, 0, 0, NULL); - if (err) - return err; - - err = hw->ops->init_cmd_wait(hw, - 0x0000 | HERMES_CMD_INIT, - 0, 0, 0, NULL); - if (err) - return err; - - err = hermes_aux_control(hw, 1); - pr_debug(PFX "AUX enable returned %d\n", err); - - if (err) - return err; - - pr_debug(PFX "Enabling volatile, EP 0x%08x\n", offset); - err = hw->ops->init_cmd_wait(hw, - HERMES_PROGRAM_ENABLE_VOLATILE, - offset & 0xFFFFu, - offset >> 16, - 0, - NULL); - pr_debug(PFX "PROGRAM_ENABLE returned %d\n", err); - - return err; -} - -/* Done programming data (Hermes I) - * - * Spectrum_cs' Symbol fw does not require this - * wl_lkm Agere fw does - * Don't know about intersil - */ -int hermesi_program_end(hermes_t *hw) -{ - struct hermes_response resp; - int rc = 0; - int err; - - rc = hw->ops->cmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp); - - pr_debug(PFX "PROGRAM_DISABLE returned %d, " - "r0 0x%04x, r1 0x%04x, r2 0x%04x\n", - rc, resp.resp0, resp.resp1, resp.resp2); - - if ((rc == 0) && - ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD)) - rc = -EIO; - - err = hermes_aux_control(hw, 0); - pr_debug(PFX "AUX disable returned %d\n", err); - - /* Acknowledge any outstanding command */ - hermes_write_regn(hw, EVACK, 0xFFFF); - - /* Reinitialise, ignoring return */ - (void) hw->ops->init_cmd_wait(hw, 0x0000 | HERMES_CMD_INIT, - 0, 0, 0, NULL); - - return rc ? rc : err; -} - /* Program the data blocks */ int hermes_program(hermes_t *hw, const char *first_block, const void *end) { const struct dblock *blk; u32 blkaddr; u32 blklen; -#if LIMIT_PROGRAM_SIZE - u32 addr; - u32 len; -#endif + int err = 0; blk = (const struct dblock *) first_block; @@ -498,30 +294,10 @@ int hermes_program(hermes_t *hw, const char *first_block, const void *end) pr_debug(PFX "Programming block of length %d " "to address 0x%08x\n", blklen, blkaddr); -#if !LIMIT_PROGRAM_SIZE - /* wl_lkm driver splits this into writes of 2000 bytes */ - hermes_aux_setaddr(hw, blkaddr); - hermes_write_bytes(hw, HERMES_AUXDATA, blk->data, - blklen); -#else - len = (blklen < MAX_DL_SIZE) ? blklen : MAX_DL_SIZE; - addr = blkaddr; - - while (addr < (blkaddr + blklen)) { - pr_debug(PFX "Programming subblock of length %d " - "to address 0x%08x. Data @ %p\n", - len, addr, &blk->data[addr - blkaddr]); - - hermes_aux_setaddr(hw, addr); - hermes_write_bytes(hw, HERMES_AUXDATA, - &blk->data[addr - blkaddr], - len); - - addr += len; - len = ((blkaddr + blklen - addr) < MAX_DL_SIZE) ? - (blkaddr + blklen - addr) : MAX_DL_SIZE; - } -#endif + err = hw->ops->program(hw, blk->data, blkaddr, blklen); + if (err) + break; + blk = (const struct dblock *) &blk->data[blklen]; if ((void *) blk > (end - sizeof(*blk))) @@ -530,7 +306,7 @@ int hermes_program(hermes_t *hw, const char *first_block, const void *end) blkaddr = dblock_addr(blk); blklen = dblock_len(blk); } - return 0; + return err; } /*** Default plugging data for Hermes I ***/ @@ -690,9 +466,8 @@ int hermes_apply_pda_with_defaults(hermes_t *hw, if ((pdi_len(pdi) == pdr_len(pdr)) && ((void *) pdi->data + pdi_len(pdi) < pda_end)) { /* do the actual plugging */ - hermes_aux_setaddr(hw, pdr_addr(pdr)); - hermes_write_bytes(hw, HERMES_AUXDATA, - pdi->data, pdi_len(pdi)); + hw->ops->program(hw, pdi->data, pdr_addr(pdr), + pdi_len(pdi)); } } diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index 8e1b31cbd375..e22093359f3e 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c @@ -184,6 +184,11 @@ MODULE_FIRMWARE("orinoco_ezusb_fw"); #define EZUSB_RID_RX 0x0701 #define EZUSB_RID_INIT1 0x0702 #define EZUSB_RID_ACK 0x0710 +#define EZUSB_RID_READ_PDA 0x0800 +#define EZUSB_RID_PROG_INIT 0x0852 +#define EZUSB_RID_PROG_SET_ADDR 0x0853 +#define EZUSB_RID_PROG_BYTES 0x0854 +#define EZUSB_RID_PROG_END 0x0855 #define EZUSB_RID_DOCMD 0x0860 /* Recognize info frames */ @@ -198,6 +203,8 @@ MODULE_FIRMWARE("orinoco_ezusb_fw"); #define BULK_BUF_SIZE 2048 +#define MAX_DL_SIZE (BULK_BUF_SIZE - sizeof(struct ezusb_packet)) + #define FW_BUF_SIZE 64 #define FW_VAR_OFFSET_PTR 0x359 #define FW_VAR_VALUE 0 @@ -1077,6 +1084,115 @@ static int ezusb_bap_pread(struct hermes *hw, int bap, return 0; } +static int ezusb_read_pda(struct hermes *hw, __le16 *pda, + u32 pda_addr, u16 pda_len) +{ + struct ezusb_priv *upriv = hw->priv; + struct request_context *ctx; + __le16 data[] = { + cpu_to_le16(pda_addr & 0xffff), + cpu_to_le16(pda_len - 4) + }; + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_READ_PDA, EZUSB_RID_READ_PDA); + if (!ctx) + return -ENOMEM; + + /* wl_lkm does not include PDA size in the PDA area. + * We will pad the information into pda, so other routines + * don't have to be modified */ + pda[0] = cpu_to_le16(pda_len - 2); + /* Includes CFG_PROD_DATA but not itself */ + pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */ + + return ezusb_access_ltv(upriv, ctx, sizeof(data), &data, + EZUSB_FRAME_CONTROL, &pda[2], pda_len - 4, + NULL); +} + +static int ezusb_program_init(struct hermes *hw, u32 entry_point) +{ + struct ezusb_priv *upriv = hw->priv; + struct request_context *ctx; + __le32 data = cpu_to_le32(entry_point); + + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_INIT, EZUSB_RID_ACK); + if (!ctx) + return -ENOMEM; + + return ezusb_access_ltv(upriv, ctx, sizeof(data), &data, + EZUSB_FRAME_CONTROL, NULL, 0, NULL); +} + +static int ezusb_program_end(struct hermes *hw) +{ + struct ezusb_priv *upriv = hw->priv; + struct request_context *ctx; + + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_END, EZUSB_RID_ACK); + if (!ctx) + return -ENOMEM; + + return ezusb_access_ltv(upriv, ctx, 0, NULL, + EZUSB_FRAME_CONTROL, NULL, 0, NULL); +} + +static int ezusb_program_bytes(struct hermes *hw, const char *buf, + u32 addr, u32 len) +{ + struct ezusb_priv *upriv = hw->priv; + struct request_context *ctx; + __le32 data = cpu_to_le32(addr); + int err; + + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_SET_ADDR, EZUSB_RID_ACK); + if (!ctx) + return -ENOMEM; + + err = ezusb_access_ltv(upriv, ctx, sizeof(data), &data, + EZUSB_FRAME_CONTROL, NULL, 0, NULL); + if (err) + return err; + + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_BYTES, EZUSB_RID_ACK); + if (!ctx) + return -ENOMEM; + + return ezusb_access_ltv(upriv, ctx, len, buf, + EZUSB_FRAME_CONTROL, NULL, 0, NULL); +} + +static int ezusb_program(struct hermes *hw, const char *buf, + u32 addr, u32 len) +{ + u32 ch_addr; + u32 ch_len; + int err = 0; + + /* We can only send 2048 bytes out of the bulk xmit at a time, + * so we have to split any programming into chunks of <2048 + * bytes. */ + + ch_len = (len < MAX_DL_SIZE) ? len : MAX_DL_SIZE; + ch_addr = addr; + + while (ch_addr < (addr + len)) { + pr_debug("Programming subblock of length %d " + "to address 0x%08x. Data @ %p\n", + ch_len, ch_addr, &buf[ch_addr - addr]); + + err = ezusb_program_bytes(hw, &buf[ch_addr - addr], + ch_addr, ch_len); + if (err) + break; + + ch_addr += ch_len; + ch_len = ((addr + len - ch_addr) < MAX_DL_SIZE) ? + (addr + len - ch_addr) : MAX_DL_SIZE; + } + + return err; +} + static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); @@ -1440,6 +1556,10 @@ static const struct hermes_ops ezusb_ops = { .read_ltv = ezusb_read_ltv, .write_ltv = ezusb_write_ltv, .bap_pread = ezusb_bap_pread, + .read_pda = ezusb_read_pda, + .program_init = ezusb_program_init, + .program_end = ezusb_program_end, + .program = ezusb_program, .lock_irqsave = ezusb_lock_irqsave, .unlock_irqrestore = ezusb_unlock_irqrestore, .lock_irq = ezusb_lock_irq, diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index b4f68ef771e4..9b1af4976bf5 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c @@ -349,6 +349,7 @@ spectrum_cs_config(struct pcmcia_device *link) goto failed; hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); + hw->eeprom_pda = true; /* * This actually configures the PCMCIA socket -- setting up -- cgit v1.2.3 From a75b4363eaafa99d909da4f1192322a78b074c73 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 1 May 2010 18:53:51 +0200 Subject: mac80211: allow controlling aggregation manually This allows enabling TX and disabling both TX and RX aggregation sessions manually in debugfs. It is very useful for debugging session initiation and teardown problems since with this you don't have to force a lot of traffic to get aggregation and thus have less data to analyse. Also, to debug mac80211 code itself, make hwsim "support" aggregation sessions. It will still just transfer the frame, but go through the setup and teardown handshakes. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index d016933d7573..ebcf43904291 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1299,7 +1299,8 @@ static int __init init_mac80211_hwsim(void) hw->flags = IEEE80211_HW_MFP_CAPABLE | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_STATIC_SMPS | - IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS; + IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | + IEEE80211_HW_AMPDU_AGGREGATION; /* ask mac80211 to reserve space for magic */ hw->vif_data_size = sizeof(struct hwsim_vif_priv); -- cgit v1.2.3 From 23ff98fc21615e324647af540a4ec1c24f993687 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 3 May 2010 09:21:14 +0200 Subject: mac80211_hwsim: fix double-scan detection Currently, hwsim will always detect a double scan after the first one has finished ... Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index ebcf43904291..62a739f6c37b 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1020,7 +1020,7 @@ static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw) mutex_lock(&hwsim->mutex); printk(KERN_DEBUG "hwsim sw_scan_complete\n"); - hwsim->scanning = true; + hwsim->scanning = false; mutex_unlock(&hwsim->mutex); } -- cgit v1.2.3 From 12ef116bf750c221e214e33c61e7f4c98300b5fd Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Mon, 3 May 2010 13:11:38 +0200 Subject: wireless: rt2x00: rt2800usb: be in sync with latest windows drivers. 0x07d1,0x3c17 D-Link Wireless N 150 USB Adapter DWA-125 0x1b75,0x3071 Ovislink Airlive WN-301USB 0x1d4d,0x0011 Pegatron Ralink RT3072 802.11b/g/n Wireless Lan USB Device 0x083a,0xf511 Arcadyan 802.11 USB Wireless LAN Card 0x13d3,0x3322 AzureWave 802.11 n/g/b USB Wireless LAN Card Signed-off-by: Xose Vazquez Perez Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6f2a945cd45c..2b79d6e58f40 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1023,7 +1023,7 @@ static struct usb_device_id rt2800usb_device_table[] = { #ifdef CONFIG_RT2800USB_UNKNOWN /* * Unclear what kind of devices these are (they aren't supported by the - * vendor driver). + * vendor linux driver). */ /* Amigo */ { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -1036,6 +1036,7 @@ static struct usb_device_id rt2800usb_device_table[] = { /* AzureWave */ { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3322), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Belkin */ { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Buffalo */ @@ -1054,6 +1055,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c17), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Encore */ { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Gemtek */ @@ -1070,11 +1072,13 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Motorola */ { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Ovislink */ + { USB_DEVICE(0x1b75, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Pegatron */ { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Planex */ { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Qcom */ @@ -1083,6 +1087,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xf511), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sweex */ { USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) }, -- cgit v1.2.3 From 52c773861895faaf544bd398c87ba10dff29f313 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 3 May 2010 16:12:39 -0400 Subject: iwmc3200wifi: fix busted iwm_debugfs_init definition Looks like we missed removing the return statement in the non-CONFIG_IWM_DEBUG dummy implementation of iwm_debugfs_init... Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/debug.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwmc3200wifi/debug.h b/drivers/net/wireless/iwmc3200wifi/debug.h index f98bf125a8ae..a0c13a49ab3c 100644 --- a/drivers/net/wireless/iwmc3200wifi/debug.h +++ b/drivers/net/wireless/iwmc3200wifi/debug.h @@ -116,10 +116,7 @@ struct iwm_debugfs { void iwm_debugfs_init(struct iwm_priv *iwm); void iwm_debugfs_exit(struct iwm_priv *iwm); #else -static inline void iwm_debugfs_init(struct iwm_priv *iwm) -{ - return 0; -} +static inline void iwm_debugfs_init(struct iwm_priv *iwm) {} static inline void iwm_debugfs_exit(struct iwm_priv *iwm) {} #endif -- cgit v1.2.3 From 3d79b2a9eeaa066b35c49fbb17e3156a3c482c3e Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Mon, 3 May 2010 10:55:07 -0700 Subject: iwlwifi: recalculate average tpt if not current We currently have this check as a BUG_ON, which is being hit by people. Previously it was an error with a recalculation if not current, return that code. The BUG_ON was introduced by: commit 3110bef78cb4282c58245bc8fd6d95d9ccb19749 Author: Guy Cohen Date: Tue Sep 9 10:54:54 2008 +0800 iwlwifi: Added support for 3 antennas ... the portion adding the BUG_ON is reverted since we are encountering the error and BUG_ON was created with assumption that error is not encountered. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index f01f242659c3..331c23a6c4e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2077,10 +2077,12 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, } /* Else we have enough samples; calculate estimate of * actual average throughput */ - - /* Sanity-check TPT calculations */ - BUG_ON(window->average_tpt != ((window->success_ratio * - tbl->expected_tpt[index] + 64) / 128)); + if (window->average_tpt != ((window->success_ratio * + tbl->expected_tpt[index] + 64) / 128)) { + IWL_ERR(priv, "expected_tpt should have been calculated by now\n"); + window->average_tpt = ((window->success_ratio * + tbl->expected_tpt[index] + 64) / 128); + } /* If we are searching for better modulation mode, check success. */ if (lq_sta->search_better_tbl && -- cgit v1.2.3 From c2661486ebacc9c2a86757d8ff1d40b3efe8a08b Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 3 May 2010 22:43:02 +0200 Subject: rt2x00: Remove rt2x00pci.h include from rt2800lib. PCI specific code has been remove quite some time ago. Signed-off-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 674609d1a727..7310f34cc12a 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -40,9 +40,6 @@ #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) #include "rt2x00usb.h" #endif -#if defined(CONFIG_RT2X00_LIB_PCI) || defined(CONFIG_RT2X00_LIB_PCI_MODULE) -#include "rt2x00pci.h" -#endif #include "rt2800lib.h" #include "rt2800.h" #include "rt2800usb.h" -- cgit v1.2.3 From 79a854f1e1a4482243fe4a2b199e199225b87bf6 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 3 May 2010 22:43:03 +0200 Subject: rt2x00: Enable RT30xx by default. Now that RT30xx support is at the same level as RT28xx support we can enable these devices by default. Signed-off-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 5239e082cd0f..eea1ef2f502b 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -87,7 +87,7 @@ if RT2800PCI config RT2800PCI_RT30XX bool "rt2800pci - Include support for rt30xx (PCI/PCIe/PCMCIA) devices" - default n + default y ---help--- This adds support for rt30xx wireless chipset family to the rt2800pci driver. @@ -156,7 +156,7 @@ if RT2800USB config RT2800USB_RT30XX bool "rt2800usb - Include support for rt30xx (USB) devices" - default n + default y ---help--- This adds support for rt30xx wireless chipset family to the rt2800usb driver. -- cgit v1.2.3 From a21ee724034b21d51d74eec8e426702a627eb465 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 3 May 2010 22:43:04 +0200 Subject: rt2x00: Fix HT40+/HT40- setting in rt2800. Inspection of the Ralink vendor driver shows that the TX_BAND_CFG register and BBP register 3 are about HT40- indication, not about HT40+ indication. Inverse the meaning of these fields in the code. Signed-off-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 4 ++-- drivers/net/wireless/rt2x00/rt2800lib.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 4c0b48173213..2aa03751c341 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -845,7 +845,7 @@ * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz */ #define TX_BAND_CFG 0x132c -#define TX_BAND_CFG_HT40_PLUS FIELD32(0x00000001) +#define TX_BAND_CFG_HT40_MINUS FIELD32(0x00000001) #define TX_BAND_CFG_A FIELD32(0x00000002) #define TX_BAND_CFG_BG FIELD32(0x00000004) @@ -1519,7 +1519,7 @@ struct mac_iveiv_entry { * BBP 3: RX Antenna */ #define BBP3_RX_ANTENNA FIELD8(0x18) -#define BBP3_HT40_PLUS FIELD8(0x20) +#define BBP3_HT40_MINUS FIELD8(0x20) /* * BBP 4: Bandwidth diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 7310f34cc12a..6d2c66d9b290 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -867,7 +867,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, } rt2800_register_read(rt2x00dev, TX_BAND_CFG, ®); - rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf)); + rt2x00_set_field32(®, TX_BAND_CFG_HT40_MINUS, conf_is_ht40_minus(conf)); rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14); rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14); rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg); @@ -900,7 +900,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2800_bbp_write(rt2x00dev, 4, bbp); rt2800_bbp_read(rt2x00dev, 3, &bbp); - rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); + rt2x00_set_field8(&bbp, BBP3_HT40_MINUS, conf_is_ht40_minus(conf)); rt2800_bbp_write(rt2x00dev, 3, bbp); if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { -- cgit v1.2.3 From df624ca5413d84b3082246de384823fbe8fed6e4 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 3 May 2010 22:43:05 +0200 Subject: rt2x00: Register frame length in TX entry descriptor instead of L2PAD. And use it consistently in the chipset drivers. Preparation for further clean ups. Signed-off-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 4 ++-- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2800pci.c | 2 +- drivers/net/wireless/rt2x00/rt2800usb.c | 2 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 6 ++---- drivers/net/wireless/rt2x00/rt2x00queue.h | 4 ++-- drivers/net/wireless/rt2x00/rt61pci.c | 5 +++-- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- 9 files changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 08a4789fc2d8..6f898913492a 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1017,8 +1017,8 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(entry_priv->desc, 1, word); rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, skb->len); - rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, skb->len); + rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, txdesc->length); + rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, txdesc->length); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 3, &word); diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d084d70e5fe2..d9b630455e7d 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1208,7 +1208,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); } diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index c1eec17fe186..c6e6e7b0ea53 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1071,7 +1071,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_NEW_SEQ, test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length); rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher); rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx); rt2x00_desc_write(txd, 0, word); diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 89281d78f04d..f08b6a37bf2d 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -663,7 +663,7 @@ static int rt2800pci_write_tx_data(struct queue_entry* entry, test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? txdesc->key_idx : 0xff); rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, - skb->len - txdesc->l2pad); + txdesc->length); rt2x00_set_field32(&word, TXWI_W1_PACKETID, skbdesc->entry->queue->qid + 1); rt2x00_desc_write(txwi, 1, word); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 2b79d6e58f40..67f8234f24d0 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -437,7 +437,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? txdesc->key_idx : 0xff); rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, - skb->len - txdesc->l2pad); + txdesc->length); rt2x00_set_field32(&word, TXWI_W1_PACKETID, skbdesc->entry->queue->qid + 1); rt2x00_desc_write(txwi, 1, word); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index a68cf90f6c4e..59d9459acfaf 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -333,12 +333,10 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, txdesc->aifs = entry->queue->aifs; /* - * Header and alignment information. + * Header and frame information. */ + txdesc->length = entry->skb->len; txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); - if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags) && - (entry->skb->len > txdesc->header_length)) - txdesc->l2pad = L2PAD_SIZE(txdesc->header_length); /* * Check whether this frame is to be acked. diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index f519aba4ff0f..94a48c174d67 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -285,8 +285,8 @@ enum txentry_desc_flags { * * @flags: Descriptor flags (See &enum queue_entry_flags). * @queue: Queue identification (See &enum data_queue_qid). + * @length: Length of the entire frame. * @header_length: Length of 802.11 header. - * @l2pad: Amount of padding to align 802.11 payload to 4-byte boundrary. * @length_high: PLCP length high word. * @length_low: PLCP length low word. * @signal: PLCP signal. @@ -311,8 +311,8 @@ struct txentry_desc { enum data_queue_qid queue; + u16 length; u16 header_length; - u16 l2pad; u16 length_high; u16 length_low; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index ac69dbe5719b..8099ecaf8694 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1808,7 +1808,8 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, if (skbdesc->desc_len > TXINFO_SIZE) { rt2x00_desc_read(txd, 11, &word); - rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skb->len); + rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, + txdesc->length); rt2x00_desc_write(txd, 11, word); } @@ -1831,7 +1832,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_KEY_TABLE, test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length); rt2x00_set_field32(&word, TXD_W0_BURST, test_bit(ENTRY_TXD_BURST, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 7ebe14b64fe8..1399c18bc667 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1494,7 +1494,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_KEY_TABLE, test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length); rt2x00_set_field32(&word, TXD_W0_BURST2, test_bit(ENTRY_TXD_BURST, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); -- cgit v1.2.3 From c693bf90cf968204f46edb820269ed380d9b7bba Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 4 May 2010 15:46:15 -0400 Subject: rtl8180: use SET_IEEE80211_PERM_ADDR Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8180_dev.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 4907fef011ad..093b93d62cc2 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -827,6 +827,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, const char *chip_name, *rf_name = NULL; u32 reg; u16 eeprom_val; + u8 mac_addr[ETH_ALEN]; err = pci_enable_device(pdev); if (err) { @@ -987,12 +988,13 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, eeprom_93cx6_read(&eeprom, 0x19, &priv->rfparam); } - eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)dev->wiphy->perm_addr, 3); - if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { + eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)mac_addr, 3); + if (!is_valid_ether_addr(mac_addr)) { printk(KERN_WARNING "%s (rtl8180): Invalid hwaddr! Using" " randomly generated MAC addr\n", pci_name(pdev)); - random_ether_addr(dev->wiphy->perm_addr); + random_ether_addr(mac_addr); } + SET_IEEE80211_PERM_ADDR(dev, mac_addr); /* CCK TX power */ for (i = 0; i < 14; i += 2) { @@ -1024,7 +1026,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, } printk(KERN_INFO "%s: hwaddr %pM, %s + %s\n", - wiphy_name(dev->wiphy), dev->wiphy->perm_addr, + wiphy_name(dev->wiphy), mac_addr, chip_name, priv->rf->name); return 0; -- cgit v1.2.3 From f2c98382fee41848265c9bee1754b483045a740e Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 4 May 2010 15:48:48 -0400 Subject: rtl8187: use SET_IEEE80211_PERM_ADDR Signed-off-by: John W. Linville Acked-by: Hin-Tak Leung --- drivers/net/wireless/rtl818x/rtl8187_dev.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 0fb850e0c656..ef66a5e60802 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -1332,6 +1332,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, u16 txpwr, reg; u16 product_id = le16_to_cpu(udev->descriptor.idProduct); int err, i; + u8 mac_addr[ETH_ALEN]; dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops); if (!dev) { @@ -1389,12 +1390,13 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, udelay(10); eeprom_93cx6_multiread(&eeprom, RTL8187_EEPROM_MAC_ADDR, - (__le16 __force *)dev->wiphy->perm_addr, 3); - if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { + (__le16 __force *)mac_addr, 3); + if (!is_valid_ether_addr(mac_addr)) { printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly " "generated MAC address\n"); - random_ether_addr(dev->wiphy->perm_addr); + random_ether_addr(mac_addr); } + SET_IEEE80211_PERM_ADDR(dev, mac_addr); channel = priv->channels; for (i = 0; i < 3; i++) { @@ -1525,7 +1527,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, skb_queue_head_init(&priv->b_tx_status.queue); printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s, rfkill mask %d\n", - wiphy_name(dev->wiphy), dev->wiphy->perm_addr, + wiphy_name(dev->wiphy), mac_addr, chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask); #ifdef CONFIG_RTL8187_LEDS -- cgit v1.2.3 From f3926b49b7122f66f8f2a1da4ae3275b112ab3e7 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 1 May 2010 18:18:18 +0200 Subject: ar9170usb: remove deprecated aggregation code This patch removes the incomplete AMPDU implementation in ar9170usb. The code in question is: * too big and complex (more than 550 SLOC.) This is enough to qualify for a new separate code file! * unbalanced quantity & quality over-engineered areas like: * xmit scheduling and queuing frames for multiple HT peers * redundant frame sorting are confronted by gaping holes: * accurate transmission feedback * firmware error-handling and device reset * HT rate control algorithm * error-prone Since its inclusion, hardly anything was done to fix any of the outlined flaws from the initial commit message. => This also indicates poor maintainability. * relies heavily on several spinlocks. As a result of this shortcomings, the code is slow and does not even support the most basic 11n requirement: HT station mode. Therefore, I request to purge my heap of **** from the kernel: "ar9170: implement transmit aggregation". The next item on the agenda is: (re-)start from scratch with an adequate design to accommodate the special requirements and features of the available frameworks and tools. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/ar9170.h | 52 +-- drivers/net/wireless/ath/ar9170/main.c | 558 +------------------------------ 2 files changed, 12 insertions(+), 598 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index dc662b76a1c8..4f845f80c098 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -109,41 +109,6 @@ struct ar9170_rxstream_mpdu_merge { bool has_plcp; }; -#define AR9170_NUM_TID 16 -#define WME_BA_BMP_SIZE 64 -#define AR9170_NUM_MAX_AGG_LEN (2 * WME_BA_BMP_SIZE) - -#define WME_AC_BE 2 -#define WME_AC_BK 3 -#define WME_AC_VI 1 -#define WME_AC_VO 0 - -#define TID_TO_WME_AC(_tid) \ - ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ - (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \ - (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ - WME_AC_VO) - -#define BAW_WITHIN(_start, _bawsz, _seqno) \ - ((((_seqno) - (_start)) & 0xfff) < (_bawsz)) - -enum ar9170_tid_state { - AR9170_TID_STATE_INVALID, - AR9170_TID_STATE_SHUTDOWN, - AR9170_TID_STATE_PROGRESS, - AR9170_TID_STATE_COMPLETE, -}; - -struct ar9170_sta_tid { - struct list_head list; - struct sk_buff_head queue; - u8 addr[ETH_ALEN]; - u16 ssn; - u16 tid; - enum ar9170_tid_state state; - bool active; -}; - struct ar9170_tx_queue_stats { unsigned int len; unsigned int limit; @@ -152,14 +117,11 @@ struct ar9170_tx_queue_stats { #define AR9170_QUEUE_TIMEOUT 64 #define AR9170_TX_TIMEOUT 8 -#define AR9170_BA_TIMEOUT 4 #define AR9170_JANITOR_DELAY 128 #define AR9170_TX_INVALID_RATE 0xffffffff -#define AR9170_NUM_TX_STATUS 128 -#define AR9170_NUM_TX_AGG_MAX 30 -#define AR9170_NUM_TX_LIMIT_HARD AR9170_TXQ_DEPTH -#define AR9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH - 10) +#define AR9170_NUM_TX_LIMIT_HARD AR9170_TXQ_DEPTH +#define AR9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH - 10) struct ar9170 { struct ieee80211_hw *hw; @@ -234,11 +196,6 @@ struct ar9170 { struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; struct delayed_work tx_janitor; - /* tx ampdu */ - struct sk_buff_head tx_status_ampdu; - spinlock_t tx_ampdu_list_lock; - struct list_head tx_ampdu_list; - atomic_t tx_ampdu_pending; /* rxstream mpdu merge */ struct ar9170_rxstream_mpdu_merge rx_mpdu; @@ -250,11 +207,6 @@ struct ar9170 { u8 global_ampdu_factor; }; -struct ar9170_sta_info { - struct ar9170_sta_tid agg[AR9170_NUM_TID]; - unsigned int ampdu_max_len; -}; - struct ar9170_tx_info { unsigned long timeout; }; diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index dfcc055a827f..b0654c873300 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -49,10 +49,6 @@ static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); -static int modparam_ht; -module_param_named(ht, modparam_ht, bool, S_IRUGO); -MODULE_PARM_DESC(ht, "enable MPDU aggregation."); - #define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ .bitrate = (_bitrate), \ .flags = (_flags), \ @@ -181,7 +177,6 @@ static struct ieee80211_supported_band ar9170_band_5GHz = { }; static void ar9170_tx(struct ar9170 *ar); -static bool ar9170_tx_ampdu(struct ar9170 *ar); static inline u16 ar9170_get_seq_h(struct ieee80211_hdr *hdr) { @@ -194,21 +189,7 @@ static inline u16 ar9170_get_seq(struct sk_buff *skb) return ar9170_get_seq_h((void *) txc->frame_data); } -static inline u16 ar9170_get_tid_h(struct ieee80211_hdr *hdr) -{ - return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; -} - -static inline u16 ar9170_get_tid(struct sk_buff *skb) -{ - struct ar9170_tx_control *txc = (void *) skb->data; - return ar9170_get_tid_h((struct ieee80211_hdr *) txc->frame_data); -} - -#define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff) -#define GET_NEXT_SEQ_FROM_SKB(skb) (GET_NEXT_SEQ(ar9170_get_seq(skb))) - -#if (defined AR9170_QUEUE_DEBUG) || (defined AR9170_TXAGG_DEBUG) +#ifdef AR9170_QUEUE_DEBUG static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) { struct ar9170_tx_control *txc = (void *) skb->data; @@ -243,7 +224,7 @@ static void __ar9170_dump_txqueue(struct ar9170 *ar, "mismatch %d != %d\n", skb_queue_len(queue), i); printk(KERN_DEBUG "---[ end ]---\n"); } -#endif /* AR9170_QUEUE_DEBUG || AR9170_TXAGG_DEBUG */ +#endif /* AR9170_QUEUE_DEBUG */ #ifdef AR9170_QUEUE_DEBUG static void ar9170_dump_txqueue(struct ar9170 *ar, @@ -274,20 +255,6 @@ static void __ar9170_dump_txstats(struct ar9170 *ar) } #endif /* AR9170_QUEUE_STOP_DEBUG */ -#ifdef AR9170_TXAGG_DEBUG -static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar) -{ - unsigned long flags; - - spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags); - printk(KERN_DEBUG "%s: A-MPDU tx_status queue =>\n", - wiphy_name(ar->hw->wiphy)); - __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu); - spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags); -} - -#endif /* AR9170_TXAGG_DEBUG */ - /* caller must guarantee exclusive access for _bin_ queue. */ static void ar9170_recycle_expired(struct ar9170 *ar, struct sk_buff_head *queue, @@ -359,70 +326,6 @@ static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, ieee80211_tx_status_irqsafe(ar->hw, skb); } -static void ar9170_tx_fake_ampdu_status(struct ar9170 *ar) -{ - struct sk_buff_head success; - struct sk_buff *skb; - unsigned int i; - unsigned long queue_bitmap = 0; - - skb_queue_head_init(&success); - - while (skb_queue_len(&ar->tx_status_ampdu) > AR9170_NUM_TX_STATUS) - __skb_queue_tail(&success, skb_dequeue(&ar->tx_status_ampdu)); - - ar9170_recycle_expired(ar, &ar->tx_status_ampdu, &success); - -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: collected %d A-MPDU frames.\n", - wiphy_name(ar->hw->wiphy), skb_queue_len(&success)); - __ar9170_dump_txqueue(ar, &success); -#endif /* AR9170_TXAGG_DEBUG */ - - while ((skb = __skb_dequeue(&success))) { - struct ieee80211_tx_info *txinfo; - - queue_bitmap |= BIT(skb_get_queue_mapping(skb)); - - txinfo = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(txinfo); - - txinfo->flags |= IEEE80211_TX_STAT_ACK; - txinfo->status.rates[0].count = 1; - - skb_pull(skb, sizeof(struct ar9170_tx_control)); - ieee80211_tx_status_irqsafe(ar->hw, skb); - } - - for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) { -#ifdef AR9170_QUEUE_STOP_DEBUG - printk(KERN_DEBUG "%s: wake queue %d\n", - wiphy_name(ar->hw->wiphy), i); - __ar9170_dump_txstats(ar); -#endif /* AR9170_QUEUE_STOP_DEBUG */ - ieee80211_wake_queue(ar->hw, i); - } - - if (queue_bitmap) - ar9170_tx(ar); -} - -static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); - struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; - - arinfo->timeout = jiffies + - msecs_to_jiffies(AR9170_BA_TIMEOUT); - - skb_queue_tail(&ar->tx_status_ampdu, skb); - ar9170_tx_fake_ampdu_status(ar); - - if (atomic_dec_and_test(&ar->tx_ampdu_pending) && - !list_empty(&ar->tx_ampdu_list)) - ar9170_tx_ampdu(ar); -} - void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -446,14 +349,10 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) if (info->flags & IEEE80211_TX_CTL_NO_ACK) { ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); } else { - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - ar9170_tx_ampdu_callback(ar, skb); - } else { - arinfo->timeout = jiffies + - msecs_to_jiffies(AR9170_TX_TIMEOUT); + arinfo->timeout = jiffies + + msecs_to_jiffies(AR9170_TX_TIMEOUT); - skb_queue_tail(&ar->tx_status[queue], skb); - } + skb_queue_tail(&ar->tx_status[queue], skb); } if (!ar->tx_stats[queue].len && @@ -523,38 +422,6 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, return NULL; } -static void ar9170_handle_block_ack(struct ar9170 *ar, u16 count, u16 r) -{ - struct sk_buff *skb; - struct ieee80211_tx_info *txinfo; - - while (count) { - skb = ar9170_get_queued_skb(ar, NULL, &ar->tx_status_ampdu, r); - if (!skb) - break; - - txinfo = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(txinfo); - - /* FIXME: maybe more ? */ - txinfo->status.rates[0].count = 1; - - skb_pull(skb, sizeof(struct ar9170_tx_control)); - ieee80211_tx_status_irqsafe(ar->hw, skb); - count--; - } - -#ifdef AR9170_TXAGG_DEBUG - if (count) { - printk(KERN_DEBUG "%s: got %d more failed mpdus, but no more " - "suitable frames left in tx_status queue.\n", - wiphy_name(ar->hw->wiphy), count); - - ar9170_dump_tx_status_ampdu(ar); - } -#endif /* AR9170_TXAGG_DEBUG */ -} - /* * This worker tries to keeps an maintain tx_status queues. * So we can guarantee that incoming tx_status reports are @@ -591,8 +458,6 @@ static void ar9170_tx_janitor(struct work_struct *work) resched = true; } - ar9170_tx_fake_ampdu_status(ar); - if (!resched) return; @@ -672,10 +537,6 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) case 0xc5: /* BlockACK events */ - ar9170_handle_block_ack(ar, - le16_to_cpu(cmd->ba_fail_cnt.failed), - le16_to_cpu(cmd->ba_fail_cnt.rate)); - ar9170_tx_fake_ampdu_status(ar); break; case 0xc6: @@ -1246,7 +1107,6 @@ static int ar9170_op_start(struct ieee80211_hw *hw) ar->global_ampdu_density = 6; ar->global_ampdu_factor = 3; - atomic_set(&ar->tx_ampdu_pending, 0); ar->bad_hw_nagger = jiffies; err = ar->open(ar); @@ -1309,40 +1169,10 @@ static void ar9170_op_stop(struct ieee80211_hw *hw) skb_queue_purge(&ar->tx_pending[i]); skb_queue_purge(&ar->tx_status[i]); } - skb_queue_purge(&ar->tx_status_ampdu); mutex_unlock(&ar->mutex); } -static void ar9170_tx_indicate_immba(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ar9170_tx_control *txc = (void *) skb->data; - - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_IMM_AMPDU); -} - -static void ar9170_tx_copy_phy(struct ar9170 *ar, struct sk_buff *dst, - struct sk_buff *src) -{ - struct ar9170_tx_control *dst_txc, *src_txc; - struct ieee80211_tx_info *dst_info, *src_info; - struct ar9170_tx_info *dst_arinfo, *src_arinfo; - - src_txc = (void *) src->data; - src_info = IEEE80211_SKB_CB(src); - src_arinfo = (void *) src_info->rate_driver_data; - - dst_txc = (void *) dst->data; - dst_info = IEEE80211_SKB_CB(dst); - dst_arinfo = (void *) dst_info->rate_driver_data; - - dst_txc->phy_control = src_txc->phy_control; - - /* same MCS for the whole aggregate */ - memcpy(dst_info->driver_rates, src_info->driver_rates, - sizeof(dst_info->driver_rates)); -} - static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) { struct ieee80211_hdr *hdr; @@ -1419,14 +1249,7 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) txc->phy_control |= cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - if (unlikely(!info->control.sta)) - goto err_out; - - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); - } else { - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); - } + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); } return 0; @@ -1536,158 +1359,6 @@ static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb) txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); } -static bool ar9170_tx_ampdu(struct ar9170 *ar) -{ - struct sk_buff_head agg; - struct ar9170_sta_tid *tid_info = NULL, *tmp; - struct sk_buff *skb, *first = NULL; - unsigned long flags, f2; - unsigned int i = 0; - u16 seq, queue, tmpssn; - bool run = false; - - skb_queue_head_init(&agg); - - spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); - if (list_empty(&ar->tx_ampdu_list)) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: aggregation list is empty.\n", - wiphy_name(ar->hw->wiphy)); -#endif /* AR9170_TXAGG_DEBUG */ - goto out_unlock; - } - - list_for_each_entry_safe(tid_info, tmp, &ar->tx_ampdu_list, list) { - if (tid_info->state != AR9170_TID_STATE_COMPLETE) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: dangling aggregation entry!\n", - wiphy_name(ar->hw->wiphy)); -#endif /* AR9170_TXAGG_DEBUG */ - continue; - } - - if (++i > 64) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: enough frames aggregated.\n", - wiphy_name(ar->hw->wiphy)); -#endif /* AR9170_TXAGG_DEBUG */ - break; - } - - queue = TID_TO_WME_AC(tid_info->tid); - - if (skb_queue_len(&ar->tx_pending[queue]) >= - AR9170_NUM_TX_AGG_MAX) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: queue %d full.\n", - wiphy_name(ar->hw->wiphy), queue); -#endif /* AR9170_TXAGG_DEBUG */ - continue; - } - - list_del_init(&tid_info->list); - - spin_lock_irqsave(&tid_info->queue.lock, f2); - tmpssn = seq = tid_info->ssn; - first = skb_peek(&tid_info->queue); - - if (likely(first)) - tmpssn = ar9170_get_seq(first); - - if (unlikely(tmpssn != seq)) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: ssn mismatch [%d != %d]\n.", - wiphy_name(ar->hw->wiphy), seq, tmpssn); -#endif /* AR9170_TXAGG_DEBUG */ - tid_info->ssn = tmpssn; - } - -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: generate A-MPDU for tid:%d ssn:%d with " - "%d queued frames.\n", wiphy_name(ar->hw->wiphy), - tid_info->tid, tid_info->ssn, - skb_queue_len(&tid_info->queue)); - __ar9170_dump_txqueue(ar, &tid_info->queue); -#endif /* AR9170_TXAGG_DEBUG */ - - while ((skb = skb_peek(&tid_info->queue))) { - if (unlikely(ar9170_get_seq(skb) != seq)) - break; - - __skb_unlink(skb, &tid_info->queue); - tid_info->ssn = seq = GET_NEXT_SEQ(seq); - - if (unlikely(skb_get_queue_mapping(skb) != queue)) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: tid:%d(q:%d) queue:%d " - "!match.\n", wiphy_name(ar->hw->wiphy), - tid_info->tid, - TID_TO_WME_AC(tid_info->tid), - skb_get_queue_mapping(skb)); -#endif /* AR9170_TXAGG_DEBUG */ - dev_kfree_skb_any(skb); - continue; - } - - if (unlikely(first == skb)) { - ar9170_tx_prepare_phy(ar, skb); - __skb_queue_tail(&agg, skb); - first = skb; - } else { - ar9170_tx_copy_phy(ar, skb, first); - __skb_queue_tail(&agg, skb); - } - - if (unlikely(skb_queue_len(&agg) == - AR9170_NUM_TX_AGG_MAX)) - break; - } - - if (skb_queue_empty(&tid_info->queue)) - tid_info->active = false; - else - list_add_tail(&tid_info->list, - &ar->tx_ampdu_list); - - spin_unlock_irqrestore(&tid_info->queue.lock, f2); - - if (unlikely(skb_queue_empty(&agg))) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: queued empty list!\n", - wiphy_name(ar->hw->wiphy)); -#endif /* AR9170_TXAGG_DEBUG */ - continue; - } - - /* - * tell the FW/HW that this is the last frame, - * that way it will wait for the immediate block ack. - */ - ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); - -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n", - wiphy_name(ar->hw->wiphy)); - __ar9170_dump_txqueue(ar, &agg); -#endif /* AR9170_TXAGG_DEBUG */ - - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); - - spin_lock_irqsave(&ar->tx_pending[queue].lock, flags); - skb_queue_splice_tail_init(&agg, &ar->tx_pending[queue]); - spin_unlock_irqrestore(&ar->tx_pending[queue].lock, flags); - run = true; - - spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); - } - -out_unlock: - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); - __skb_queue_purge(&agg); - - return run; -} - static void ar9170_tx(struct ar9170 *ar) { struct sk_buff *skb; @@ -1762,9 +1433,6 @@ static void ar9170_tx(struct ar9170 *ar) arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_TX_TIMEOUT); - if (info->flags & IEEE80211_TX_CTL_AMPDU) - atomic_inc(&ar->tx_ampdu_pending); - #ifdef AR9170_QUEUE_DEBUG printk(KERN_DEBUG "%s: send frame q:%d =>\n", wiphy_name(ar->hw->wiphy), i); @@ -1773,9 +1441,6 @@ static void ar9170_tx(struct ar9170 *ar) err = ar->tx(ar, skb); if (unlikely(err)) { - if (info->flags & IEEE80211_TX_CTL_AMPDU) - atomic_dec(&ar->tx_ampdu_pending); - frames_failed++; dev_kfree_skb_any(skb); } else { @@ -1822,94 +1487,11 @@ static void ar9170_tx(struct ar9170 *ar) msecs_to_jiffies(AR9170_JANITOR_DELAY)); } -static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ieee80211_tx_info *txinfo; - struct ar9170_sta_info *sta_info; - struct ar9170_sta_tid *agg; - struct sk_buff *iter; - unsigned long flags, f2; - unsigned int max; - u16 tid, seq, qseq; - bool run = false, queue = false; - - tid = ar9170_get_tid(skb); - seq = ar9170_get_seq(skb); - txinfo = IEEE80211_SKB_CB(skb); - sta_info = (void *) txinfo->control.sta->drv_priv; - agg = &sta_info->agg[tid]; - max = sta_info->ampdu_max_len; - - spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); - - if (unlikely(agg->state != AR9170_TID_STATE_COMPLETE)) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: BlockACK session not fully initialized " - "for ESS:%pM tid:%d state:%d.\n", - wiphy_name(ar->hw->wiphy), agg->addr, agg->tid, - agg->state); -#endif /* AR9170_TXAGG_DEBUG */ - goto err_unlock; - } - - if (!agg->active) { - agg->active = true; - agg->ssn = seq; - queue = true; - } - - /* check if seq is within the BA window */ - if (unlikely(!BAW_WITHIN(agg->ssn, max, seq))) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: frame with tid:%d seq:%d does not " - "fit into BA window (%d - %d)\n", - wiphy_name(ar->hw->wiphy), tid, seq, agg->ssn, - (agg->ssn + max) & 0xfff); -#endif /* AR9170_TXAGG_DEBUG */ - goto err_unlock; - } - - spin_lock_irqsave(&agg->queue.lock, f2); - - skb_queue_reverse_walk(&agg->queue, iter) { - qseq = ar9170_get_seq(iter); - - if (GET_NEXT_SEQ(qseq) == seq) { - __skb_queue_after(&agg->queue, iter, skb); - goto queued; - } - } - - __skb_queue_head(&agg->queue, skb); - -queued: - spin_unlock_irqrestore(&agg->queue.lock, f2); - -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: new aggregate %p queued.\n", - wiphy_name(ar->hw->wiphy), skb); - __ar9170_dump_txqueue(ar, &agg->queue); -#endif /* AR9170_TXAGG_DEBUG */ - - if (skb_queue_len(&agg->queue) >= AR9170_NUM_TX_AGG_MAX) - run = true; - - if (queue) - list_add_tail(&agg->list, &ar->tx_ampdu_list); - - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); - return run; - -err_unlock: - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); - dev_kfree_skb_irq(skb); - return false; -} - int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct ar9170 *ar = hw->priv; struct ieee80211_tx_info *info; + unsigned int queue; if (unlikely(!IS_STARTED(ar))) goto err_free; @@ -1917,18 +1499,10 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (unlikely(ar9170_tx_prepare(ar, skb))) goto err_free; + queue = skb_get_queue_mapping(skb); info = IEEE80211_SKB_CB(skb); - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - bool run = ar9170_tx_ampdu_queue(ar, skb); - - if (run || !atomic_read(&ar->tx_ampdu_pending)) - ar9170_tx_ampdu(ar); - } else { - unsigned int queue = skb_get_queue_mapping(skb); - - ar9170_tx_prepare_phy(ar, skb); - skb_queue_tail(&ar->tx_pending[queue], skb); - } + ar9170_tx_prepare_phy(ar, skb); + skb_queue_tail(&ar->tx_pending[queue], skb); ar9170_tx(ar); return NETDEV_TX_OK; @@ -2329,57 +1903,6 @@ out: return err; } -static int ar9170_sta_add(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct ar9170 *ar = hw->priv; - struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; - unsigned int i; - - memset(sta_info, 0, sizeof(*sta_info)); - - if (!sta->ht_cap.ht_supported) - return 0; - - if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) - ar->global_ampdu_density = sta->ht_cap.ampdu_density; - - if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) - ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; - - for (i = 0; i < AR9170_NUM_TID; i++) { - sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; - sta_info->agg[i].active = false; - sta_info->agg[i].ssn = 0; - sta_info->agg[i].tid = i; - INIT_LIST_HEAD(&sta_info->agg[i].list); - skb_queue_head_init(&sta_info->agg[i].queue); - } - - sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); - - return 0; -} - -static int ar9170_sta_remove(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; - unsigned int i; - - if (!sta->ht_cap.ht_supported) - return 0; - - for (i = 0; i < AR9170_NUM_TID; i++) { - sta_info->agg[i].state = AR9170_TID_STATE_INVALID; - skb_queue_purge(&sta_info->agg[i].queue); - } - - return 0; -} - static int ar9170_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { @@ -2422,55 +1945,7 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn) { - struct ar9170 *ar = hw->priv; - struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; - struct ar9170_sta_tid *tid_info = &sta_info->agg[tid]; - unsigned long flags; - - if (!modparam_ht) - return -EOPNOTSUPP; - switch (action) { - case IEEE80211_AMPDU_TX_START: - spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); - if (tid_info->state != AR9170_TID_STATE_SHUTDOWN || - !list_empty(&tid_info->list)) { - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_INFO "%s: A-MPDU [ESS:[%pM] tid:[%d]] " - "is in a very bad state!\n", - wiphy_name(hw->wiphy), sta->addr, tid); -#endif /* AR9170_TXAGG_DEBUG */ - return -EBUSY; - } - - *ssn = tid_info->ssn; - tid_info->state = AR9170_TID_STATE_PROGRESS; - tid_info->active = false; - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); - ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); - break; - - case IEEE80211_AMPDU_TX_STOP: - spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); - tid_info->state = AR9170_TID_STATE_SHUTDOWN; - list_del_init(&tid_info->list); - tid_info->active = false; - skb_queue_purge(&tid_info->queue); - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); - ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); - break; - - case IEEE80211_AMPDU_TX_OPERATIONAL: -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_INFO "%s: A-MPDU for %pM [tid:%d] Operational.\n", - wiphy_name(hw->wiphy), sta->addr, tid); -#endif /* AR9170_TXAGG_DEBUG */ - spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); - sta_info->agg[tid].state = AR9170_TID_STATE_COMPLETE; - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); - break; - case IEEE80211_AMPDU_RX_START: case IEEE80211_AMPDU_RX_STOP: /* Handled by firmware */ @@ -2496,8 +1971,6 @@ static const struct ieee80211_ops ar9170_ops = { .bss_info_changed = ar9170_op_bss_info_changed, .get_tsf = ar9170_op_get_tsf, .set_key = ar9170_set_key, - .sta_add = ar9170_sta_add, - .sta_remove = ar9170_sta_remove, .get_stats = ar9170_get_stats, .ampdu_action = ar9170_ampdu_action, }; @@ -2530,8 +2003,6 @@ void *ar9170_alloc(size_t priv_size) mutex_init(&ar->mutex); spin_lock_init(&ar->cmdlock); spin_lock_init(&ar->tx_stats_lock); - spin_lock_init(&ar->tx_ampdu_list_lock); - skb_queue_head_init(&ar->tx_status_ampdu); for (i = 0; i < __AR9170_NUM_TXQ; i++) { skb_queue_head_init(&ar->tx_status[i]); skb_queue_head_init(&ar->tx_pending[i]); @@ -2539,7 +2010,6 @@ void *ar9170_alloc(size_t priv_size) ar9170_rx_reset_rx_mpdu(ar); INIT_WORK(&ar->beacon_work, ar9170_new_beacon); INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); - INIT_LIST_HEAD(&ar->tx_ampdu_list); /* all hw supports 2.4 GHz, so set channel to 1 by default */ ar->channel = &ar9170_2ghz_chantable[0]; @@ -2552,16 +2022,8 @@ void *ar9170_alloc(size_t priv_size) IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM; - if (modparam_ht) { - ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; - } else { - ar9170_band_2GHz.ht_cap.ht_supported = false; - ar9170_band_5GHz.ht_cap.ht_supported = false; - } - ar->hw->queues = __AR9170_NUM_TXQ; ar->hw->extra_tx_headroom = 8; - ar->hw->sta_data_size = sizeof(struct ar9170_sta_info); ar->hw->max_rates = 1; ar->hw->max_rate_tries = 3; -- cgit v1.2.3 From 3ef83d745bf5220bef3a0fd11b96eb9ac64c8e8e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 4 May 2010 09:58:57 +0200 Subject: ath9k: fix another source of corrupt frames Atheros hardware supports receiving frames that span multiple descriptors and buffers. In this case, the rx status of every descriptor except for the last one is invalid and may contain random data. Because the driver does not support this, it needs to drop such frames. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/common.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index b4424a623cf5..579e15fb4143 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -57,13 +57,19 @@ static bool ath9k_rx_accept(struct ath_common *common, * rs_more indicates chained descriptors which can be used * to link buffers together for a sort of scatter-gather * operation. - * + * reject the frame, we don't support scatter-gather yet and + * the frame is probably corrupt anyway + */ + if (rx_stats->rs_more) + return false; + + /* * The rx_stats->rs_status will not be set until the end of the * chained descriptors so it can be ignored if rs_more is set. The * rs_more will be false at the last element of the chained * descriptors. */ - if (!rx_stats->rs_more && rx_stats->rs_status != 0) { + if (rx_stats->rs_status != 0) { if (rx_stats->rs_status & ATH9K_RXERR_CRC) rxs->flag |= RX_FLAG_FAILED_FCS_CRC; if (rx_stats->rs_status & ATH9K_RXERR_PHY) -- cgit v1.2.3 From bac6fafd4d6a0af26aeb37277a39607f7ce0be77 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Tue, 4 May 2010 22:54:41 +0100 Subject: orinoco: refactor xmit path ... so orinoco_usb can share some common functionality. Handle 802.2 encapsulation and MIC calculation in that function. The 802.3 header is prepended to the SKB. The calculated MIC is written to a specified buffer. Also modify the transmit control word that will be passed onto the hardware to specify whether the MIC is present, and the key used. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/main.c | 169 ++++++++++++++++++----------- drivers/net/wireless/orinoco/orinoco.h | 6 + drivers/net/wireless/orinoco/orinoco_usb.c | 91 ++++++++-------- 3 files changed, 155 insertions(+), 111 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 7c9faa4c079e..86f268cd89e7 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -339,18 +339,109 @@ EXPORT_SYMBOL(orinoco_change_mtu); /* Tx path */ /********************************************************************/ +/* Add encapsulation and MIC to the existing SKB. + * The main xmit routine will then send the whole lot to the card. + * Need 8 bytes headroom + * Need 8 bytes tailroom + * + * With encapsulated ethernet II frame + * -------- + * 803.3 header (14 bytes) + * dst[6] + * -------- src[6] + * 803.3 header (14 bytes) len[2] + * dst[6] 803.2 header (8 bytes) + * src[6] encaps[6] + * len[2] <- leave alone -> len[2] + * -------- -------- <-- 0 + * Payload Payload + * ... ... + * + * -------- -------- + * MIC (8 bytes) + * -------- + * + * returns 0 on success, -ENOMEM on error. + */ +int orinoco_process_xmit_skb(struct sk_buff *skb, + struct net_device *dev, + struct orinoco_private *priv, + int *tx_control, + u8 *mic_buf) +{ + struct orinoco_tkip_key *key; + struct ethhdr *eh; + int do_mic; + + key = (struct orinoco_tkip_key *) priv->keys[priv->tx_key].key; + + do_mic = ((priv->encode_alg == ORINOCO_ALG_TKIP) && + (key != NULL)); + + if (do_mic) + *tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) | + HERMES_TXCTRL_MIC; + + eh = (struct ethhdr *)skb->data; + + /* Encapsulate Ethernet-II frames */ + if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ + struct header_struct { + struct ethhdr eth; /* 802.3 header */ + u8 encap[6]; /* 802.2 header */ + } __attribute__ ((packed)) hdr; + int len = skb->len + sizeof(encaps_hdr) - (2 * ETH_ALEN); + + if (skb_headroom(skb) < ENCAPS_OVERHEAD) { + if (net_ratelimit()) + printk(KERN_ERR + "%s: Not enough headroom for 802.2 headers %d\n", + dev->name, skb_headroom(skb)); + return -ENOMEM; + } + + /* Fill in new header */ + memcpy(&hdr.eth, eh, 2 * ETH_ALEN); + hdr.eth.h_proto = htons(len); + memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr)); + + /* Make room for the new header, and copy it in */ + eh = (struct ethhdr *) skb_push(skb, ENCAPS_OVERHEAD); + memcpy(eh, &hdr, sizeof(hdr)); + } + + /* Calculate Michael MIC */ + if (do_mic) { + size_t len = skb->len - ETH_HLEN; + u8 *mic = &mic_buf[0]; + + /* Have to write to an even address, so copy the spare + * byte across */ + if (skb->len % 2) { + *mic = skb->data[skb->len - 1]; + mic++; + } + + orinoco_mic(priv->tx_tfm_mic, key->tx_mic, + eh->h_dest, eh->h_source, 0 /* priority */, + skb->data + ETH_HLEN, + len, mic); + } + + return 0; +} +EXPORT_SYMBOL(orinoco_process_xmit_skb); + static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); struct net_device_stats *stats = &priv->stats; - struct orinoco_tkip_key *key; hermes_t *hw = &priv->hw; int err = 0; u16 txfid = priv->txfid; - struct ethhdr *eh; int tx_control; unsigned long flags; - int do_mic; + u8 mic_buf[MICHAEL_MIC_LEN+1]; if (!netif_running(dev)) { printk(KERN_ERR "%s: Tx on stopped device!\n", @@ -382,16 +473,12 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) if (skb->len < ETH_HLEN) goto drop; - key = (struct orinoco_tkip_key *) priv->keys[priv->tx_key].key; - - do_mic = ((priv->encode_alg == ORINOCO_ALG_TKIP) && - (key != NULL)); - tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX; - if (do_mic) - tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) | - HERMES_TXCTRL_MIC; + err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control, + &mic_buf[0]); + if (err) + goto drop; if (priv->has_alt_txcntl) { /* WPA enabled firmwares have tx_cntl at the end of @@ -434,34 +521,6 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); } - eh = (struct ethhdr *)skb->data; - - /* Encapsulate Ethernet-II frames */ - if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ - struct header_struct { - struct ethhdr eth; /* 802.3 header */ - u8 encap[6]; /* 802.2 header */ - } __attribute__ ((packed)) hdr; - - /* Strip destination and source from the data */ - skb_pull(skb, 2 * ETH_ALEN); - - /* And move them to a separate header */ - memcpy(&hdr.eth, eh, 2 * ETH_ALEN); - hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len); - memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr)); - - /* Insert the SNAP header */ - if (skb_headroom(skb) < sizeof(hdr)) { - printk(KERN_ERR - "%s: Not enough headroom for 802.2 headers %d\n", - dev->name, skb_headroom(skb)); - goto drop; - } - eh = (struct ethhdr *) skb_push(skb, sizeof(hdr)); - memcpy(eh, &hdr, sizeof(hdr)); - } - err = hw->ops->bap_pwrite(hw, USER_BAP, skb->data, skb->len, txfid, HERMES_802_3_OFFSET); if (err) { @@ -470,32 +529,16 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) goto busy; } - /* Calculate Michael MIC */ - if (do_mic) { - u8 mic_buf[MICHAEL_MIC_LEN + 1]; - u8 *mic; - size_t offset; - size_t len; + if (tx_control & HERMES_TXCTRL_MIC) { + size_t offset = HERMES_802_3_OFFSET + skb->len; + size_t len = MICHAEL_MIC_LEN; - if (skb->len % 2) { - /* MIC start is on an odd boundary */ - mic_buf[0] = skb->data[skb->len - 1]; - mic = &mic_buf[1]; - offset = skb->len - 1; - len = MICHAEL_MIC_LEN + 1; - } else { - mic = &mic_buf[0]; - offset = skb->len; - len = MICHAEL_MIC_LEN; + if (offset % 2) { + offset--; + len++; } - - orinoco_mic(priv->tx_tfm_mic, key->tx_mic, - eh->h_dest, eh->h_source, 0 /* priority */, - skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic); - - /* Write the MIC */ err = hw->ops->bap_pwrite(hw, USER_BAP, &mic_buf[0], len, - txfid, HERMES_802_3_OFFSET + offset); + txfid, offset); if (err) { printk(KERN_ERR "%s: Error %d writing MIC to BAP\n", dev->name, err); @@ -2234,7 +2277,7 @@ int orinoco_if_add(struct orinoco_private *priv, /* we use the default eth_mac_addr for setting the MAC addr */ /* Reserve space in skb for the SNAP header */ - dev->hard_header_len += ENCAPS_OVERHEAD; + dev->needed_headroom = ENCAPS_OVERHEAD; netif_carrier_off(dev); diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index e9f415a56d4d..a6da86e0a70f 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h @@ -200,6 +200,12 @@ extern irqreturn_t orinoco_interrupt(int irq, void *dev_id); extern void __orinoco_ev_info(struct net_device *dev, hermes_t *hw); extern void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw); +int orinoco_process_xmit_skb(struct sk_buff *skb, + struct net_device *dev, + struct orinoco_private *priv, + int *tx_control, + u8 *mic); + /* Common ndo functions exported for reuse by orinoco_usb */ int orinoco_open(struct net_device *dev); int orinoco_stop(struct net_device *dev); diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index e22093359f3e..78f089baa8c9 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c @@ -67,6 +67,7 @@ #include #include +#include "mic.h" #include "orinoco.h" #ifndef URB_ASYNC_UNLINK @@ -1198,11 +1199,9 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) struct orinoco_private *priv = ndev_priv(dev); struct net_device_stats *stats = &priv->stats; struct ezusb_priv *upriv = priv->card; + u8 mic[MICHAEL_MIC_LEN+1]; int err = 0; - char *p; - struct ethhdr *eh; - int len, data_len, data_off; - __le16 tx_control; + int tx_control; unsigned long flags; struct request_context *ctx; u8 *buf; @@ -1222,7 +1221,7 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) if (orinoco_lock(priv, &flags) != 0) { printk(KERN_ERR - "%s: orinoco_xmit() called while hw_unavailable\n", + "%s: ezusb_xmit() called while hw_unavailable\n", dev->name); return NETDEV_TX_BUSY; } @@ -1232,53 +1231,46 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) /* Oops, the firmware hasn't established a connection, silently drop the packet (this seems to be the safest approach). */ - stats->tx_errors++; - orinoco_unlock(priv, &flags); - dev_kfree_skb(skb); - return NETDEV_TX_OK; + goto drop; } + /* Check packet length */ + if (skb->len < ETH_HLEN) + goto drop; + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0); if (!ctx) - goto fail; + goto busy; memset(ctx->buf, 0, BULK_BUF_SIZE); buf = ctx->buf->data; - /* Length of the packet body */ - /* FIXME: what if the skb is smaller than this? */ - len = max_t(int, skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN); - - eh = (struct ethhdr *) skb->data; - - tx_control = cpu_to_le16(0); - memcpy(buf, &tx_control, sizeof(tx_control)); - buf += sizeof(tx_control); - /* Encapsulate Ethernet-II frames */ - if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ - struct header_struct *hdr = (void *) buf; - buf += sizeof(*hdr); - data_len = len; - data_off = sizeof(tx_control) + sizeof(*hdr); - p = skb->data + ETH_HLEN; - - /* 802.3 header */ - memcpy(hdr->dest, eh->h_dest, ETH_ALEN); - memcpy(hdr->src, eh->h_source, ETH_ALEN); - hdr->len = htons(data_len + ENCAPS_OVERHEAD); - - /* 802.2 header */ - memcpy(&hdr->dsap, &encaps_hdr, sizeof(encaps_hdr)); - - hdr->ethertype = eh->h_proto; - } else { /* IEEE 802.3 frame */ - data_len = len + ETH_HLEN; - data_off = sizeof(tx_control); - p = skb->data; + tx_control = 0; + + err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control, + &mic[0]); + if (err) + goto drop; + + { + __le16 *tx_cntl = (__le16 *)buf; + *tx_cntl = cpu_to_le16(tx_control); + buf += sizeof(*tx_cntl); } - memcpy(buf, p, data_len); - buf += data_len; + memcpy(buf, skb->data, skb->len); + buf += skb->len; + + if (tx_control & HERMES_TXCTRL_MIC) { + u8 *m = mic; + /* Mic has been offset so it can be copied to an even + * address. We're copying eveything anyway, so we + * don't need to copy that first byte. */ + if (skb->len % 2) + m++; + memcpy(buf, m, MICHAEL_MIC_LEN); + buf += MICHAEL_MIC_LEN; + } /* Finally, we actually initiate the send */ netif_stop_queue(dev); @@ -1294,20 +1286,23 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) if (net_ratelimit()) printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err); - stats->tx_errors++; - goto fail; + goto busy; } dev->trans_start = jiffies; - stats->tx_bytes += data_off + data_len; + stats->tx_bytes += skb->len; + goto ok; - orinoco_unlock(priv, &flags); + drop: + stats->tx_errors++; + stats->tx_dropped++; + ok: + orinoco_unlock(priv, &flags); dev_kfree_skb(skb); - return NETDEV_TX_OK; - fail: + busy: orinoco_unlock(priv, &flags); return NETDEV_TX_BUSY; } -- cgit v1.2.3 From f444de05d20e27cdd960c13fcbcfca3099f03143 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 5 May 2010 15:25:02 +0200 Subject: cfg80211/mac80211: better channel handling Currently (all tested with hwsim) you can do stupid things like setting up an AP on a certain channel, then adding another virtual interface and making that associate on another channel -- this will make the beaconing to move channel but obviously without the necessary IEs data update. In order to improve this situation, first make the configuration APIs (cfg80211 and nl80211) aware of multi-channel operation -- we'll eventually need that in the future anyway. There's one userland API change and one API addition. The API change is that now SET_WIPHY must be called with virtual interface index rather than only wiphy index in order to take effect for that interface -- luckily all current users (hostapd) do that. For monitor interfaces, the old setting is preserved, but monitors are always slaved to other devices anyway so no guarantees. The second userland API change is the introduction of a per virtual interface SET_CHANNEL command, that hostapd should use going forward to make it easier to understand what's going on (it can automatically detect a kernel with this command). Other than mac80211, no existing cfg80211 drivers are affected by this change because they only allow a single virtual interface. mac80211, however, now needs to be aware that the channel settings are per interface now, and needs to disallow (for now) real multi-channel operation, which is another important part of this patch. One of the immediate benefits is that you can now start hostapd to operate on a hardware that already has a connection on another virtual interface, as long as you specify the same channel. Note that two things are left unhandled (this is an improvement -- not a complete fix): * different HT/no-HT modes currently you could start an HT AP and then connect to a non-HT network on the same channel which would configure the hardware for no HT; that can be fixed fairly easily * CSA An AP we're connected to on a virtual interface might indicate switching channels, and in that case we would follow it, regardless of how many other interfaces are operating; this requires more effort to fix but is pretty rare after all Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cfg.c | 1 + drivers/net/wireless/orinoco/cfg.c | 1 + drivers/net/wireless/rndis_wlan.c | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 82ebe1461a77..ea9d0b2ea0d7 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -78,6 +78,7 @@ static const u32 cipher_suites[] = { static int lbs_cfg_set_channel(struct wiphy *wiphy, + struct net_device *netdev, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) { diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c index 81d228de9e5d..8c4169c227ae 100644 --- a/drivers/net/wireless/orinoco/cfg.c +++ b/drivers/net/wireless/orinoco/cfg.c @@ -159,6 +159,7 @@ static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev, } static int orinoco_set_channel(struct wiphy *wiphy, + struct net_device *netdev, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) { diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index aceb95ef7274..99d4f0de77ca 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -534,7 +534,7 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev, static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev); -static int rndis_set_channel(struct wiphy *wiphy, +static int rndis_set_channel(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, @@ -2290,7 +2290,7 @@ static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev) return deauthenticate(usbdev); } -static int rndis_set_channel(struct wiphy *wiphy, +static int rndis_set_channel(struct wiphy *wiphy, struct net_device *netdev, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) { struct rndis_wlan_private *priv = wiphy_priv(wiphy); -- cgit v1.2.3 From 0aaffa9b9699894aab3266195a529baf9f96ac29 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 5 May 2010 15:28:27 +0200 Subject: mac80211: improve HT channel handling Currently, when one interface switches HT mode, all others will follow along. This is clearly undesirable, since the new one might switch to no-HT while another one is operating in HT. Address this issue by keeping track of the HT mode per interface, and allowing only changes that are compatible, i.e. switching into HT40+ is not possible when another interface is in HT40-, in that case the second one needs to fall back to HT20. Also, to allow drivers to know what's going on, store the per-interface HT mode (channel type) in the virtual interface's bss_conf. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 62a739f6c37b..bdce71a4ba20 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -651,17 +651,17 @@ static void mac80211_hwsim_beacon(unsigned long arg) add_timer(&data->beacon_timer); } +static const char *hwsim_chantypes[] = { + [NL80211_CHAN_NO_HT] = "noht", + [NL80211_CHAN_HT20] = "ht20", + [NL80211_CHAN_HT40MINUS] = "ht40-", + [NL80211_CHAN_HT40PLUS] = "ht40+", +}; static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) { struct mac80211_hwsim_data *data = hw->priv; struct ieee80211_conf *conf = &hw->conf; - static const char *chantypes[4] = { - [NL80211_CHAN_NO_HT] = "noht", - [NL80211_CHAN_HT20] = "ht20", - [NL80211_CHAN_HT40MINUS] = "ht40-", - [NL80211_CHAN_HT40PLUS] = "ht40+", - }; static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = { [IEEE80211_SMPS_AUTOMATIC] = "auto", [IEEE80211_SMPS_OFF] = "off", @@ -672,7 +672,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) printk(KERN_DEBUG "%s:%s (freq=%d/%s idle=%d ps=%d smps=%s)\n", wiphy_name(hw->wiphy), __func__, conf->channel->center_freq, - chantypes[conf->channel_type], + hwsim_chantypes[conf->channel_type], !!(conf->flags & IEEE80211_CONF_IDLE), !!(conf->flags & IEEE80211_CONF_PS), smps_modes[conf->smps_mode]); @@ -760,9 +760,10 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_HT) { - printk(KERN_DEBUG " %s: HT: op_mode=0x%x\n", + printk(KERN_DEBUG " %s: HT: op_mode=0x%x, chantype=%s\n", wiphy_name(hw->wiphy), - info->ht_operation_mode); + info->ht_operation_mode, + hwsim_chantypes[info->channel_type]); } if (changed & BSS_CHANGED_BASIC_RATES) { -- cgit v1.2.3 From 9c6dda4e2dfea970a7105e3805f0195bc3079f2f Mon Sep 17 00:00:00 2001 From: Sujith Date: Thu, 6 May 2010 14:45:47 +0530 Subject: ath9k_htc: Fix beaconing in IBSS mode The current way of managing beaconing in ad-hoc mode has a subtle race - the beacon obtained from mac80211 is freed in the SWBA handler rather than the TX completion routine. But transmission of beacons goes through the normal SKB queue maintained in hif_usb, leading to a situation where __skb_dequeue() in the TX completion handler goes kaput. Fix this by simply getting a beacon from mac80211 for every SWBA and free it in its completion routine. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 5 ++-- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 39 +++++++------------------ drivers/net/wireless/ath/ath9k/htc_drv_init.c | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 12 -------- 4 files changed, 13 insertions(+), 45 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 1ae18bbc4d9e..ad556aa8da39 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -356,7 +356,6 @@ struct ath9k_htc_priv { u16 seq_no; u32 bmiss_cnt; - struct sk_buff *beacon; spinlock_t beacon_lock; bool tx_queues_stop; @@ -408,13 +407,13 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif); void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); -void ath9k_htc_beacon_update(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif); void ath9k_htc_rxep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id); void ath9k_htc_txep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id, bool txok); +void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, + enum htc_endpoint_id ep_id, bool txok); void ath9k_htc_station_work(struct work_struct *work); void ath9k_htc_aggr_work(struct work_struct *work); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 7cb55f5b071c..c10c7d002eb7 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -165,22 +165,10 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); } -void ath9k_htc_beacon_update(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif) +void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, + enum htc_endpoint_id ep_id, bool txok) { - struct ath_common *common = ath9k_hw_common(priv->ah); - - spin_lock_bh(&priv->beacon_lock); - - if (priv->beacon) - dev_kfree_skb_any(priv->beacon); - - priv->beacon = ieee80211_beacon_get(priv->hw, vif); - if (!priv->beacon) - ath_print(common, ATH_DBG_BEACON, - "Unable to allocate beacon\n"); - - spin_unlock_bh(&priv->beacon_lock); + dev_kfree_skb_any(skb); } void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) @@ -189,6 +177,7 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) struct tx_beacon_header beacon_hdr; struct ath9k_htc_tx_ctl tx_ctl; struct ieee80211_tx_info *info; + struct sk_buff *beacon; u8 *tx_fhdr; memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); @@ -207,25 +196,17 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) return; } - if (unlikely(priv->beacon == NULL)) { - spin_unlock_bh(&priv->beacon_lock); - return; - } - - /* Free the old SKB first */ - dev_kfree_skb_any(priv->beacon); - /* Get a new beacon */ - priv->beacon = ieee80211_beacon_get(priv->hw, priv->vif); - if (!priv->beacon) { + beacon = ieee80211_beacon_get(priv->hw, priv->vif); + if (!beacon) { spin_unlock_bh(&priv->beacon_lock); return; } - info = IEEE80211_SKB_CB(priv->beacon); + info = IEEE80211_SKB_CB(beacon); if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *) priv->beacon->data; + (struct ieee80211_hdr *) beacon->data; priv->seq_no += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(priv->seq_no); @@ -233,10 +214,10 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) tx_ctl.type = ATH9K_HTC_NORMAL; beacon_hdr.vif_index = avp->index; - tx_fhdr = skb_push(priv->beacon, sizeof(beacon_hdr)); + tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); - htc_send(priv->htc, priv->beacon, priv->beacon_ep, &tx_ctl); + htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl); spin_unlock_bh(&priv->beacon_lock); } diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 701f2ef5a440..17111fc1d2cc 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -144,7 +144,7 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv) goto err; /* Beacon */ - ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, NULL, + ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, ath9k_htc_beaconep, &priv->beacon_ep); if (ret) goto err; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index ca7f3a78eb11..7c9e33ba95ab 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1313,15 +1313,6 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, priv->nvifs--; ath9k_htc_remove_station(priv, vif, NULL); - - if (vif->type == NL80211_IFTYPE_ADHOC) { - spin_lock_bh(&priv->beacon_lock); - if (priv->beacon) - dev_kfree_skb_any(priv->beacon); - priv->beacon = NULL; - spin_unlock_bh(&priv->beacon_lock); - } - priv->vif = NULL; mutex_unlock(&priv->mutex); @@ -1590,9 +1581,6 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, ath9k_htc_beacon_config(priv, vif); } - if (changed & BSS_CHANGED_BEACON) - ath9k_htc_beacon_update(priv, vif); - if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) { priv->op_flags &= ~OP_ENABLE_BEACON; -- cgit v1.2.3 From a21c2ab4210a89a71a0a99685acf16ae126b2eee Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Thu, 6 May 2010 12:29:04 +0200 Subject: rt2x00: rt2800: update initial SIFS values Currently the CCK and OFDM SIFS value is set to 32us. This value is neither used by the Ralink driver nor specified in 802.11. Instead of using 10us for CCK SIFS (as defined in 802.11) use 16us like in the Ralink drivers. And indeed using a SIFS value of 10us breaks connectivity with 11g + CTS protected connections. Add a comment to the code why we don't use 10us for CCK SIFS value. The OFDM SIFS value is set to 16us (as defined in 802.11 and also used by the Ralink drivers). Signed-off-by: Helmut Schaa Acked-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 6d2c66d9b290..11a0d8b6235d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1414,9 +1414,16 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca); + /* + * Usually the CCK SIFS time should be set to 10 and the OFDM SIFS + * time should be set to 16. However, the original Ralink driver uses + * 16 for both and indeed using a value of 10 for CCK SIFS results in + * connection problems with 11g + CTS protection. Hence, use the same + * defaults as the Ralink driver: 16 for both, CCK and OFDM SIFS. + */ rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); - rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, 32); - rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, 32); + rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, 16); + rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, 16); rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, 314); rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); -- cgit v1.2.3 From 809bfe81ce225d1f5a111840c3d9e30704d98478 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Thu, 6 May 2010 12:29:44 +0200 Subject: rt2x00: rt2800: don't overwrite SIFS values on erp changes The SIFS value is a constant and doesn't need to be updated on erp changes. Furthermore the code used 10us for both, the OFDM SIFS and CCK SIFS time which broke CTS protected 11g connections (see patch "rt2x00: rt2800: update initial SIFS values" for details). Signed-off-by: Helmut Schaa Acked-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 11a0d8b6235d..b110368c00e0 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -639,8 +639,6 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp) rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); - rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); - rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); -- cgit v1.2.3 From 55f9321a024a2d03f71a23b74003792692ca1a38 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Thu, 6 May 2010 14:45:46 +0200 Subject: rt2x00: Fix RF3052 channel initialization Update channel initialization for the RF3052 chipset. According to the Ralink drivers, the rt3x array must be used for this chipset, rather then the rt2x array. Furthermore RF3052 supports the 5GHz band, extend the rt3x array with the 5GHz channels, and use them for the RF3052 chip. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 67 ++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index b110368c00e0..525267d4cc3e 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2223,7 +2223,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) EXPORT_SYMBOL_GPL(rt2800_init_eeprom); /* - * RF value list for rt28x0 + * RF value list for rt28xx * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750) */ static const struct rf_channel rf_vals[] = { @@ -2298,10 +2298,10 @@ static const struct rf_channel rf_vals[] = { }; /* - * RF value list for rt3070 - * Supports: 2.4 GHz + * RF value list for rt3xxx + * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052) */ -static const struct rf_channel rf_vals_302x[] = { +static const struct rf_channel rf_vals_3x[] = { {1, 241, 2, 2 }, {2, 241, 2, 7 }, {3, 242, 2, 2 }, @@ -2316,6 +2316,51 @@ static const struct rf_channel rf_vals_302x[] = { {12, 246, 2, 7 }, {13, 247, 2, 2 }, {14, 248, 2, 4 }, + + /* 802.11 UNI / HyperLan 2 */ + {36, 0x56, 0, 4}, + {38, 0x56, 0, 6}, + {40, 0x56, 0, 8}, + {44, 0x57, 0, 0}, + {46, 0x57, 0, 2}, + {48, 0x57, 0, 4}, + {52, 0x57, 0, 8}, + {54, 0x57, 0, 10}, + {56, 0x58, 0, 0}, + {60, 0x58, 0, 4}, + {62, 0x58, 0, 6}, + {64, 0x58, 0, 8}, + + /* 802.11 HyperLan 2 */ + {100, 0x5b, 0, 8}, + {102, 0x5b, 0, 10}, + {104, 0x5c, 0, 0}, + {108, 0x5c, 0, 4}, + {110, 0x5c, 0, 6}, + {112, 0x5c, 0, 8}, + {116, 0x5d, 0, 0}, + {118, 0x5d, 0, 2}, + {120, 0x5d, 0, 4}, + {124, 0x5d, 0, 8}, + {126, 0x5d, 0, 10}, + {128, 0x5e, 0, 0}, + {132, 0x5e, 0, 4}, + {134, 0x5e, 0, 6}, + {136, 0x5e, 0, 8}, + {140, 0x5f, 0, 0}, + + /* 802.11 UNII */ + {149, 0x5f, 0, 9}, + {151, 0x5f, 0, 11}, + {153, 0x60, 0, 1}, + {157, 0x60, 0, 5}, + {159, 0x60, 0, 7}, + {161, 0x60, 0, 9}, + {165, 0x61, 0, 1}, + {167, 0x61, 0, 3}, + {169, 0x61, 0, 5}, + {171, 0x61, 0, 7}, + {173, 0x61, 0, 9}, }; int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) @@ -2356,11 +2401,11 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; if (rt2x00_rf(rt2x00dev, RF2820) || - rt2x00_rf(rt2x00dev, RF2720) || - rt2x00_rf(rt2x00dev, RF3052)) { + rt2x00_rf(rt2x00dev, RF2720)) { spec->num_channels = 14; spec->channels = rf_vals; - } else if (rt2x00_rf(rt2x00dev, RF2850) || rt2x00_rf(rt2x00dev, RF2750)) { + } else if (rt2x00_rf(rt2x00dev, RF2850) || + rt2x00_rf(rt2x00dev, RF2750)) { spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals); spec->channels = rf_vals; @@ -2368,8 +2413,12 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00_rf(rt2x00dev, RF2020) || rt2x00_rf(rt2x00dev, RF3021) || rt2x00_rf(rt2x00dev, RF3022)) { - spec->num_channels = ARRAY_SIZE(rf_vals_302x); - spec->channels = rf_vals_302x; + spec->num_channels = 14; + spec->channels = rf_vals_3x; + } else if (rt2x00_rf(rt2x00dev, RF3052)) { + spec->supported_bands |= SUPPORT_BAND_5GHZ; + spec->num_channels = ARRAY_SIZE(rf_vals_3x); + spec->channels = rf_vals_3x; } /* -- cgit v1.2.3 From 51e080deba57437459571f26a3c6f3db03324c4c Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 6 May 2010 16:26:23 -0400 Subject: rtl8180: assign sequence numbers in the driver This is a step towards support for beaconing modes of operation. Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8180.h | 3 +++ drivers/net/wireless/rtl818x/rtl8180_dev.c | 10 ++++++++++ 2 files changed, 13 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rtl818x/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180.h index de3844fe06d8..b92d678abc0c 100644 --- a/drivers/net/wireless/rtl818x/rtl8180.h +++ b/drivers/net/wireless/rtl818x/rtl8180.h @@ -78,6 +78,9 @@ struct rtl8180_priv { u32 anaparam; u16 rfparam; u8 csthreshold; + + /* sequence # */ + u16 seqno; }; void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 093b93d62cc2..3a214d7507a5 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -233,6 +233,7 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct rtl8180_priv *priv = dev->priv; struct rtl8180_tx_ring *ring; struct rtl8180_tx_desc *entry; @@ -284,6 +285,14 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) } spin_lock_irqsave(&priv->lock, flags); + + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + priv->seqno += 0x10; + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(priv->seqno); + } + idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; entry = &ring->desc[idx]; @@ -298,6 +307,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) __skb_queue_tail(&ring->queue, skb); if (ring->entries - skb_queue_len(&ring->queue) < 2) ieee80211_stop_queue(dev, prio); + spin_unlock_irqrestore(&priv->lock, flags); rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); -- cgit v1.2.3 From c809e86c11a64488acc85ddf12ece3c9b879ccb6 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 6 May 2010 16:49:40 -0400 Subject: rtl8180: add software-based support for IBSS mode Device documentation suggests that hardware support for beaconing is available. But I implemented software-based beacon generation as an experiment and it seems better to have that working now rather than waiting for something better to materialize. Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8180.h | 8 +++ drivers/net/wireless/rtl818x/rtl8180_dev.c | 82 ++++++++++++++++++++++++++---- 2 files changed, 80 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rtl818x/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180.h index b92d678abc0c..4baf0cf0826f 100644 --- a/drivers/net/wireless/rtl818x/rtl8180.h +++ b/drivers/net/wireless/rtl818x/rtl8180.h @@ -55,6 +55,14 @@ struct rtl8180_tx_ring { struct sk_buff_head queue; }; +struct rtl8180_vif { + struct ieee80211_hw *dev; + + /* beaconing */ + struct delayed_work beacon_work; + bool enable_beacon; +}; + struct rtl8180_priv { /* common between rtl818x drivers */ struct rtl818x_csr __iomem *map; diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 3a214d7507a5..cbdc5cfec90c 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -662,10 +662,59 @@ static void rtl8180_stop(struct ieee80211_hw *dev) rtl8180_free_tx_ring(dev, i); } +static u64 rtl8180_get_tsf(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + + return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | + (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; +} + +void rtl8180_beacon_work(struct work_struct *work) +{ + struct rtl8180_vif *vif_priv = + container_of(work, struct rtl8180_vif, beacon_work.work); + struct ieee80211_vif *vif = + container_of((void *)vif_priv, struct ieee80211_vif, drv_priv); + struct ieee80211_hw *dev = vif_priv->dev; + struct ieee80211_mgmt *mgmt; + struct sk_buff *skb; + int err = 0; + + /* don't overflow the tx ring */ + if (ieee80211_queue_stopped(dev, 0)) + goto resched; + + /* grab a fresh beacon */ + skb = ieee80211_beacon_get(dev, vif); + + /* + * update beacon timestamp w/ TSF value + * TODO: make hardware update beacon timestamp + */ + mgmt = (struct ieee80211_mgmt *)skb->data; + mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev)); + + /* TODO: use actual beacon queue */ + skb_set_queue_mapping(skb, 0); + + err = rtl8180_tx(dev, skb); + WARN_ON(err); + +resched: + /* + * schedule next beacon + * TODO: use hardware support for beacon timing + */ + schedule_delayed_work(&vif_priv->beacon_work, + usecs_to_jiffies(1024 * vif->bss_conf.beacon_int)); +} + static int rtl8180_add_interface(struct ieee80211_hw *dev, struct ieee80211_vif *vif) { struct rtl8180_priv *priv = dev->priv; + struct rtl8180_vif *vif_priv; /* * We only support one active interface at a time. @@ -675,6 +724,7 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev, switch (vif->type) { case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: break; default: return -EOPNOTSUPP; @@ -682,6 +732,12 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev, priv->vif = vif; + /* Initialize driver private area */ + vif_priv = (struct rtl8180_vif *)&vif->drv_priv; + vif_priv->dev = dev; + INIT_DELAYED_WORK(&vif_priv->beacon_work, rtl8180_beacon_work); + vif_priv->enable_beacon = false; + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], le32_to_cpu(*(__le32 *)vif->addr)); @@ -715,8 +771,11 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, u32 changed) { struct rtl8180_priv *priv = dev->priv; + struct rtl8180_vif *vif_priv; int i; + vif_priv = (struct rtl8180_vif *)&vif->drv_priv; + if (changed & BSS_CHANGED_BSSID) { for (i = 0; i < ETH_ALEN; i++) rtl818x_iowrite8(priv, &priv->map->BSSID[i], @@ -731,7 +790,16 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, } if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) - priv->rf->conf_erp(dev, info); + priv->rf->conf_erp(dev, info); + + if (changed & BSS_CHANGED_BEACON_ENABLED) + vif_priv->enable_beacon = info->enable_beacon; + + if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON)) { + cancel_delayed_work_sync(&vif_priv->beacon_work); + if (vif_priv->enable_beacon) + schedule_work(&vif_priv->beacon_work.work); + } } static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, int mc_count, @@ -772,14 +840,6 @@ static void rtl8180_configure_filter(struct ieee80211_hw *dev, rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); } -static u64 rtl8180_get_tsf(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - - return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | - (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; -} - static const struct ieee80211_ops rtl8180_ops = { .tx = rtl8180_tx, .start = rtl8180_start, @@ -916,7 +976,9 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_UNSPEC; - dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + dev->vif_data_size = sizeof(struct rtl8180_vif); + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); dev->queues = 1; dev->max_signal = 65; -- cgit v1.2.3 From 8e1559949928d4d8bfe044bfcf57879faff82e19 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 6 May 2010 22:41:12 -0400 Subject: ath9k_common: move the rate status setting into ath9k_process_rate() This has no real functional change, this just moves the setting the the mac80211 rate index into ath9k_process_rate(). This allows us to eventually make ath9k_process_rate() return a negative value in case we have detected a specific case rate situation which should have been ignored. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/common.c | 40 ++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 579e15fb4143..254dcbdbc061 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -108,11 +108,11 @@ static bool ath9k_rx_accept(struct ath_common *common, return true; } -static u8 ath9k_process_rate(struct ath_common *common, - struct ieee80211_hw *hw, - struct ath_rx_status *rx_stats, - struct ieee80211_rx_status *rxs, - struct sk_buff *skb) +static int ath9k_process_rate(struct ath_common *common, + struct ieee80211_hw *hw, + struct ath_rx_status *rx_stats, + struct ieee80211_rx_status *rxs, + struct sk_buff *skb) { struct ieee80211_supported_band *sband; enum ieee80211_band band; @@ -128,25 +128,33 @@ static u8 ath9k_process_rate(struct ath_common *common, rxs->flag |= RX_FLAG_40MHZ; if (rx_stats->rs_flags & ATH9K_RX_GI) rxs->flag |= RX_FLAG_SHORT_GI; - return rx_stats->rs_rate & 0x7f; + rxs->rate_idx = rx_stats->rs_rate & 0x7f; + return 0; } for (i = 0; i < sband->n_bitrates; i++) { - if (sband->bitrates[i].hw_value == rx_stats->rs_rate) - return i; + if (sband->bitrates[i].hw_value == rx_stats->rs_rate) { + rxs->rate_idx = i; + return 0; + } if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) { rxs->flag |= RX_FLAG_SHORTPRE; - return i; + rxs->rate_idx = i; + return 0; } } - /* No valid hardware bitrate found -- we should not get here */ + /* + * No valid hardware bitrate found -- we should not get here + * because hardware has already validated this frame as OK. + */ ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected " "0x%02x using 1 Mbit\n", rx_stats->rs_rate); if ((common->debug_mask & ATH_DBG_XMIT)) print_hex_dump_bytes("", DUMP_PREFIX_NONE, skb->data, skb->len); - return 0; + rxs->rate_idx = 0; + return 0; } static void ath9k_process_rssi(struct ath_common *common, @@ -208,13 +216,19 @@ int ath9k_cmn_rx_skb_preprocess(struct ath_common *common, struct ath_hw *ah = common->ah; memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); + + /* + * everything but the rate is checked here, the rate check is done + * separately to avoid doing two lookups for a rate for each frame. + */ if (!ath9k_rx_accept(common, skb, rx_status, rx_stats, decrypt_error)) return -EINVAL; ath9k_process_rssi(common, hw, skb, rx_stats); - rx_status->rate_idx = ath9k_process_rate(common, hw, - rx_stats, rx_status, skb); + if (ath9k_process_rate(common, hw, rx_stats, rx_status, skb)) + return -EINVAL; + rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp); rx_status->band = hw->conf.channel->band; rx_status->freq = hw->conf.channel->center_freq; -- cgit v1.2.3 From 6f256de70b90aecbb550a2df387684ed2136b792 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 6 May 2010 22:41:13 -0400 Subject: ath9k_common: drop incomming frames with an invalid hardware rate ath9k_common (used by ath9k and ath9k_htc) trusts the frames blessed by hardware as OK are infact correct even if the rate seen by the driver is unrecognized. ath9k_common just treats these frames in mac80211 as frames as frames under 1 mbps rate. It seems this might not be the best thing to do as other parts of the frame might not be valid so just drop these frames for now. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/common.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 254dcbdbc061..7707341cd0d3 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -153,8 +153,7 @@ static int ath9k_process_rate(struct ath_common *common, if ((common->debug_mask & ATH_DBG_XMIT)) print_hex_dump_bytes("", DUMP_PREFIX_NONE, skb->data, skb->len); - rxs->rate_idx = 0; - return 0; + return -EINVAL; } static void ath9k_process_rssi(struct ath_common *common, -- cgit v1.2.3 From bc6fb35644ee46725f51ef27e901bd5d7e52c101 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 6 May 2010 22:41:14 -0400 Subject: ath9k_hw: Update initvals for AR9003 for xb113 Generated using the new shiny intivals-tool [1]: initvals -w -f ar9003 > ar9003_initvals.h The respective checksums are: 0x000000005a76829d ar9300_2p0_radio_postamble 0x000000009d90cb74 ar9300Modes_lowest_ob_db_tx_gain_table_2p0 0x00000000e0bc2c84 ar9300Modes_fast_clock_2p0 0x00000000852fca34 ar9300_2p0_radio_core 0x0000000000000000 ar9300Common_rx_gain_table_merlin_2p0 0x0000000078658fb5 ar9300_2p0_mac_postamble 0x0000000023235333 ar9300_2p0_soc_postamble 0x0000000054d41904 ar9200_merlin_2p0_radio_core 0x00000000618455d4 ar9300_2p0_baseband_postamble 0x000000009aa590a4 ar9300_2p0_baseband_core 0x000000004783d946 ar9300Modes_high_power_tx_gain_table_2p0 0x000000006681db44 ar9300Modes_high_ob_db_tx_gain_table_2p0 0x000000001f318700 ar9300Common_rx_gain_table_2p0 0x000000009990cb74 ar9300Modes_low_ob_db_tx_gain_table_2p0 0x00000000c9d66d40 ar9300_2p0_mac_core 0x0000000039139500 ar9300Common_wo_xlna_rx_gain_table_2p0 0x00000000a0c54980 ar9300_2p0_soc_preamble 0x00000000292e2544 ar9300PciePhy_pll_on_clkreq_disable_L1_2p0 0x000000002d3e2544 ar9300PciePhy_clkreq_enable_L1_2p0 0x00000000293e2544 ar9300PciePhy_clkreq_disable_L1_2p0 [1] http://wireless.kernel.org/en/users/Drivers/ath9k_hw/initvals-tool Cc: Tom Hammel Cc: Enis Akay Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_initvals.h | 204 +++++++++++------------ 1 file changed, 102 insertions(+), 102 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_initvals.h index a131cd10ef29..ef6116e13033 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_initvals.h @@ -541,7 +541,7 @@ static const u32 ar9300_2p0_mac_postamble[][5] = { static const u32 ar9300_2p0_soc_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00007010, 0x00000023, 0x00000023, 0x00000022, 0x00000022}, + {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, }; static const u32 ar9200_merlin_2p0_radio_core[][2] = { @@ -588,12 +588,12 @@ static const u32 ar9200_merlin_2p0_radio_core[][2] = { static const u32 ar9300_2p0_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005}, + {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a800b}, {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, - {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, + {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x00000b9c}, {0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044}, {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, @@ -744,7 +744,7 @@ static const u32 ar9300_2p0_baseband_core[][2] = { {0x0000a408, 0x0e79e5c6}, {0x0000a40c, 0x00820820}, {0x0000a414, 0x1ce739ce}, - {0x0000a418, 0x7d001dce}, + {0x0000a418, 0x2d001dce}, {0x0000a41c, 0x1ce739ce}, {0x0000a420, 0x000001ce}, {0x0000a424, 0x1ce739ce}, @@ -756,7 +756,7 @@ static const u32 ar9300_2p0_baseband_core[][2] = { {0x0000a43c, 0x00000000}, {0x0000a440, 0x00000000}, {0x0000a444, 0x00000000}, - {0x0000a448, 0x07000080}, + {0x0000a448, 0x04000080}, {0x0000a44c, 0x00000001}, {0x0000a450, 0x00010000}, {0x0000a458, 0x00000000}, @@ -777,7 +777,7 @@ static const u32 ar9300_2p0_baseband_core[][2] = { {0x0000a638, 0x00000000}, {0x0000a63c, 0x00000000}, {0x0000a640, 0x00000000}, - {0x0000a644, 0x3ffd9d74}, + {0x0000a644, 0x3fad9d74}, {0x0000a648, 0x0048060a}, {0x0000a64c, 0x00000637}, {0x0000a670, 0x03020100}, @@ -835,9 +835,9 @@ static const u32 ar9300_2p0_baseband_core[][2] = { static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050db, 0x000050db, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00020220, 0x00020220, 0x00000000, 0x00000000}, - {0x0000a504, 0x06020223, 0x06020223, 0x04000002, 0x04000002}, + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, @@ -848,28 +848,28 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x34043643, 0x34043643, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x38043a44, 0x38043a44, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x3b043e45, 0x3b043e45, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x40063e46, 0x40063e46, 0x34001640, 0x34001640}, - {0x0000a540, 0x44083e46, 0x44083e46, 0x38001660, 0x38001660}, - {0x0000a544, 0x46083e66, 0x46083e66, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x4b0a3e69, 0x4b0a3e69, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x4f0a5e66, 0x4f0a5e66, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x540a7e66, 0x540a7e66, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x570a7e89, 0x570a7e89, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x5c0e7e8a, 0x5c0e7e8a, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x60127e8b, 0x60127e8b, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x65127ecc, 0x65127ecc, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x6b169ecd, 0x6b169ecd, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x70169f0e, 0x70169f0e, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, - {0x0000a580, 0x00820220, 0x00820220, 0x00800000, 0x00800000}, - {0x0000a584, 0x06820223, 0x06820223, 0x04800002, 0x04800002}, + {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, + {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, + {0x0000a584, 0x06802223, 0x06802223, 0x04800002, 0x04800002}, {0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004}, {0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200}, {0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202}, @@ -880,42 +880,42 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { {0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02}, {0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04}, {0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x34843643, 0x34843643, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x38843a44, 0x38843a44, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x3b843e45, 0x3b843e45, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x40863e46, 0x40863e46, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x4c8a3065, 0x44883e46, 0x44883e46, 0x38801660}, - {0x0000a5c4, 0x46883e66, 0x46883e66, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x4b8a3e69, 0x4b8a3e69, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x4f8a5e66, 0x4f8a5e66, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x548a7e66, 0x548a7e66, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x578a7e89, 0x578a7e89, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x5c8e7e8a, 0x5c8e7e8a, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x60927e8b, 0x60927e8b, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x65927ecc, 0x65927ecc, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x6b969ecd, 0x6b969ecd, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x70969f0e, 0x70969f0e, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, + {0x0000a5b0, 0x34825643, 0x34825643, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x38825a44, 0x38825a44, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x3b825e45, 0x3b825e45, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x41825e4a, 0x41825e4a, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x48825e6c, 0x48825e6c, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x4e825e8e, 0x4e825e8e, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x53825eb2, 0x53825eb2, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x59825eb5, 0x59825eb5, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5f825ef6, 0x5f825ef6, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x62825f56, 0x62825f56, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x66827f56, 0x66827f56, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6a829f56, 0x6a829f56, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x70849f56, 0x70849f56, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, - {0x00016048, 0xad241a61, 0xad241a61, 0xad241a61, 0xad241a61}, + {0x00016048, 0xae481a61, 0xae481a61, 0xae481a61, 0xae481a61}, {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, {0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, - {0x00016448, 0xad241a61, 0xad241a61, 0xad241a61, 0xad241a61}, + {0x00016448, 0xae481a61, 0xae481a61, 0xae481a61, 0xae481a61}, {0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, {0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, - {0x00016848, 0xad241a61, 0xad241a61, 0xad241a61, 0xad241a61}, + {0x00016848, 0xae481a61, 0xae481a61, 0xae481a61, 0xae481a61}, {0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, }; static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050db, 0x000050db, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00020220, 0x00020220, 0x00000000, 0x00000000}, - {0x0000a504, 0x06020223, 0x06020223, 0x04000002, 0x04000002}, + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, @@ -926,28 +926,28 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x34043643, 0x34043643, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x38043a44, 0x38043a44, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x3b043e45, 0x3b043e45, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x40063e46, 0x40063e46, 0x34001640, 0x34001640}, - {0x0000a540, 0x44083e46, 0x44083e46, 0x38001660, 0x38001660}, - {0x0000a544, 0x46083e66, 0x46083e66, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x4b0a3e69, 0x4b0a3e69, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x4f0a5e66, 0x4f0a5e66, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x540a7e66, 0x540a7e66, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x570a7e89, 0x570a7e89, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x5c0e7e8a, 0x5c0e7e8a, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x60127e8b, 0x60127e8b, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x65127ecc, 0x65127ecc, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x6b169ecd, 0x6b169ecd, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x70169f0e, 0x70169f0e, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, - {0x0000a580, 0x00820220, 0x00820220, 0x00800000, 0x00800000}, - {0x0000a584, 0x06820223, 0x06820223, 0x04800002, 0x04800002}, + {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, + {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, + {0x0000a584, 0x06802223, 0x06802223, 0x04800002, 0x04800002}, {0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004}, {0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200}, {0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202}, @@ -958,34 +958,34 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { {0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02}, {0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04}, {0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x34843643, 0x34843643, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x38843a44, 0x38843a44, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x3b843e45, 0x3b843e45, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x40863e46, 0x40863e46, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x44883e46, 0x44883e46, 0x38801660, 0x38801660}, - {0x0000a5c4, 0x46883e66, 0x46883e66, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x4b8a3e69, 0x4b8a3e69, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x4f8a5e66, 0x4f8a5e66, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x548a7e66, 0x548a7e66, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x578a7e89, 0x578a7e89, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x5c8e7e8a, 0x5c8e7e8a, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x60927e8b, 0x60927e8b, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x65927ecc, 0x65927ecc, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x6b969ecd, 0x6b969ecd, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x70969f0e, 0x70969f0e, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, + {0x0000a5b0, 0x34825643, 0x34825643, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x38825a44, 0x38825a44, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x3b825e45, 0x3b825e45, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x41825e4a, 0x41825e4a, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x48825e6c, 0x48825e6c, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x4e825e8e, 0x4e825e8e, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x53825eb2, 0x53825eb2, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x59825eb5, 0x59825eb5, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5f825ef6, 0x5f825ef6, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x62825f56, 0x62825f56, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x66827f56, 0x66827f56, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6a829f56, 0x6a829f56, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x70849f56, 0x70849f56, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, - {0x00016048, 0x8c001a61, 0x8c001a61, 0x8c001a61, 0x8c001a61}, + {0x00016048, 0x8e481a61, 0x8e481a61, 0x8e481a61, 0x8e481a61}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, - {0x00016448, 0x8c001a61, 0x8c001a61, 0x8c001a61, 0x8c001a61}, + {0x00016448, 0x8e481a61, 0x8e481a61, 0x8e481a61, 0x8e481a61}, {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, - {0x00016848, 0x8c001a61, 0x8c001a61, 0x8c001a61, 0x8c001a61}, + {0x00016848, 0x8e481a61, 0x8e481a61, 0x8e481a61, 0x8e481a61}, {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; -- cgit v1.2.3 From 2ff6575b1e497f88acf2c7de7e1ba015267b689d Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 7 May 2010 13:37:57 +0530 Subject: ath9k_htc: Handle IDLE LED properly Switch LED off/on when handling CONF_CHANGE_IDLE. Not doing this would leave the radio LED on even though the chip would be in full sleep mode. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 7c9e33ba95ab..f50358605266 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1099,7 +1099,7 @@ fail_tx: return 0; } -static int ath9k_htc_radio_enable(struct ieee80211_hw *hw) +static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led) { struct ath9k_htc_priv *priv = hw->priv; struct ath_hw *ah = priv->ah; @@ -1147,6 +1147,13 @@ static int ath9k_htc_radio_enable(struct ieee80211_hw *hw) priv->tx_queues_stop = false; spin_unlock_bh(&priv->tx_lock); + if (led) { + /* Enable LED */ + ath9k_hw_cfg_output(ah, ah->led_pin, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_set_gpio(ah, ah->led_pin, 0); + } + ieee80211_wake_queues(hw); return ret; @@ -1158,13 +1165,13 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) int ret = 0; mutex_lock(&priv->mutex); - ret = ath9k_htc_radio_enable(hw); + ret = ath9k_htc_radio_enable(hw, false); mutex_unlock(&priv->mutex); return ret; } -static void ath9k_htc_radio_disable(struct ieee80211_hw *hw) +static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led) { struct ath9k_htc_priv *priv = hw->priv; struct ath_hw *ah = priv->ah; @@ -1177,6 +1184,12 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw) return; } + if (led) { + /* Disable LED */ + ath9k_hw_set_gpio(ah, ah->led_pin, 1); + ath9k_hw_cfg_gpio_input(ah, ah->led_pin); + } + /* Cancel all the running timers/work .. */ cancel_work_sync(&priv->ps_work); cancel_delayed_work_sync(&priv->ath9k_ani_work); @@ -1217,7 +1230,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) struct ath9k_htc_priv *priv = hw->priv; mutex_lock(&priv->mutex); - ath9k_htc_radio_disable(hw); + ath9k_htc_radio_disable(hw, false); mutex_unlock(&priv->mutex); } @@ -1337,7 +1350,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) if (enable_radio) { ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); - ath9k_htc_radio_enable(hw); + ath9k_htc_radio_enable(hw, true); ath_print(common, ATH_DBG_CONFIG, "not-idle: enabling radio\n"); } @@ -1389,10 +1402,9 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) if (priv->ps_idle) { ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); - ath9k_htc_radio_disable(hw); + ath9k_htc_radio_disable(hw, true); } - mutex_unlock(&priv->mutex); return 0; -- cgit v1.2.3 From d717fd6188b2ea63cf9dc0a870fd312c312841cd Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 7 May 2010 11:38:58 +0300 Subject: wl1271: Add sysfs file to retrieve HW PG-version and ROM-version This patch reads the HW PG version (along with a ROM-version, embedded in the same value) from the wl1271 hardware and publishes the value in a sysfs -file. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 2 ++ drivers/net/wireless/wl12xx/wl1271_boot.c | 12 +++++++++++ drivers/net/wireless/wl12xx/wl1271_boot.h | 3 +++ drivers/net/wireless/wl12xx/wl1271_main.c | 34 +++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 75887e74205b..3e1769dd1b55 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -388,6 +388,8 @@ struct wl1271 { size_t fw_len; struct wl1271_nvs_file *nvs; + s8 hw_pg_ver; + u8 bssid[ETH_ALEN]; u8 mac_addr[ETH_ALEN]; u8 bss_type; diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 7e797157783e..139a1e0fc7e3 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -440,11 +440,23 @@ static int wl1271_boot_write_irq_polarity(struct wl1271 *wl) return 0; } +static void wl1271_boot_hw_version(struct wl1271 *wl) +{ + u32 fuse; + + fuse = wl1271_top_reg_read(wl, REG_FUSE_DATA_2_1); + fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET; + + wl->hw_pg_ver = (s8)fuse; +} + int wl1271_boot(struct wl1271 *wl) { int ret = 0; u32 tmp, clk, pause; + wl1271_boot_hw_version(wl); + if (REF_CLOCK == 0 || REF_CLOCK == 2 || REF_CLOCK == 4) /* ref clk: 19.2/38.4/38.4-XTAL */ clk = 0x3; diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h index 95ecc5241959..f829699d597e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.h +++ b/drivers/net/wireless/wl12xx/wl1271_boot.h @@ -55,6 +55,9 @@ struct wl1271_static_data { #define OCP_REG_CLK_POLARITY 0x0cb2 #define OCP_REG_CLK_PULL 0x0cb4 +#define REG_FUSE_DATA_2_1 0x050a +#define PG_VER_MASK 0x3c +#define PG_VER_OFFSET 2 #define CMD_MBOX_ADDRESS 0x407B4 diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b0837255de6f..36dfdee5fbfe 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -2232,6 +2232,29 @@ static DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR, wl1271_sysfs_show_bt_coex_state, wl1271_sysfs_store_bt_coex_state); +static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct wl1271 *wl = dev_get_drvdata(dev); + ssize_t len; + + /* FIXME: what's the maximum length of buf? page size?*/ + len = 500; + + mutex_lock(&wl->mutex); + if (wl->hw_pg_ver >= 0) + len = snprintf(buf, len, "%d\n", wl->hw_pg_ver); + else + len = snprintf(buf, len, "n/a\n"); + mutex_unlock(&wl->mutex); + + return len; +} + +static DEVICE_ATTR(hw_pg_ver, S_IRUGO | S_IWUSR, + wl1271_sysfs_show_hw_pg_ver, NULL); + int wl1271_register_hw(struct wl1271 *wl) { int ret; @@ -2351,6 +2374,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->vif = NULL; wl->flags = 0; wl->sg_enabled = true; + wl->hw_pg_ver = -1; for (i = 0; i < ACX_TX_DESCRIPTORS; i++) wl->tx_frames[i] = NULL; @@ -2380,8 +2404,18 @@ struct ieee80211_hw *wl1271_alloc_hw(void) goto err_platform; } + /* Create sysfs file to get HW PG version */ + ret = device_create_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); + if (ret < 0) { + wl1271_error("failed to create sysfs file hw_pg_ver"); + goto err_bt_coex_state; + } + return hw; +err_bt_coex_state: + device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); + err_platform: platform_device_unregister(wl->plat_dev); -- cgit v1.2.3 From 554d7209c87a7b7ec70c14d9ed1c01e05f5dbc23 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 7 May 2010 11:38:59 +0300 Subject: wl1271: Fix 32 bit register read related endiannes bug Reading single registers did not pay attention to data endianness. This patch fix that. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 2 +- drivers/net/wireless/wl12xx/wl1271_io.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 3e1769dd1b55..6f1b6b5640c0 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -481,7 +481,7 @@ struct wl1271 { struct wl1271_stats stats; struct wl1271_debugfs debugfs; - u32 buffer_32; + __le32 buffer_32; u32 buffer_cmd; u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index d8837ef0bb40..bc806c74c63a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h @@ -74,12 +74,12 @@ static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) wl1271_raw_read(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32), false); - return wl->buffer_32; + return le32_to_cpu(wl->buffer_32); } static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) { - wl->buffer_32 = val; + wl->buffer_32 = cpu_to_le32(val); wl1271_raw_write(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32), false); } -- cgit v1.2.3 From 69e5434cd536c7eb4d5be0d0b7db06ed420c1315 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 7 May 2010 11:39:00 +0300 Subject: wl1271: Fix to join and channel number handling This patch changes the way JOIN's are performed, and channel numbers updated. The reason for this is that the firmware JOIN command clears WPA(2) key material, and if done while associated to a WPA(2) secured AP, will render the data-path unusable. While the channel is not usually changed while associated (and currently we could not even support something like that), after performing a scan operation while associated, mac80211 will re-set the current channel to the driver. This caused our problem. Also, the mac80211 is assuming that the driver channel configuration remains persistent over periods of IDLE. Therefore remove channel resetting to zero from the unjoin function. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 36dfdee5fbfe..3e4b9fbe8a00 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1139,10 +1139,25 @@ out: return ret; } -static int wl1271_join(struct wl1271 *wl) +static int wl1271_join(struct wl1271 *wl, bool set_assoc) { int ret; + /* + * One of the side effects of the JOIN command is that is clears + * WPA/WPA2 keys from the chipset. Performing a JOIN while associated + * to a WPA/WPA2 access point will therefore kill the data-path. + * Currently there is no supported scenario for JOIN during + * association - if it becomes a supported scenario, the WPA/WPA2 keys + * must be handled somehow. + * + */ + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + wl1271_info("JOIN while associated."); + + if (set_assoc) + set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); + ret = wl1271_cmd_join(wl, wl->set_bss_type); if (ret < 0) goto out; @@ -1189,7 +1204,6 @@ static int wl1271_unjoin(struct wl1271 *wl) goto out; clear_bit(WL1271_FLAG_JOINED, &wl->flags); - wl->channel = 0; memset(wl->bssid, 0, ETH_ALEN); /* stop filterting packets based on bssid */ @@ -1249,7 +1263,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) goto out; /* if the channel changes while joined, join again */ - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + if (changed & IEEE80211_CONF_CHANGE_CHANNEL && + ((wl->band != conf->channel->band) || + (wl->channel != channel))) { wl->band = conf->channel->band; wl->channel = channel; @@ -1269,7 +1285,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) "failed %d", ret); if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { - ret = wl1271_join(wl); + ret = wl1271_join(wl, false); if (ret < 0) wl1271_warning("cmd join to update channel " "failed %d", ret); @@ -1651,6 +1667,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, enum wl1271_cmd_ps_mode mode; struct wl1271 *wl = hw->priv; bool do_join = false; + bool set_assoc = false; int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); @@ -1760,7 +1777,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (bss_conf->assoc) { u32 rates; wl->aid = bss_conf->aid; - set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); + set_assoc = true; /* * use basic rates from AP, and determine lowest rate @@ -1860,7 +1877,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } if (do_join) { - ret = wl1271_join(wl); + ret = wl1271_join(wl, set_assoc); if (ret < 0) { wl1271_warning("cmd join failed %d", ret); goto out_sleep; -- cgit v1.2.3 From 0cbb1034396243173fa5acac715fcf416fa76644 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Fri, 7 May 2010 11:39:01 +0300 Subject: wl1271: Increase timeout for command event waiting Incresed the timeout value for command complete event waiting from 100 ms to 750 ms. In some rare cases it can take about 600 ms before complete event for join command is received. This is most propably caused by the firmware being busy with scanning related activities. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 00f78b7aa384..f2820b42a943 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -129,7 +129,7 @@ enum cmd_templ { /* unit ms */ #define WL1271_COMMAND_TIMEOUT 2000 #define WL1271_CMD_TEMPL_MAX_SIZE 252 -#define WL1271_EVENT_TIMEOUT 100 +#define WL1271_EVENT_TIMEOUT 750 struct wl1271_cmd_header { __le16 id; -- cgit v1.2.3 From cbd1ea87a198669537591cef9ee834d6986c169b Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 7 May 2010 11:39:02 +0300 Subject: wl1271: Reduce PSM entry hang over period from 128 => 1 ms Currently, we configure a 128ms hang over period for the PSM entry (the firmware will remain active for 128ms after sending the null func for PSM and getting an ack for it.) This is a huge power consumption issue, and appears unnecessary. So, configure the value to 1 ms. Signed-off-by: Juuso Oikarinen Reviewed-by: Janne Ylalehto Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 4292f8dc2a80..0a2d2ed1e1bf 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -515,7 +515,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send) ps_params->ps_mode = ps_mode; ps_params->send_null_data = send; ps_params->retries = 5; - ps_params->hang_over_period = 128; + ps_params->hang_over_period = 1; ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, -- cgit v1.2.3 From 1affa091975e47d50ce6a88e9b1abfe717c2fe27 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Fri, 7 May 2010 11:03:08 +0200 Subject: rt2x00: rt2800: use correct txop value in tx descriptor rt2800 devices use a different enumeration to specify what IFS values should be used on frame transmission compared to the other rt2x00 devices. Hence, create a new enum called txop that contains the valid values. Furthermore use the appropriate txop values as found in the ralink drivers: - TXOP_BACKOFF for management frames - TXOP_SIFS for subsequent fragments in a burst - TXOP_HTTXOP for all data frames Signed-off-by: Helmut Schaa Acked-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 2 +- drivers/net/wireless/rt2x00/rt2800usb.c | 2 +- drivers/net/wireless/rt2x00/rt2x00ht.c | 17 +++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00queue.h | 2 ++ drivers/net/wireless/rt2x00/rt2x00reg.h | 10 ++++++++++ 5 files changed, 31 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index f08b6a37bf2d..df2c3fb8b4b6 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -643,7 +643,7 @@ static int rt2800pci_write_tx_data(struct queue_entry* entry, rt2x00_set_field32(&word, TXWI_W0_AMPDU, test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags)); rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density); - rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->ifs); + rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop); rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs); rt2x00_set_field32(&word, TXWI_W0_BW, test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags)); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 67f8234f24d0..94b68127811e 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -417,7 +417,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXWI_W0_AMPDU, test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags)); rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density); - rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->ifs); + rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop); rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs); rt2x00_set_field32(&word, TXWI_W0_BW, test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags)); diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c index 1056c92143a8..5a407602ce3e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c @@ -35,6 +35,7 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; if (tx_info->control.sta) txdesc->mpdu_density = @@ -66,4 +67,20 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); + + /* + * Determine IFS values + * - Use TXOP_BACKOFF for management frames + * - Use TXOP_SIFS for fragment bursts + * - Use TXOP_HTTXOP for everything else + * + * Note: rt2800 devices won't use CTS protection (if used) + * for frames not transmitted with TXOP_HTTXOP + */ + if (ieee80211_is_mgmt(hdr->frame_control)) + txdesc->txop = TXOP_BACKOFF; + else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)) + txdesc->txop = TXOP_SIFS; + else + txdesc->txop = TXOP_HTTXOP; } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 94a48c174d67..36a957adc1f9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -299,6 +299,7 @@ enum txentry_desc_flags { * @retry_limit: Max number of retries. * @aifs: AIFS value. * @ifs: IFS value. + * @txop: IFS value for 11n capable chips. * @cw_min: cwmin value. * @cw_max: cwmax value. * @cipher: Cipher type used for encryption. @@ -328,6 +329,7 @@ struct txentry_desc { short retry_limit; short aifs; short ifs; + short txop; short cw_min; short cw_max; diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index 603bfc0adaa3..b9fe94873ee0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -100,6 +100,16 @@ enum ifs { IFS_NONE = 3, }; +/* + * IFS backoff values for HT devices + */ +enum txop { + TXOP_HTTXOP = 0, + TXOP_PIFS = 1, + TXOP_SIFS = 2, + TXOP_BACKOFF = 3, +}; + /* * Cipher types for hardware encryption */ -- cgit v1.2.3 From 1ae5dc342ac78d7a42965fd1f323815f6f5ef2c1 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 10 May 2010 05:01:31 -0700 Subject: net: trans_start cleanups Now that core network takes care of trans_start updates, dont do it in drivers themselves, if possible. Drivers can avoid one cache miss (on dev->trans_start) in their start_xmit() handler. Exceptions are NETIF_F_LLTX drivers Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/wireless/atmel.c | 1 - drivers/net/wireless/libertas/main.c | 2 +- drivers/net/wireless/libertas/tx.c | 2 -- drivers/net/wireless/orinoco/main.c | 1 - drivers/net/wireless/prism54/islpci_eth.c | 2 -- drivers/net/wireless/ray_cs.c | 1 - drivers/net/wireless/wl3501_cs.c | 3 +-- drivers/net/wireless/zd1201.c | 3 +-- 8 files changed, 3 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 3edbbcf0f548..c8f7090b27d3 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -865,7 +865,6 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) /* low bit of first byte of destination tells us if broadcast */ tx_update_descriptor(priv, *(skb->data) & 0x01, len + 18, buff, TX_PACKET_TYPE_DATA); - dev->trans_start = jiffies; dev->stats.tx_bytes += len; spin_unlock_irqrestore(&priv->irqlock, flags); diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 38edad6f24b8..d9b8ee130c45 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -229,7 +229,7 @@ static void lbs_tx_timeout(struct net_device *dev) lbs_pr_err("tx watch dog timeout\n"); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ if (priv->currenttxskb) lbs_send_tx_feedback(priv, 0); diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 52d244ea3d97..a9bf658659eb 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -147,8 +147,6 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; - if (priv->monitormode) { /* Keep the skb to echo it back once Tx feedback is received from FW */ diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 1d60c7e4392a..884a7779fc5f 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -517,7 +517,6 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) goto busy; } - dev->trans_start = jiffies; stats->tx_bytes += HERMES_802_3_OFFSET + skb->len; goto ok; diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 64585da8a96c..2fc52bc2d7dd 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -224,8 +224,6 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) priv->data_low_tx_full = 1; } - /* set the transmission time */ - ndev->trans_start = jiffies; ndev->stats.tx_packets++; ndev->stats.tx_bytes += skb->len; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index d9c45bfcee61..73972ee76540 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -941,7 +941,6 @@ static netdev_tx_t ray_dev_start_xmit(struct sk_buff *skb, case XMIT_MSG_BAD: case XMIT_OK: default: - dev->trans_start = jiffies; dev_kfree_skb(skb); } diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 65dd502eab0d..1e61e6cace90 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1307,7 +1307,7 @@ static void wl3501_tx_timeout(struct net_device *dev) printk(KERN_ERR "%s: Error %d resetting card on Tx timeout!\n", dev->name, rc); else { - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } } @@ -1326,7 +1326,6 @@ static netdev_tx_t wl3501_hard_start_xmit(struct sk_buff *skb, spin_lock_irqsave(&this->lock, flags); enabled = wl3501_block_interrupt(this); - dev->trans_start = jiffies; rc = wl3501_send_pkt(this, skb->data, skb->len); if (enabled) wl3501_unblock_interrupt(this); diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 1e2b684f8ed4..ece86a5d3355 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -827,7 +827,6 @@ static netdev_tx_t zd1201_hard_start_xmit(struct sk_buff *skb, } else { dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; } kfree_skb(skb); @@ -845,7 +844,7 @@ static void zd1201_tx_timeout(struct net_device *dev) usb_unlink_urb(zd->tx_urb); dev->stats.tx_errors++; /* Restart the timeout to quiet the watchdog: */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ } static int zd1201_set_mac_address(struct net_device *dev, void *p) -- cgit v1.2.3 From 9e385c56a1eecfb62dbc5162037fb4ed1676b27e Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 10 May 2010 14:24:34 -0400 Subject: rtl8180: change PCI DMA mask to DMA_BIT_MASK(32) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From the original report: "I had problems to get my rtl8185 PCI card running on Sparc64: I always got an error about "No suitable DMA available" followed by an error that no device could be detected. When comparing the rtl8180 driver to others I noticed that others are mostly using DMA_BIT_MASK so I changed the custom mask to DMA_BIT_MASK(32) which fixed my issue." Reported-by: Tiziano Müller Acked-by: David S. Miller Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8180_dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index cbdc5cfec90c..9430f962c168 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -926,8 +926,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, goto err_free_reg; } - if ((err = pci_set_dma_mask(pdev, 0xFFFFFF00ULL)) || - (err = pci_set_consistent_dma_mask(pdev, 0xFFFFFF00ULL))) { + if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) || + (err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))) { printk(KERN_ERR "%s (rtl8180): No suitable DMA available\n", pci_name(pdev)); goto err_free_reg; -- cgit v1.2.3 From 5efa3a6bf4dd1674920d7419cbde9d731cdb61f1 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 7 May 2010 18:23:22 -0400 Subject: ath9k_hw: enable PCIe low power mode for AR9003 Cc: Paul Shaw Cc: Don Breslin Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8f37f1c2a380..f2d0389a66c0 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -573,6 +573,26 @@ static int __ath9k_hw_init(struct ath_hw *ah) ath9k_hw_init_mode_regs(ah); + /* + * Configire PCIE after Ini init. SERDES values now come from ini file + * This enables PCIe low power mode. + */ + if (AR_SREV_9300_20_OR_LATER(ah)) { + u32 regval; + unsigned int i; + + /* Set Bits 16 and 17 in the AR_WA register. */ + regval = REG_READ(ah, AR_WA); + regval |= 0x00030000; + REG_WRITE(ah, AR_WA, regval); + + for (i = 0; i < ah->iniPcieSerdesLowPower.ia_rows; i++) { + REG_WRITE(ah, + INI_RA(&ah->iniPcieSerdesLowPower, i, 0), + INI_RA(&ah->iniPcieSerdesLowPower, i, 1)); + } + } + if (ah->is_pciexpress) ath9k_hw_configpcipowersave(ah, 0, 0); else -- cgit v1.2.3 From 7ada88e5e5d7b465de8d0441b4a8d890a602074f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 8 May 2010 18:21:01 +0200 Subject: iwlwifi: remove stray mutex_unlock() This mutex_unlock() has been here from the initial commit, but as nearly as I can tell, there isn't a reason for it. Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 9dad8672d700..3faa78ceaed1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2482,7 +2482,6 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) &priv->_3945.shared_phys, GFP_KERNEL); if (!priv->_3945.shared_virt) { IWL_ERR(priv, "failed to allocate pci memory\n"); - mutex_unlock(&priv->mutex); return -ENOMEM; } -- cgit v1.2.3 From 277a64d17ee819161242ce3059a9c2d0f8dfd29c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 8 May 2010 18:23:20 +0200 Subject: ath9k/htc_drv_main: null dereference typo This is a stray null dereference. We initialize "ista" properly later on. Signed-off-by: Dan Carpenter Acked-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index f50358605266..e75db06e8087 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -461,7 +461,7 @@ static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, struct ath_common *common = ath9k_hw_common(priv->ah); struct ath9k_htc_target_aggr aggr; struct ieee80211_sta *sta = NULL; - struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; + struct ath9k_htc_sta *ista; int ret = 0; u8 cmd_rsp; -- cgit v1.2.3 From 0730d114194364d078dbd0cfce708e8c67dccdfb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 8 May 2010 18:24:02 +0200 Subject: ath9k/htc_drv_main: off by one error I changed "> ATH9K_HTC_MAX_TID" to ">= ATH9K_HTC_MAX_TID" to avoid a potential overflow. Signed-off-by: Dan Carpenter Acked-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index e75db06e8087..6c386dad1d40 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -465,7 +465,7 @@ static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, int ret = 0; u8 cmd_rsp; - if (tid > ATH9K_HTC_MAX_TID) + if (tid >= ATH9K_HTC_MAX_TID) return -EINVAL; memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); -- cgit v1.2.3 From 05e8594d5594acb62896571a7fe04faa647e0437 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 8 May 2010 18:24:38 +0200 Subject: ath5k: several off by one range checks There are several places that use > ARRAY_SIZE() instead of >= ARRAY_SIZE(). Signed-off-by: Dan Carpenter Acked-by: Bob Copeland Acked-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ani.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index 584a32859bdb..f2311ab35504 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c @@ -73,7 +73,7 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) const s8 hi[] = { -14, -12 }; const s8 fr[] = { -78, -80 }; #endif - if (level < 0 || level > ARRAY_SIZE(sz)) { + if (level < 0 || level >= ARRAY_SIZE(sz)) { ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "level out of range %d", level); return; @@ -104,7 +104,7 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) { const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; - if (level < 0 || level > ARRAY_SIZE(val) || + if (level < 0 || level >= ARRAY_SIZE(val) || level > ah->ah_sc->ani_state.max_spur_level) { ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "level out of range %d", level); @@ -129,7 +129,7 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) { const int val[] = { 0, 4, 8 }; - if (level < 0 || level > ARRAY_SIZE(val)) { + if (level < 0 || level >= ARRAY_SIZE(val)) { ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "level out of range %d", level); return; -- cgit v1.2.3 From d43e49ec83b7d1b1339205e1f3980a447658dc40 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 8 May 2010 23:40:18 +0200 Subject: rt2x00: Fix setting of txdesc->length field. We should take the stripping of the IV into account for the txdesc->length field. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Tested-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00crypto.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index d291c7862e10..583dacd8d241 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -128,6 +128,7 @@ void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc) /* Pull buffer to correct size */ skb_pull(skb, txdesc->iv_len); + txdesc->length -= txdesc->iv_len; /* IV/EIV data has officially been stripped */ skbdesc->flags |= SKBDESC_IV_STRIPPED; -- cgit v1.2.3 From e6a8aab1648226d64772a8224df0677f555a5632 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 8 May 2010 23:40:19 +0200 Subject: rt2x00: Clean up rt2800usb.h. Remove unused RXD_DESC_SIZE define and remove duplicated RXWI definitions from rt2800.h. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.h | 40 --------------------------------- 1 file changed, 40 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index d1d8ae94b4d4..2bca6a71a7f5 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h @@ -79,8 +79,6 @@ */ #define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) #define RXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) -#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 1 * sizeof(__le32) ) /* * TX Info structure @@ -112,44 +110,6 @@ #define RXINFO_W0_USB_DMA_RX_PKT_LEN FIELD32(0x0000ffff) -/* - * RX WI structure - */ - -/* - * Word0 - */ -#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff) -#define RXWI_W0_KEY_INDEX FIELD32(0x00000300) -#define RXWI_W0_BSSID FIELD32(0x00001c00) -#define RXWI_W0_UDF FIELD32(0x0000e000) -#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) -#define RXWI_W0_TID FIELD32(0xf0000000) - -/* - * Word1 - */ -#define RXWI_W1_FRAG FIELD32(0x0000000f) -#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0) -#define RXWI_W1_MCS FIELD32(0x007f0000) -#define RXWI_W1_BW FIELD32(0x00800000) -#define RXWI_W1_SHORT_GI FIELD32(0x01000000) -#define RXWI_W1_STBC FIELD32(0x06000000) -#define RXWI_W1_PHYMODE FIELD32(0xc0000000) - -/* - * Word2 - */ -#define RXWI_W2_RSSI0 FIELD32(0x000000ff) -#define RXWI_W2_RSSI1 FIELD32(0x0000ff00) -#define RXWI_W2_RSSI2 FIELD32(0x00ff0000) - -/* - * Word3 - */ -#define RXWI_W3_SNR0 FIELD32(0x000000ff) -#define RXWI_W3_SNR1 FIELD32(0x0000ff00) - /* * RX descriptor format for RX Ring. */ -- cgit v1.2.3 From 78b8f3b0ddb061af1e3907f9c4bca76eae39f79f Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 8 May 2010 23:40:20 +0200 Subject: rt2x00: Don't check whether hardware crypto is enabled when reading RXD. We should simply follow what the hardware told us it has done. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 8 +++----- drivers/net/wireless/rt2x00/rt2800pci.c | 17 +++++++---------- drivers/net/wireless/rt2x00/rt2800usb.c | 8 ++------ drivers/net/wireless/rt2x00/rt61pci.c | 8 ++------ drivers/net/wireless/rt2x00/rt73usb.c | 8 ++------ 5 files changed, 16 insertions(+), 33 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index c6e6e7b0ea53..f90b308899aa 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1213,11 +1213,9 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { - rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER); - if (rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR)) - rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY; - } + rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER); + if (rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR)) + rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY; if (rxdesc->cipher != CIPHER_NONE) { _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]); diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index df2c3fb8b4b6..b9ec08180aad 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -840,16 +840,13 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, if (rt2x00_get_field32(rxd3, RXD_W3_CRC_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { - /* - * Unfortunately we don't know the cipher type used during - * decryption. This prevents us from correct providing - * correct statistics through debugfs. - */ - rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); - rxdesc->cipher_status = - rt2x00_get_field32(rxd3, RXD_W3_CIPHER_ERROR); - } + /* + * Unfortunately we don't know the cipher type used during + * decryption. This prevents us from correct providing + * correct statistics through debugfs. + */ + rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); + rxdesc->cipher_status = rt2x00_get_field32(rxd3, RXD_W3_CIPHER_ERROR); if (rt2x00_get_field32(rxd3, RXD_W3_DECRYPTED)) { /* diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 94b68127811e..df7ad981b808 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -549,7 +549,6 @@ static void rt2800usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, static void rt2800usb_fill_rxdone(struct queue_entry *entry, struct rxdone_entry_desc *rxdesc) { - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); __le32 *rxi = (__le32 *)entry->skb->data; __le32 *rxwi; @@ -595,11 +594,8 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { - rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); - rxdesc->cipher_status = - rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR); - } + rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); + rxdesc->cipher_status = rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR); if (rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED)) { /* diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 8099ecaf8694..1b0c70d65699 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1968,12 +1968,8 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry, if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { - rxdesc->cipher = - rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG); - rxdesc->cipher_status = - rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR); - } + rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG); + rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR); if (rxdesc->cipher != CIPHER_NONE) { _rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv[0]); diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 1399c18bc667..6acba620971f 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1644,12 +1644,8 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { - rxdesc->cipher = - rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG); - rxdesc->cipher_status = - rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR); - } + rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG); + rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR); if (rxdesc->cipher != CIPHER_NONE) { _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]); -- cgit v1.2.3 From 59679b91d1d33ebe90b72ffded9a57dba788fa6b Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 8 May 2010 23:40:21 +0200 Subject: rt2x00: Factor out TXWI writing to common rt2800 code. TXWI writing is exactly the same for rt2800pci and rt2800usb, so make it common code. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 54 +++++++++++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2800lib.h | 2 ++ drivers/net/wireless/rt2x00/rt2800pci.c | 56 +-------------------------------- drivers/net/wireless/rt2x00/rt2800usb.c | 50 ++--------------------------- 4 files changed, 60 insertions(+), 102 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 525267d4cc3e..28d82ce05527 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -281,6 +281,60 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); +void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc) +{ + __le32 *txwi = (__le32 *)(skb->data - TXWI_DESC_SIZE); + u32 word; + + /* + * Initialize TX Info descriptor + */ + rt2x00_desc_read(txwi, 0, &word); + rt2x00_set_field32(&word, TXWI_W0_FRAG, + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0); + rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); + rt2x00_set_field32(&word, TXWI_W0_TS, + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_AMPDU, + test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density); + rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop); + rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs); + rt2x00_set_field32(&word, TXWI_W0_BW, + test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_SHORT_GI, + test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc); + rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode); + rt2x00_desc_write(txwi, 0, word); + + rt2x00_desc_read(txwi, 1, &word); + rt2x00_set_field32(&word, TXWI_W1_ACK, + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W1_NSEQ, + test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); + rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, + test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? + txdesc->key_idx : 0xff); + rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, + txdesc->length); + rt2x00_set_field32(&word, TXWI_W1_PACKETID, txdesc->queue + 1); + rt2x00_desc_write(txwi, 1, word); + + /* + * Always write 0 to IV/EIV fields, hardware will insert the IV + * from the IVEIV register when TXD_W3_WIV is set to 0. + * When TXD_W3_WIV is set to 1 it will use the IV data + * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which + * crypto entry in the registers should be used to encrypt the frame. + */ + _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); + _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); +} +EXPORT_SYMBOL_GPL(rt2800_write_txwi); + #ifdef CONFIG_RT2X00_LIB_DEBUGFS const struct rt2x00debug rt2800_rt2x00debug = { .owner = THIS_MODULE, diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index ebabeae62d1b..b805310e126c 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -111,6 +111,8 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, const u8 command, const u8 token, const u8 arg0, const u8 arg1); +void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc); + extern const struct rt2x00debug rt2800_rt2x00debug; int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index b9ec08180aad..bd56cd16485a 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -616,67 +616,13 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, static int rt2800pci_write_tx_data(struct queue_entry* entry, struct txentry_desc *txdesc) { - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct sk_buff *skb = entry->skb; - struct skb_frame_desc *skbdesc; int ret; - __le32 *txwi; - u32 word; ret = rt2x00pci_write_tx_data(entry, txdesc); if (ret) return ret; - skbdesc = get_skb_frame_desc(skb); - txwi = (__le32 *)(skb->data - rt2x00dev->ops->extra_tx_headroom); - - /* - * Initialize TX Info descriptor - */ - rt2x00_desc_read(txwi, 0, &word); - rt2x00_set_field32(&word, TXWI_W0_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0); - rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); - rt2x00_set_field32(&word, TXWI_W0_TS, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_AMPDU, - test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density); - rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop); - rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs); - rt2x00_set_field32(&word, TXWI_W0_BW, - test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_SHORT_GI, - test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc); - rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode); - rt2x00_desc_write(txwi, 0, word); - - rt2x00_desc_read(txwi, 1, &word); - rt2x00_set_field32(&word, TXWI_W1_ACK, - test_bit(ENTRY_TXD_ACK, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W1_NSEQ, - test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); - rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, - test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? - txdesc->key_idx : 0xff); - rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, - txdesc->length); - rt2x00_set_field32(&word, TXWI_W1_PACKETID, - skbdesc->entry->queue->qid + 1); - rt2x00_desc_write(txwi, 1, word); - - /* - * Always write 0 to IV/EIV fields, hardware will insert the IV - * from the IVEIV register when TXD_W3_WIV is set to 0. - * When TXD_W3_WIV is set to 1 it will use the IV data - * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which - * crypto entry in the registers should be used to encrypt the frame. - */ - _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); - _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); + rt2800_write_txwi(entry->skb, txdesc); return 0; } diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index df7ad981b808..b39b858e0cf1 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -401,59 +401,15 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); __le32 *txi = skbdesc->desc; - __le32 *txwi = &txi[TXINFO_DESC_SIZE / sizeof(__le32)]; u32 word; /* - * Initialize TX Info descriptor + * Initialize TXWI descriptor */ - rt2x00_desc_read(txwi, 0, &word); - rt2x00_set_field32(&word, TXWI_W0_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0); - rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); - rt2x00_set_field32(&word, TXWI_W0_TS, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_AMPDU, - test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density); - rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop); - rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs); - rt2x00_set_field32(&word, TXWI_W0_BW, - test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_SHORT_GI, - test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc); - rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode); - rt2x00_desc_write(txwi, 0, word); - - rt2x00_desc_read(txwi, 1, &word); - rt2x00_set_field32(&word, TXWI_W1_ACK, - test_bit(ENTRY_TXD_ACK, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W1_NSEQ, - test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); - rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, - test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? - txdesc->key_idx : 0xff); - rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, - txdesc->length); - rt2x00_set_field32(&word, TXWI_W1_PACKETID, - skbdesc->entry->queue->qid + 1); - rt2x00_desc_write(txwi, 1, word); + rt2800_write_txwi(skb, txdesc); /* - * Always write 0 to IV/EIV fields, hardware will insert the IV - * from the IVEIV register when TXINFO_W0_WIV is set to 0. - * When TXINFO_W0_WIV is set to 1 it will use the IV data - * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which - * crypto entry in the registers should be used to encrypt the frame. - */ - _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); - _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); - - /* - * Initialize TX descriptor + * Initialize TXINFO descriptor */ rt2x00_desc_read(txi, 0, &word); rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, -- cgit v1.2.3 From 2de64dd22d0390688b853788dcadee3c0ad9e518 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 8 May 2010 23:40:22 +0200 Subject: rt2x00: Factor out RXWI processing to common rt2800 code. RXWI processing is exactly the same for rt2800pci and rt2800usb, so make it common code. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 44 ++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2800lib.h | 1 + drivers/net/wireless/rt2x00/rt2800pci.c | 57 +++++-------------------- drivers/net/wireless/rt2x00/rt2800usb.c | 74 ++++++++++----------------------- 4 files changed, 79 insertions(+), 97 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 28d82ce05527..7410ac1acaff 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -335,6 +335,50 @@ void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc) } EXPORT_SYMBOL_GPL(rt2800_write_txwi); +void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *rxdesc) +{ + __le32 *rxwi = (__le32 *) skb->data; + u32 word; + + rt2x00_desc_read(rxwi, 0, &word); + + rxdesc->cipher = rt2x00_get_field32(word, RXWI_W0_UDF); + rxdesc->size = rt2x00_get_field32(word, RXWI_W0_MPDU_TOTAL_BYTE_COUNT); + + rt2x00_desc_read(rxwi, 1, &word); + + if (rt2x00_get_field32(word, RXWI_W1_SHORT_GI)) + rxdesc->flags |= RX_FLAG_SHORT_GI; + + if (rt2x00_get_field32(word, RXWI_W1_BW)) + rxdesc->flags |= RX_FLAG_40MHZ; + + /* + * Detect RX rate, always use MCS as signal type. + */ + rxdesc->dev_flags |= RXDONE_SIGNAL_MCS; + rxdesc->signal = rt2x00_get_field32(word, RXWI_W1_MCS); + rxdesc->rate_mode = rt2x00_get_field32(word, RXWI_W1_PHYMODE); + + /* + * Mask of 0x8 bit to remove the short preamble flag. + */ + if (rxdesc->rate_mode == RATE_MODE_CCK) + rxdesc->signal &= ~0x8; + + rt2x00_desc_read(rxwi, 2, &word); + + rxdesc->rssi = + (rt2x00_get_field32(word, RXWI_W2_RSSI0) + + rt2x00_get_field32(word, RXWI_W2_RSSI1)) / 2; + + /* + * Remove RXWI descriptor from start of buffer. + */ + skb_pull(skb, RXWI_DESC_SIZE); +} +EXPORT_SYMBOL_GPL(rt2800_process_rxwi); + #ifdef CONFIG_RT2X00_LIB_DEBUGFS const struct rt2x00debug rt2800_rt2x00debug = { .owner = THIS_MODULE, diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index b805310e126c..94de999e2290 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -112,6 +112,7 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, const u8 arg0, const u8 arg1); void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc); +void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *txdesc); extern const struct rt2x00debug rt2800_rt2x00debug; diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index bd56cd16485a..308842a2e8ba 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -770,20 +770,11 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct queue_entry_priv_pci *entry_priv = entry->priv_data; __le32 *rxd = entry_priv->desc; - __le32 *rxwi = (__le32 *)entry->skb->data; - u32 rxd3; - u32 rxwi0; - u32 rxwi1; - u32 rxwi2; - u32 rxwi3; - - rt2x00_desc_read(rxd, 3, &rxd3); - rt2x00_desc_read(rxwi, 0, &rxwi0); - rt2x00_desc_read(rxwi, 1, &rxwi1); - rt2x00_desc_read(rxwi, 2, &rxwi2); - rt2x00_desc_read(rxwi, 3, &rxwi3); - - if (rt2x00_get_field32(rxd3, RXD_W3_CRC_ERROR)) + u32 word; + + rt2x00_desc_read(rxd, 3, &word); + + if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; /* @@ -791,10 +782,9 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, * decryption. This prevents us from correct providing * correct statistics through debugfs. */ - rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); - rxdesc->cipher_status = rt2x00_get_field32(rxd3, RXD_W3_CIPHER_ERROR); + rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR); - if (rt2x00_get_field32(rxd3, RXD_W3_DECRYPTED)) { + if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) { /* * Hardware has stripped IV/EIV data from 802.11 frame during * decryption. Unfortunately the descriptor doesn't contain @@ -809,47 +799,22 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, rxdesc->flags |= RX_FLAG_MMIC_ERROR; } - if (rt2x00_get_field32(rxd3, RXD_W3_MY_BSS)) + if (rt2x00_get_field32(word, RXD_W3_MY_BSS)) rxdesc->dev_flags |= RXDONE_MY_BSS; - if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD)) + if (rt2x00_get_field32(word, RXD_W3_L2PAD)) rxdesc->dev_flags |= RXDONE_L2PAD; - if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) - rxdesc->flags |= RX_FLAG_SHORT_GI; - - if (rt2x00_get_field32(rxwi1, RXWI_W1_BW)) - rxdesc->flags |= RX_FLAG_40MHZ; - /* - * Detect RX rate, always use MCS as signal type. + * Process the RXWI structure that is at the start of the buffer. */ - rxdesc->dev_flags |= RXDONE_SIGNAL_MCS; - rxdesc->rate_mode = rt2x00_get_field32(rxwi1, RXWI_W1_PHYMODE); - rxdesc->signal = rt2x00_get_field32(rxwi1, RXWI_W1_MCS); - - /* - * Mask of 0x8 bit to remove the short preamble flag. - */ - if (rxdesc->rate_mode == RATE_MODE_CCK) - rxdesc->signal &= ~0x8; - - rxdesc->rssi = - (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) + - rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2; - - rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT); + rt2800_process_rxwi(entry->skb, rxdesc); /* * Set RX IDX in register to inform hardware that we have handled * this entry and it is available for reuse again. */ rt2800_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx); - - /* - * Remove TXWI descriptor from start of buffer. - */ - skb_pull(entry->skb, RXWI_DESC_SIZE); } /* diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index b39b858e0cf1..db371193b507 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -507,53 +507,45 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, { struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); __le32 *rxi = (__le32 *)entry->skb->data; - __le32 *rxwi; __le32 *rxd; - u32 rxi0; - u32 rxwi0; - u32 rxwi1; - u32 rxwi2; - u32 rxwi3; - u32 rxd0; + u32 word; int rx_pkt_len; + /* + * Copy descriptor to the skbdesc->desc buffer, making it safe from + * moving of frame data in rt2x00usb. + */ + memcpy(skbdesc->desc, rxi, skbdesc->desc_len); + /* * RX frame format is : * | RXINFO | RXWI | header | L2 pad | payload | pad | RXD | USB pad | * |<------------ rx_pkt_len -------------->| */ - rt2x00_desc_read(rxi, 0, &rxi0); - rx_pkt_len = rt2x00_get_field32(rxi0, RXINFO_W0_USB_DMA_RX_PKT_LEN); - - rxwi = (__le32 *)(entry->skb->data + RXINFO_DESC_SIZE); + rt2x00_desc_read(rxi, 0, &word); + rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN); /* - * FIXME : we need to check for rx_pkt_len validity + * Remove the RXINFO structure from the sbk. */ - rxd = (__le32 *)(entry->skb->data + RXINFO_DESC_SIZE + rx_pkt_len); + skb_pull(entry->skb, RXINFO_DESC_SIZE); /* - * Copy descriptor to the skbdesc->desc buffer, making it safe from - * moving of frame data in rt2x00usb. + * FIXME: we need to check for rx_pkt_len validity */ - memcpy(skbdesc->desc, rxi, skbdesc->desc_len); + rxd = (__le32 *)(entry->skb->data + rx_pkt_len); /* * It is now safe to read the descriptor on all architectures. */ - rt2x00_desc_read(rxwi, 0, &rxwi0); - rt2x00_desc_read(rxwi, 1, &rxwi1); - rt2x00_desc_read(rxwi, 2, &rxwi2); - rt2x00_desc_read(rxwi, 3, &rxwi3); - rt2x00_desc_read(rxd, 0, &rxd0); + rt2x00_desc_read(rxd, 0, &word); - if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR)) + if (rt2x00_get_field32(word, RXD_W0_CRC_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; - rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); - rxdesc->cipher_status = rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR); + rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W0_CIPHER_ERROR); - if (rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED)) { + if (rt2x00_get_field32(word, RXD_W0_DECRYPTED)) { /* * Hardware has stripped IV/EIV data from 802.11 frame during * decryption. Unfortunately the descriptor doesn't contain @@ -568,41 +560,21 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, rxdesc->flags |= RX_FLAG_MMIC_ERROR; } - if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS)) + if (rt2x00_get_field32(word, RXD_W0_MY_BSS)) rxdesc->dev_flags |= RXDONE_MY_BSS; - if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD)) + if (rt2x00_get_field32(word, RXD_W0_L2PAD)) rxdesc->dev_flags |= RXDONE_L2PAD; - if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) - rxdesc->flags |= RX_FLAG_SHORT_GI; - - if (rt2x00_get_field32(rxwi1, RXWI_W1_BW)) - rxdesc->flags |= RX_FLAG_40MHZ; - /* - * Detect RX rate, always use MCS as signal type. + * Remove RXD descriptor from end of buffer. */ - rxdesc->dev_flags |= RXDONE_SIGNAL_MCS; - rxdesc->rate_mode = rt2x00_get_field32(rxwi1, RXWI_W1_PHYMODE); - rxdesc->signal = rt2x00_get_field32(rxwi1, RXWI_W1_MCS); - - /* - * Mask of 0x8 bit to remove the short preamble flag. - */ - if (rxdesc->rate_mode == RATE_MODE_CCK) - rxdesc->signal &= ~0x8; - - rxdesc->rssi = - (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) + - rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2; - - rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT); + skb_trim(entry->skb, rx_pkt_len); /* - * Remove RXWI descriptor from start of buffer. + * Process the RXWI structure. */ - skb_pull(entry->skb, skbdesc->desc_len); + rt2800_process_rxwi(entry->skb, rxdesc); } /* -- cgit v1.2.3 From d61cb26696e19494c049297def6c8f37d9e2f534 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 8 May 2010 23:40:24 +0200 Subject: rt2x00: Clean up all driver's kick_tx_queue callback functions. All of the driver's kick_tx_queue callback functions treat the TX queue for beacons in a special manner. Clean this up by integrating the kicking of the beacon queue into the write_beacon callback function, and let the generic code no longer call the kick_tx_queue callback function when updating the beacon. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 19 +++++------ drivers/net/wireless/rt2x00/rt2500pci.c | 19 +++++------ drivers/net/wireless/rt2x00/rt2500usb.c | 55 +++++++++++++------------------ drivers/net/wireless/rt2x00/rt2800pci.c | 20 +++++------ drivers/net/wireless/rt2x00/rt2800usb.c | 29 +++++----------- drivers/net/wireless/rt2x00/rt2x00queue.c | 5 +-- drivers/net/wireless/rt2x00/rt61pci.c | 30 ++++++++--------- drivers/net/wireless/rt2x00/rt73usb.c | 40 ++++++++-------------- 8 files changed, 83 insertions(+), 134 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 6f898913492a..9c13a4e0e731 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1089,6 +1089,14 @@ static void rt2400pci_write_beacon(struct queue_entry *entry) rt2x00_desc_read(entry_priv->desc, 1, &word); rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); rt2x00_desc_write(entry_priv->desc, 1, word); + + /* + * Enable beaconing again. + */ + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, 1); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); } static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, @@ -1096,17 +1104,6 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, { u32 reg; - if (queue == QID_BEACON) { - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) { - rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TBCN, 1); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); - } - return; - } - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue == QID_AC_BE)); rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue == QID_AC_BK)); diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d9b630455e7d..84ab56ec5872 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1246,6 +1246,14 @@ static void rt2500pci_write_beacon(struct queue_entry *entry) rt2x00_desc_read(entry_priv->desc, 1, &word); rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); rt2x00_desc_write(entry_priv->desc, 1, word); + + /* + * Enable beaconing again. + */ + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, 1); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); } static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, @@ -1253,17 +1261,6 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, { u32 reg; - if (queue == QID_BEACON) { - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) { - rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TBCN, 1); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); - } - return; - } - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue == QID_AC_BE)); rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue == QID_AC_BK)); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index f90b308899aa..5ee9b9fd77b3 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1090,7 +1090,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry) struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint); int length; - u16 reg; + u16 reg, reg0; /* * Add the descriptor in front of the skb. @@ -1132,6 +1132,26 @@ static void rt2500usb_write_beacon(struct queue_entry *entry) * Send out the guardian byte. */ usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); + + /* + * Enable beaconing again. + */ + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); + reg0 = reg; + rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 1); + /* + * Beacon generation will fail initially. + * To prevent this we need to change the TXRX_CSR19 + * register several times (reg0 is the same as reg + * except for TXRX_CSR19_BEACON_GEN, which is 0 in reg0 + * and 1 in reg). + */ + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); } static int rt2500usb_get_tx_data_len(struct queue_entry *entry) @@ -1148,37 +1168,6 @@ static int rt2500usb_get_tx_data_len(struct queue_entry *entry) return length; } -static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue) -{ - u16 reg, reg0; - - if (queue != QID_BEACON) { - rt2x00usb_kick_tx_queue(rt2x00dev, queue); - return; - } - - rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); - if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) { - rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); - rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); - reg0 = reg; - rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 1); - /* - * Beacon generation will fail initially. - * To prevent this we need to change the TXRX_CSR19 - * register several times (reg0 is the same as reg - * except for TXRX_CSR19_BEACON_GEN, which is 0 in reg0 - * and 1 in reg). - */ - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); - } -} - /* * RX control handlers */ @@ -1777,7 +1766,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .write_tx_data = rt2x00usb_write_tx_data, .write_beacon = rt2500usb_write_beacon, .get_tx_data_len = rt2500usb_get_tx_data_len, - .kick_tx_queue = rt2500usb_kick_tx_queue, + .kick_tx_queue = rt2x00usb_kick_tx_queue, .kill_tx_queue = rt2x00usb_kill_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, .config_shared_key = rt2500usb_config_key, diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 308842a2e8ba..6d564607bbbd 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -704,6 +704,14 @@ static void rt2800pci_write_beacon(struct queue_entry *entry) beacon_base + skbdesc->desc_len, entry->skb->data, entry->skb->len); + /* + * Enable beaconing again. + */ + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + /* * Clean up beacon skb. */ @@ -716,18 +724,6 @@ static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, { struct data_queue *queue; unsigned int idx, qidx = 0; - u32 reg; - - if (queue_idx == QID_BEACON) { - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); - if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) { - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); - rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); - } - return; - } if (queue_idx > QID_HCCA && queue_idx != QID_MGMT) return; diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index db371193b507..dbec71852f00 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -458,6 +458,14 @@ static void rt2800usb_write_beacon(struct queue_entry *entry) entry->skb->data, entry->skb->len, REGISTER_TIMEOUT32(entry->skb->len)); + /* + * Enable beaconing again. + */ + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + /* * Clean up the beacon skb. */ @@ -480,25 +488,6 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry) return length; } -static void rt2800usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue) -{ - u32 reg; - - if (queue != QID_BEACON) { - rt2x00usb_kick_tx_queue(rt2x00dev, queue); - return; - } - - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); - if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) { - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); - rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); - } -} - /* * RX control handlers */ @@ -667,7 +656,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .write_tx_data = rt2x00usb_write_tx_data, .write_beacon = rt2800usb_write_beacon, .get_tx_data_len = rt2800usb_get_tx_data_len, - .kick_tx_queue = rt2800usb_kick_tx_queue, + .kick_tx_queue = rt2x00usb_kick_tx_queue, .kill_tx_queue = rt2x00usb_kill_tx_queue, .fill_rxdone = rt2800usb_fill_rxdone, .config_shared_key = rt2800_config_shared_key, diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 59d9459acfaf..949aaad0cbd2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -602,12 +602,9 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); /* - * Send beacon to hardware. - * Also enable beacon generation, which might have been disabled - * by the driver during the config_beacon() callback function. + * Send beacon to hardware and enable beacon genaration.. */ rt2x00dev->ops->lib->write_beacon(intf->beacon); - rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); mutex_unlock(&intf->beacon_skb_mutex); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 1b0c70d65699..9e3a1ee426e2 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1868,6 +1868,19 @@ static void rt61pci_write_beacon(struct queue_entry *entry) beacon_base + skbdesc->desc_len, entry->skb->data, entry->skb->len); + /* + * Enable beaconing again. + * + * For Wi-Fi faily generated beacons between participating + * stations. Set TBTT phase adaptive adjustment step to 8us. + */ + rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); + + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + /* * Clean up beacon skb. */ @@ -1880,23 +1893,6 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, { u32 reg; - if (queue == QID_BEACON) { - /* - * For Wi-Fi faily generated beacons between participating - * stations. Set TBTT phase adaptive adjustment step to 8us. - */ - rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) { - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); - } - return; - } - rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, (queue == QID_AC_BE)); rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, (queue == QID_AC_BK)); diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 6acba620971f..ca3707af4b4c 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1535,6 +1535,19 @@ static void rt73usb_write_beacon(struct queue_entry *entry) entry->skb->data, entry->skb->len, REGISTER_TIMEOUT32(entry->skb->len)); + /* + * Enable beaconing again. + * + * For Wi-Fi faily generated beacons between participating stations. + * Set TBTT phase adaptive adjustment step to 8us (default 16us) + */ + rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); + + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); + /* * Clean up the beacon skb. */ @@ -1556,31 +1569,6 @@ static int rt73usb_get_tx_data_len(struct queue_entry *entry) return length; } -static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue) -{ - u32 reg; - - if (queue != QID_BEACON) { - rt2x00usb_kick_tx_queue(rt2x00dev, queue); - return; - } - - /* - * For Wi-Fi faily generated beacons between participating stations. - * Set TBTT phase adaptive adjustment step to 8us (default 16us) - */ - rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); - if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) { - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); - } -} - /* * RX control handlers */ @@ -2261,7 +2249,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .write_tx_data = rt2x00usb_write_tx_data, .write_beacon = rt73usb_write_beacon, .get_tx_data_len = rt73usb_get_tx_data_len, - .kick_tx_queue = rt73usb_kick_tx_queue, + .kick_tx_queue = rt2x00usb_kick_tx_queue, .kill_tx_queue = rt2x00usb_kill_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, .config_shared_key = rt73usb_config_shared_key, -- cgit v1.2.3 From f224f4ef794c4a9146a7fa7303018fecab8c9328 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 8 May 2010 23:40:25 +0200 Subject: rt2x00: provide beacon's txdesc to write_beacon callback function. Preparation to fix rt2800 beaconing. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 3 ++- drivers/net/wireless/rt2x00/rt2500pci.c | 3 ++- drivers/net/wireless/rt2x00/rt2500usb.c | 3 ++- drivers/net/wireless/rt2x00/rt2800pci.c | 3 ++- drivers/net/wireless/rt2x00/rt2800usb.c | 3 ++- drivers/net/wireless/rt2x00/rt2x00.h | 3 ++- drivers/net/wireless/rt2x00/rt2x00queue.c | 2 +- drivers/net/wireless/rt2x00/rt61pci.c | 3 ++- drivers/net/wireless/rt2x00/rt73usb.c | 3 ++- 9 files changed, 17 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 9c13a4e0e731..4b3845152e1f 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1059,7 +1059,8 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ -static void rt2400pci_write_beacon(struct queue_entry *entry) +static void rt2400pci_write_beacon(struct queue_entry *entry, + struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct queue_entry_priv_pci *entry_priv = entry->priv_data; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 84ab56ec5872..d876c6d87591 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1216,7 +1216,8 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ -static void rt2500pci_write_beacon(struct queue_entry *entry) +static void rt2500pci_write_beacon(struct queue_entry *entry, + struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct queue_entry_priv_pci *entry_priv = entry->priv_data; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 5ee9b9fd77b3..30c0544e8036 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1082,7 +1082,8 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, */ static void rt2500usb_beacondone(struct urb *urb); -static void rt2500usb_write_beacon(struct queue_entry *entry) +static void rt2500usb_write_beacon(struct queue_entry *entry, + struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 6d564607bbbd..80c67681cf9f 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -678,7 +678,8 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ -static void rt2800pci_write_beacon(struct queue_entry *entry) +static void rt2800pci_write_beacon(struct queue_entry *entry, + struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index dbec71852f00..d992a9352ed7 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -427,7 +427,8 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ -static void rt2800usb_write_beacon(struct queue_entry *entry) +static void rt2800usb_write_beacon(struct queue_entry *entry, + struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 4f9b666f7a7f..6c1ff4c15c84 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -551,7 +551,8 @@ struct rt2x00lib_ops { struct txentry_desc *txdesc); int (*write_tx_data) (struct queue_entry *entry, struct txentry_desc *txdesc); - void (*write_beacon) (struct queue_entry *entry); + void (*write_beacon) (struct queue_entry *entry, + struct txentry_desc *txdesc); int (*get_tx_data_len) (struct queue_entry *entry); void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 949aaad0cbd2..12ec68577f99 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -604,7 +604,7 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, /* * Send beacon to hardware and enable beacon genaration.. */ - rt2x00dev->ops->lib->write_beacon(intf->beacon); + rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc); mutex_unlock(&intf->beacon_skb_mutex); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 9e3a1ee426e2..24363634e6fd 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1842,7 +1842,8 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ -static void rt61pci_write_beacon(struct queue_entry *entry) +static void rt61pci_write_beacon(struct queue_entry *entry, + struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ca3707af4b4c..81f6db1b16f2 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1504,7 +1504,8 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ -static void rt73usb_write_beacon(struct queue_entry *entry) +static void rt73usb_write_beacon(struct queue_entry *entry, + struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); -- cgit v1.2.3 From 3b9f0ed78cf2eb678edd60d74a4a36f5947d003d Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 8 May 2010 23:40:26 +0200 Subject: rt2x00: Fix beaconing on rt2800. According to the Ralink vendor driver for rt2800 we don't need a full TXD for a beacon but just a TXWI in front of the actual beacon. Fix the rt2800pci and rt2800usb beaconing code accordingly. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 17 +++++++++-------- drivers/net/wireless/rt2x00/rt2800usb.c | 14 ++++++-------- 2 files changed, 15 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 80c67681cf9f..7d4778d66e77 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -682,7 +682,6 @@ static void rt2800pci_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); unsigned int beacon_base; u32 reg; @@ -695,15 +694,17 @@ static void rt2800pci_write_beacon(struct queue_entry *entry, rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); /* - * Write entire beacon with descriptor to register. + * Add the TXWI for the beacon to the skb. + */ + rt2800_write_txwi(entry->skb, txdesc); + skb_push(entry->skb, TXWI_DESC_SIZE); + + /* + * Write entire beacon with TXWI to register. */ beacon_base = HW_BEACON_OFFSET(entry->entry_idx); - rt2800_register_multiwrite(rt2x00dev, - beacon_base, - skbdesc->desc, skbdesc->desc_len); - rt2800_register_multiwrite(rt2x00dev, - beacon_base + skbdesc->desc_len, - entry->skb->data, entry->skb->len); + rt2800_register_multiwrite(rt2x00dev, beacon_base, + entry->skb->data, entry->skb->len); /* * Enable beaconing again. diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index d992a9352ed7..00e7906dc208 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -431,17 +431,9 @@ static void rt2800usb_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); unsigned int beacon_base; u32 reg; - /* - * Add the descriptor in front of the skb. - */ - skb_push(entry->skb, entry->queue->desc_size); - memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); - skbdesc->desc = entry->skb->data; - /* * Disable beaconing while we are reloading the beacon data, * otherwise we might be sending out invalid data. @@ -450,6 +442,12 @@ static void rt2800usb_write_beacon(struct queue_entry *entry, rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + /* + * Add the TXWI for the beacon to the skb. + */ + rt2800_write_txwi(entry->skb, txdesc); + skb_push(entry->skb, TXWI_DESC_SIZE); + /* * Write entire beacon with descriptor to register. */ -- cgit v1.2.3 From 6295d81552f4b58256a9f7d85ce630b862598753 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sun, 9 May 2010 21:24:22 +0200 Subject: rt2x00: Clean up generic procedures on descriptor writing. With a little bit of restructuring it isn't necessary to have special cases in rt2x00queue_write_tx_descriptor for writing the descriptor for beacons. Simply split off the kicking of the TX queue to a separate function with is only called for non-beacons. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 12ec68577f99..97b2c7650656 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -428,20 +428,23 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, * it is now ready to be dumped to userspace through debugfs. */ rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, entry->skb); +} + +static void rt2x00queue_kick_tx_queue(struct queue_entry *entry, + struct txentry_desc *txdesc) +{ + struct data_queue *queue = entry->queue; + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; /* * Check if we need to kick the queue, there are however a few rules - * 1) Don't kick beacon queue - * 2) Don't kick unless this is the last in frame in a burst. + * 1) Don't kick unless this is the last in frame in a burst. * When the burst flag is set, this frame is always followed * by another frame which in some way are related to eachother. * This is true for fragments, RTS or CTS-to-self frames. - * 3) Rule 2 can be broken when the available entries + * 2) Rule 1 can be broken when the available entries * in the queue are less then a certain threshold. */ - if (entry->queue->qid == QID_BEACON) - return; - if (rt2x00queue_threshold(queue) || !test_bit(ENTRY_TXD_BURST, &txdesc->flags)) rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid); @@ -537,6 +540,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, rt2x00queue_index_inc(queue, Q_INDEX); rt2x00queue_write_tx_descriptor(entry, &txdesc); + rt2x00queue_kick_tx_queue(entry, &txdesc); return 0; } -- cgit v1.2.3 From a6bc03a07f8676d336e697914e9fe6cd54474ad1 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Mon, 10 May 2010 11:35:36 +0200 Subject: wireless: rt2x00: rt2800usb: replace X by x s/X/x Signed-off-by: Xose Vazquez Perez Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 00e7906dc208..d48d705d1808 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -753,7 +753,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, /* EnGenius */ - { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Gigabyte */ { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, -- cgit v1.2.3 From 9459d59fbf0bc82ff4c804679fa8bc22788eca63 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 10 May 2010 09:24:29 -0700 Subject: wireless: depends on NET When CONFIG_NET is disabled, the attempt to build wext-priv.c fails with: net/wireless/wext-priv.c: In function 'ioctl_private_call': net/wireless/wext-priv.c:207: error: implicit declaration of function 'call_commit_handler' Signed-off-by: Randy Dunlap Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 2fbe9b4506c0..174e3442d519 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -5,6 +5,7 @@ menuconfig WLAN bool "Wireless LAN" depends on !S390 + depends on NET select WIRELESS default y ---help--- -- cgit v1.2.3 From 562db532760827f6ce30801a08e6b568848bc9f2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 29 Apr 2010 07:41:53 -0700 Subject: iwlagn: wait for asynchronous firmware loading When we kick off a firmware loading process, and then unbind from the pci device right away, we get into trouble. Avoid that by waiting for the firmware loading to finish (whether successfully or not) before the unbind in iwl_pci_remove. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 2 ++ 2 files changed, 8 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ba0fdba602cd..ae8eb09f8011 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1741,6 +1741,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) /* We have our copies now, allow OS release its copies */ release_firmware(ucode_raw); + complete(&priv->firmware_loading_complete); return; try_again: @@ -1754,6 +1755,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) IWL_ERR(priv, "failed to allocate pci memory\n"); iwl_dealloc_ucode_pci(priv); out_unbind: + complete(&priv->firmware_loading_complete); device_release_driver(&priv->pci_dev->dev); release_firmware(ucode_raw); } @@ -3671,6 +3673,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_power_initialize(priv); iwl_tt_initialize(priv); + init_completion(&priv->firmware_loading_complete); + err = iwl_request_firmware(priv, true); if (err) goto out_remove_sysfs; @@ -3711,6 +3715,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) if (!priv) return; + wait_for_completion(&priv->firmware_loading_complete); + IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); iwl_dbgfs_unregister(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index ef1720a852e9..4d4c6516430a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1304,6 +1304,8 @@ struct iwl_priv { struct delayed_work alive_start; struct delayed_work scan_check; + struct completion firmware_loading_complete; + /*For 3945 only*/ struct delayed_work thermal_periodic; struct delayed_work rfkill_poll; -- cgit v1.2.3 From 95b13014bb761a267db8bc1a47cbb35ddde587ef Mon Sep 17 00:00:00 2001 From: Shanyu Zhao Date: Wed, 21 Apr 2010 11:46:33 -0700 Subject: iwlwifi: rename 6000 series Gen2 devices to Gen2a Rename the current 6000 series Gen2 devices to Gen2a. Rename the ucode name prefix to iwlwifi-6000g2a. Also corrected the device IDs for Gen2a series devices. Signed-off-by: Jay Sternberg Signed-off-by: Shanyu Zhao Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-6000.c | 24 +++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-agn.c | 9 ++++----- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- 3 files changed, 18 insertions(+), 17 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 7acef703253a..f0570871fbb0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -67,9 +67,10 @@ #define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" #define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api) -#define IWL6000G2_FW_PRE "iwlwifi-6005-" -#define _IWL6000G2_MODULE_FIRMWARE(api) IWL6000G2_FW_PRE #api ".ucode" -#define IWL6000G2_MODULE_FIRMWARE(api) _IWL6000G2_MODULE_FIRMWARE(api) +#define IWL6000G2A_FW_PRE "iwlwifi-6000g2a-" +#define _IWL6000G2A_MODULE_FIRMWARE(api) IWL6000G2A_FW_PRE #api ".ucode" +#define IWL6000G2A_MODULE_FIRMWARE(api) _IWL6000G2A_MODULE_FIRMWARE(api) + static void iwl6000_set_ct_threshold(struct iwl_priv *priv) { @@ -408,12 +409,10 @@ static const struct iwl_ops iwl6050_ops = { .led = &iwlagn_led_ops, }; -/* - * "i": Internal configuration, use internal Power Amplifier - */ -struct iwl_cfg iwl6000g2_2agn_cfg = { - .name = "6000 Series 2x2 AGN Gen2", - .fw_name_pre = IWL6000G2_FW_PRE, + +struct iwl_cfg iwl6000g2a_2agn_cfg = { + .name = "6000 Series 2x2 AGN Gen2a", + .fw_name_pre = IWL6000G2A_FW_PRE, .ucode_api_max = IWL6000G2_UCODE_API_MAX, .ucode_api_min = IWL6000G2_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, @@ -442,9 +441,12 @@ struct iwl_cfg iwl6000g2_2agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, - .max_event_log_size = 1024, + .max_event_log_size = 512, }; +/* + * "i": Internal configuration, use internal Power Amplifier + */ struct iwl_cfg iwl6000i_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6200 AGN", .fw_name_pre = IWL6000_FW_PRE, @@ -645,4 +647,4 @@ struct iwl_cfg iwl6000_3agn_cfg = { MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL6000G2_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index dc283769780e..5cf38227c6c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3789,11 +3789,10 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, -/* 6x00 Series Gen2 */ - {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2_2agn_cfg)}, +/* 6x00 Series Gen2a */ + {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)}, /* 6x50 WiFi/WiMax Series */ {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index cd3b932ae808..e485465e4d56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -57,8 +57,8 @@ extern struct iwl_cfg iwl5100_bgn_cfg; extern struct iwl_cfg iwl5100_abg_cfg; extern struct iwl_cfg iwl5150_agn_cfg; extern struct iwl_cfg iwl5150_abg_cfg; +extern struct iwl_cfg iwl6000g2a_2agn_cfg; extern struct iwl_cfg iwl6000i_2agn_cfg; -extern struct iwl_cfg iwl6000g2_2agn_cfg; extern struct iwl_cfg iwl6000i_2abg_cfg; extern struct iwl_cfg iwl6000i_2bg_cfg; extern struct iwl_cfg iwl6000_3agn_cfg; -- cgit v1.2.3 From 1e460535ab3978b7a23e08e9f556af2f84c43235 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 23 Apr 2010 14:14:53 -0700 Subject: iwl3945: fix scan races Port following patch to 3945. "commit 90c4162ff59a3281b6d2f7206740be6217bd6758 Author: Johannes Berg Date: Wed Apr 7 00:21:36 2010 -0700 iwlwifi: fix scan races" Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-scan.c | 3 ++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 727360944859..7deed865b14f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -515,6 +515,7 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_scan_request *req); +void iwl_bg_start_internal_scan(struct work_struct *work); void iwl_internal_short_hw_scan(struct iwl_priv *priv); int iwl_force_reset(struct iwl_priv *priv, int mode); u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 447c3018296d..28e2d86ee055 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -367,7 +367,7 @@ void iwl_internal_short_hw_scan(struct iwl_priv *priv) queue_work(priv->workqueue, &priv->start_internal_scan); } -static void iwl_bg_start_internal_scan(struct work_struct *work) +void iwl_bg_start_internal_scan(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, start_internal_scan); @@ -402,6 +402,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) unlock: mutex_unlock(&priv->mutex); } +EXPORT_SYMBOL(iwl_bg_start_internal_scan); void iwl_bg_scan_check(struct work_struct *data) { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 867d105c7f08..04cedef0b006 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3739,6 +3739,7 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll); INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); + INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan); INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); iwl3945_hw_setup_deferred_work(priv); @@ -3761,6 +3762,7 @@ static void iwl3945_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work_sync(&priv->init_alive_start); cancel_delayed_work(&priv->scan_check); cancel_delayed_work(&priv->alive_start); + cancel_work_sync(&priv->start_internal_scan); cancel_work_sync(&priv->beacon_update); if (priv->cfg->ops->lib->recover_from_tx_stall) del_timer_sync(&priv->monitor_recover); -- cgit v1.2.3 From 381733cc53ce7abf3d8498f8ccf7586546c0b264 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sun, 25 Apr 2010 09:39:46 -0700 Subject: iwlwifi: remove powersave debugfs if it is not supported For the devices do not have power save support, remove the power save control related debugfs files. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 0aedbec9cbc8..f0d9b7247663 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1612,8 +1612,11 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR); - DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); + if (!priv->cfg->broken_powersave) { + DEBUGFS_ADD_FILE(sleep_level_override, dir_data, + S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); + } DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); -- cgit v1.2.3 From 683abfbefe95750f8aa47dc6d2a7ee41c01c14ad Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 26 Apr 2010 17:20:07 -0700 Subject: iwlwifi: rename "tx_power" to "chain_tx_power" The "chain_tx_power" debugfs function is to display the tx power per chain based. Name it "tx_power" is misleading. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index f0d9b7247663..b071e1bff80e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1214,7 +1214,7 @@ static ssize_t iwl_dbgfs_chain_noise_read(struct file *file, return ret; } -static ssize_t iwl_dbgfs_tx_power_read(struct file *file, +static ssize_t iwl_dbgfs_chain_tx_power_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -1565,7 +1565,7 @@ DEBUGFS_READ_FILE_OPS(ucode_tx_stats); DEBUGFS_READ_FILE_OPS(ucode_general_stats); DEBUGFS_READ_FILE_OPS(sensitivity); DEBUGFS_READ_FILE_OPS(chain_noise); -DEBUGFS_READ_FILE_OPS(tx_power); +DEBUGFS_READ_FILE_OPS(chain_tx_power); DEBUGFS_READ_FILE_OPS(power_save_status); DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); @@ -1624,7 +1624,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); - DEBUGFS_ADD_FILE(tx_power, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(chain_tx_power, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); -- cgit v1.2.3 From 92445c953eb5698d1abab16b9a43238effdc0a6d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 27 Apr 2010 03:36:15 -0700 Subject: iwlwifi: use vif iwl_bss_info_changed The iw_mode will always follow the only vif we have, but using the vif directly seems easier. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 1e11706dcf63..d8ee5283ecbe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1857,8 +1857,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); - if (changes & BSS_CHANGED_BEACON && - priv->iw_mode == NL80211_IFTYPE_AP) { + if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) { dev_kfree_skb(priv->ibss_beacon); priv->ibss_beacon = ieee80211_beacon_get(hw, vif); } @@ -1884,8 +1883,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, } /* mac80211 only sets assoc when in STATION mode */ - if (priv->iw_mode == NL80211_IFTYPE_ADHOC || - bss_conf->assoc) { + if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { memcpy(priv->staging_rxon.bssid_addr, bss_conf->bssid, ETH_ALEN); @@ -1903,7 +1901,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, * mac80211 decides to do both changes at once because * it will invoke post_associate. */ - if (priv->iw_mode == NL80211_IFTYPE_ADHOC && + if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON) { struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); -- cgit v1.2.3 From 4e7033ef491a8447247e77b20626cbc197a2eb83 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 27 Apr 2010 14:33:33 -0700 Subject: iwlwifi: remove device type checking for tx power in debugfs Instead of checking device type for enable/disable tx power control, move it to .cfg for better control and more flexibilities. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945.c | 7 +++++++ drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 3 +-- 4 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 3faa78ceaed1..360781326cb7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1714,6 +1714,11 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv) int ref_temp; int temperature = priv->temperature; + if (priv->disable_tx_power_cal || + test_bit(STATUS_SCANNING, &priv->status)) { + /* do not perform tx power calibration */ + return 0; + } /* set up new Tx power info for each and every channel, 2.4 and 5.x */ for (i = 0; i < priv->channel_count; i++) { ch_info = &priv->channel_info[i]; @@ -2842,6 +2847,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, + .tx_power_by_driver = true, }; static struct iwl_cfg iwl3945_abg_cfg = { @@ -2862,6 +2868,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, + .tx_power_by_driver = true, }; DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 136c29067489..460aea3240c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2262,6 +2262,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .temperature_kelvin = true, .max_event_log_size = 512, + .tx_power_by_driver = true, /* * Force use of chains B and C for scan RX on 5 GHz band diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7deed865b14f..60d26e4e6edc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -319,6 +319,7 @@ struct iwl_cfg { u32 monitor_recover_period; bool temperature_kelvin; u32 max_event_log_size; + const bool tx_power_by_driver; u8 scan_antennas[IEEE80211_NUM_BANDS]; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index b071e1bff80e..0faadf3a8b82 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1647,8 +1647,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal); DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, &priv->disable_chain_noise_cal); - if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || - ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) + if (priv->cfg->tx_power_by_driver) DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &priv->disable_tx_power_cal); return 0; -- cgit v1.2.3 From 6e5c800e75fad95f2a12d45d9b548b23834a13ff Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 27 Apr 2010 14:00:28 -0700 Subject: iwlwifi: use .cfg to enable/disable continuous ucode trace Instead of checking device type for enable/disable continuous ucode trace function; put it in .cfg for better control and more flexibilities. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 7 +++++++ drivers/net/wireless/iwlwifi/iwl-6000.c | 7 +++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 3 ++- 6 files changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index fb59af2d41c6..f9f8a567593d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -260,6 +260,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 128, + .ucode_tracing = true, }; struct iwl_cfg iwl1000_bg_cfg = { @@ -289,6 +290,7 @@ struct iwl_cfg iwl1000_bg_cfg = { .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 128, + .ucode_tracing = true, }; MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 460aea3240c8..a756fd4838d0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2263,7 +2263,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .temperature_kelvin = true, .max_event_log_size = 512, .tx_power_by_driver = true, - + .ucode_tracing = true, /* * Force use of chains B and C for scan RX on 5 GHz band * because the device has off-channel reception on chain A. diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 115d3ea1142f..c32db4956821 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -466,6 +466,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, + .ucode_tracing = true, }; struct iwl_cfg iwl5100_bgn_cfg = { @@ -494,6 +495,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, + .ucode_tracing = true, }; struct iwl_cfg iwl5100_abg_cfg = { @@ -520,6 +522,7 @@ struct iwl_cfg iwl5100_abg_cfg = { .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, + .ucode_tracing = true, }; struct iwl_cfg iwl5100_agn_cfg = { @@ -548,6 +551,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, + .ucode_tracing = true, }; struct iwl_cfg iwl5350_agn_cfg = { @@ -576,6 +580,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, + .ucode_tracing = true, }; struct iwl_cfg iwl5150_agn_cfg = { @@ -604,6 +609,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, + .ucode_tracing = true, }; struct iwl_cfg iwl5150_abg_cfg = { @@ -630,6 +636,7 @@ struct iwl_cfg iwl5150_abg_cfg = { .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, + .ucode_tracing = true, }; MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index f0570871fbb0..7cd45fe9b775 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -442,6 +442,7 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = { .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, + .ucode_tracing = true, }; /* @@ -479,6 +480,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 1024, + .ucode_tracing = true, }; struct iwl_cfg iwl6000i_2abg_cfg = { @@ -511,6 +513,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 1024, + .ucode_tracing = true, }; struct iwl_cfg iwl6000i_2bg_cfg = { @@ -543,6 +546,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 1024, + .ucode_tracing = true, }; struct iwl_cfg iwl6050_2agn_cfg = { @@ -577,6 +581,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .chain_noise_scale = 1500, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 1024, + .ucode_tracing = true, }; struct iwl_cfg iwl6050_2abg_cfg = { @@ -609,6 +614,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { .chain_noise_scale = 1500, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 1024, + .ucode_tracing = true, }; struct iwl_cfg iwl6000_3agn_cfg = { @@ -643,6 +649,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 1024, + .ucode_tracing = true, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 60d26e4e6edc..5034dc0037a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -320,6 +320,7 @@ struct iwl_cfg { bool temperature_kelvin; u32 max_event_log_size; const bool tx_power_by_driver; + const bool ucode_tracing; u8 scan_antennas[IEEE80211_NUM_BANDS]; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 0faadf3a8b82..59355fae1f55 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1640,8 +1640,9 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); - DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); } + if (priv->cfg->ucode_tracing) + DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal); -- cgit v1.2.3 From 65d1f89682acf4d61dec7a8b771ed34afb7c17d9 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sun, 25 Apr 2010 15:41:43 -0700 Subject: iwlwifi: use cfg to configure calibration operation sensitivity calibration and chain noise calibration are not available for all the devices; use .cfg to configure the availability of those calibration functions Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 ++++ drivers/net/wireless/iwlwifi/iwl-4965.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-5000.c | 14 ++++++++++++++ drivers/net/wireless/iwlwifi/iwl-6000.c | 14 ++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-debugfs.c | 13 ++++++++----- 6 files changed, 44 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index f9f8a567593d..4d360d74b0cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -261,6 +261,8 @@ struct iwl_cfg iwl1000_bgn_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 128, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; struct iwl_cfg iwl1000_bg_cfg = { @@ -291,6 +293,8 @@ struct iwl_cfg iwl1000_bg_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 128, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index a756fd4838d0..6b0ae74546dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2264,6 +2264,8 @@ struct iwl_cfg iwl4965_agn_cfg = { .max_event_log_size = 512, .tx_power_by_driver = true, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, /* * Force use of chains B and C for scan RX on 5 GHz band * because the device has off-channel reception on chain A. diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index c32db4956821..8ed616e59631 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -467,6 +467,8 @@ struct iwl_cfg iwl5300_agn_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; struct iwl_cfg iwl5100_bgn_cfg = { @@ -496,6 +498,8 @@ struct iwl_cfg iwl5100_bgn_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; struct iwl_cfg iwl5100_abg_cfg = { @@ -523,6 +527,8 @@ struct iwl_cfg iwl5100_abg_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; struct iwl_cfg iwl5100_agn_cfg = { @@ -552,6 +558,8 @@ struct iwl_cfg iwl5100_agn_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; struct iwl_cfg iwl5350_agn_cfg = { @@ -581,6 +589,8 @@ struct iwl_cfg iwl5350_agn_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; struct iwl_cfg iwl5150_agn_cfg = { @@ -610,6 +620,8 @@ struct iwl_cfg iwl5150_agn_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; struct iwl_cfg iwl5150_abg_cfg = { @@ -637,6 +649,8 @@ struct iwl_cfg iwl5150_abg_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 7cd45fe9b775..b69fa36fb87a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -443,6 +443,8 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; /* @@ -481,6 +483,8 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; struct iwl_cfg iwl6000i_2abg_cfg = { @@ -514,6 +518,8 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; struct iwl_cfg iwl6000i_2bg_cfg = { @@ -547,6 +553,8 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; struct iwl_cfg iwl6050_2agn_cfg = { @@ -582,6 +590,8 @@ struct iwl_cfg iwl6050_2agn_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; struct iwl_cfg iwl6050_2abg_cfg = { @@ -615,6 +625,8 @@ struct iwl_cfg iwl6050_2abg_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; struct iwl_cfg iwl6000_3agn_cfg = { @@ -650,6 +662,8 @@ struct iwl_cfg iwl6000_3agn_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 5034dc0037a1..88c641202c2f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -321,6 +321,8 @@ struct iwl_cfg { u32 max_event_log_size; const bool tx_power_by_driver; const bool ucode_tracing; + const bool sensitivity_calib_by_driver; + const bool chain_noise_calib_by_driver; u8 scan_antennas[IEEE80211_NUM_BANDS]; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 59355fae1f55..df34c3105e1e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1637,17 +1637,20 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); - if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { + if (priv->cfg->sensitivity_calib_by_driver) DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); + if (priv->cfg->chain_noise_calib_by_driver) DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); - } if (priv->cfg->ucode_tracing) DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); - DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal); - DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, - &priv->disable_chain_noise_cal); + if (priv->cfg->sensitivity_calib_by_driver) + DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, + &priv->disable_sens_cal); + if (priv->cfg->chain_noise_calib_by_driver) + DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, + &priv->disable_chain_noise_cal); if (priv->cfg->tx_power_by_driver) DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &priv->disable_tx_power_cal); -- cgit v1.2.3 From 0af0d04b8db7712498558541cbedeeebdbabf70f Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 26 Apr 2010 16:08:27 -0700 Subject: iwlwifi: give correct return information for tx power debugfs Return -EAGAIN when request tx power information and uCode is not ready; so it will not confuse with tx power information not available. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index df34c3105e1e..06905bb9238d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1225,7 +1225,7 @@ static ssize_t iwl_dbgfs_chain_tx_power_read(struct file *file, struct statistics_tx *tx; if (!iwl_is_alive(priv)) - pos += scnprintf(buf + pos, bufsz - pos, "N/A\n"); + return -EAGAIN; else { tx = &priv->statistics.tx; if (tx->tx_power.ant_a || -- cgit v1.2.3 From f401241310f4260505b1c462807c83aac5e5bbc8 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 27 Apr 2010 14:10:00 -0700 Subject: iwlwifi: wimax co-exist code clean up wifi/wimax co-exist command is part of _agn device configuration sequence; move it to iwl-agn-ucode.c which is more appropriate place for the function. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 60 +++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-core.c | 59 --------------------------- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - 3 files changed, 59 insertions(+), 61 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index ae476c234a7c..c3e3283426a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -52,6 +52,37 @@ static const s8 iwlagn_default_queue_to_tx_fifo[] = { IWL_TX_FIFO_UNUSED, }; +static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { + {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, + 0, COEX_UNASSOC_IDLE_FLAGS}, + {COEX_CU_UNASSOC_MANUAL_SCAN_RP, COEX_CU_UNASSOC_MANUAL_SCAN_WP, + 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, + {COEX_CU_UNASSOC_AUTO_SCAN_RP, COEX_CU_UNASSOC_AUTO_SCAN_WP, + 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, + {COEX_CU_CALIBRATION_RP, COEX_CU_CALIBRATION_WP, + 0, COEX_CALIBRATION_FLAGS}, + {COEX_CU_PERIODIC_CALIBRATION_RP, COEX_CU_PERIODIC_CALIBRATION_WP, + 0, COEX_PERIODIC_CALIBRATION_FLAGS}, + {COEX_CU_CONNECTION_ESTAB_RP, COEX_CU_CONNECTION_ESTAB_WP, + 0, COEX_CONNECTION_ESTAB_FLAGS}, + {COEX_CU_ASSOCIATED_IDLE_RP, COEX_CU_ASSOCIATED_IDLE_WP, + 0, COEX_ASSOCIATED_IDLE_FLAGS}, + {COEX_CU_ASSOC_MANUAL_SCAN_RP, COEX_CU_ASSOC_MANUAL_SCAN_WP, + 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, + {COEX_CU_ASSOC_AUTO_SCAN_RP, COEX_CU_ASSOC_AUTO_SCAN_WP, + 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, + {COEX_CU_ASSOC_ACTIVE_LEVEL_RP, COEX_CU_ASSOC_ACTIVE_LEVEL_WP, + 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, + {COEX_CU_RF_ON_RP, COEX_CU_RF_ON_WP, 0, COEX_CU_RF_ON_FLAGS}, + {COEX_CU_RF_OFF_RP, COEX_CU_RF_OFF_WP, 0, COEX_RF_OFF_FLAGS}, + {COEX_CU_STAND_ALONE_DEBUG_RP, COEX_CU_STAND_ALONE_DEBUG_WP, + 0, COEX_STAND_ALONE_DEBUG_FLAGS}, + {COEX_CU_IPAN_ASSOC_LEVEL_RP, COEX_CU_IPAN_ASSOC_LEVEL_WP, + 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, + {COEX_CU_RSRVD1_RP, COEX_CU_RSRVD1_WP, 0, COEX_RSRVD1_FLAGS}, + {COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS} +}; + /* * ucode */ @@ -320,6 +351,33 @@ restart: queue_work(priv->workqueue, &priv->restart); } +static int iwlagn_send_wimax_coex(struct iwl_priv *priv) +{ + struct iwl_wimax_coex_cmd coex_cmd; + + if (priv->cfg->support_wimax_coexist) { + /* UnMask wake up src at associated sleep */ + coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK; + + /* UnMask wake up src at unassociated sleep */ + coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK; + memcpy(coex_cmd.sta_prio, cu_priorities, + sizeof(struct iwl_wimax_coex_event_entry) * + COEX_NUM_OF_EVENTS); + + /* enabling the coexistence feature */ + coex_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK; + + /* enabling the priorities tables */ + coex_cmd.flags |= COEX_FLAGS_STA_TABLE_VALID_MSK; + } else { + /* coexistence is disabled */ + memset(&coex_cmd, 0, sizeof(coex_cmd)); + } + return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD, + sizeof(coex_cmd), &coex_cmd); +} + int iwlagn_alive_notify(struct iwl_priv *priv) { u32 a; @@ -407,7 +465,7 @@ int iwlagn_alive_notify(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); - iwl_send_wimax_coex(priv); + iwlagn_send_wimax_coex(priv); iwlagn_set_Xtal_calib(priv); iwl_send_calib_results(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d8ee5283ecbe..0c3b9846aa52 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -67,37 +67,6 @@ static bool bt_coex_active = true; module_param(bt_coex_active, bool, S_IRUGO); MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist"); -static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { - {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, - 0, COEX_UNASSOC_IDLE_FLAGS}, - {COEX_CU_UNASSOC_MANUAL_SCAN_RP, COEX_CU_UNASSOC_MANUAL_SCAN_WP, - 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, - {COEX_CU_UNASSOC_AUTO_SCAN_RP, COEX_CU_UNASSOC_AUTO_SCAN_WP, - 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, - {COEX_CU_CALIBRATION_RP, COEX_CU_CALIBRATION_WP, - 0, COEX_CALIBRATION_FLAGS}, - {COEX_CU_PERIODIC_CALIBRATION_RP, COEX_CU_PERIODIC_CALIBRATION_WP, - 0, COEX_PERIODIC_CALIBRATION_FLAGS}, - {COEX_CU_CONNECTION_ESTAB_RP, COEX_CU_CONNECTION_ESTAB_WP, - 0, COEX_CONNECTION_ESTAB_FLAGS}, - {COEX_CU_ASSOCIATED_IDLE_RP, COEX_CU_ASSOCIATED_IDLE_WP, - 0, COEX_ASSOCIATED_IDLE_FLAGS}, - {COEX_CU_ASSOC_MANUAL_SCAN_RP, COEX_CU_ASSOC_MANUAL_SCAN_WP, - 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, - {COEX_CU_ASSOC_AUTO_SCAN_RP, COEX_CU_ASSOC_AUTO_SCAN_WP, - 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, - {COEX_CU_ASSOC_ACTIVE_LEVEL_RP, COEX_CU_ASSOC_ACTIVE_LEVEL_WP, - 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, - {COEX_CU_RF_ON_RP, COEX_CU_RF_ON_WP, 0, COEX_CU_RF_ON_FLAGS}, - {COEX_CU_RF_OFF_RP, COEX_CU_RF_OFF_WP, 0, COEX_RF_OFF_FLAGS}, - {COEX_CU_STAND_ALONE_DEBUG_RP, COEX_CU_STAND_ALONE_DEBUG_WP, - 0, COEX_STAND_ALONE_DEBUG_FLAGS}, - {COEX_CU_IPAN_ASSOC_LEVEL_RP, COEX_CU_IPAN_ASSOC_LEVEL_WP, - 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, - {COEX_CU_RSRVD1_RP, COEX_CU_RSRVD1_WP, 0, COEX_RSRVD1_FLAGS}, - {COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS} -}; - #define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \ [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ IWL_RATE_SISO_##s##M_PLCP, \ @@ -2340,34 +2309,6 @@ void iwl_free_txq_mem(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_free_txq_mem); -int iwl_send_wimax_coex(struct iwl_priv *priv) -{ - struct iwl_wimax_coex_cmd coex_cmd; - - if (priv->cfg->support_wimax_coexist) { - /* UnMask wake up src at associated sleep */ - coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK; - - /* UnMask wake up src at unassociated sleep */ - coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK; - memcpy(coex_cmd.sta_prio, cu_priorities, - sizeof(struct iwl_wimax_coex_event_entry) * - COEX_NUM_OF_EVENTS); - - /* enabling the coexistence feature */ - coex_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK; - - /* enabling the priorities tables */ - coex_cmd.flags |= COEX_FLAGS_STA_TABLE_VALID_MSK; - } else { - /* coexistence is disabled */ - memset(&coex_cmd, 0, sizeof(coex_cmd)); - } - return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD, - sizeof(coex_cmd), &coex_cmd); -} -EXPORT_SYMBOL(iwl_send_wimax_coex); - #ifdef CONFIG_IWLWIFI_DEBUGFS #define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 88c641202c2f..f66c1c1848c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -373,7 +373,6 @@ int iwl_alloc_txq_mem(struct iwl_priv *priv); void iwl_free_txq_mem(struct iwl_priv *priv); void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info, __le32 *tx_flags); -int iwl_send_wimax_coex(struct iwl_priv *priv); #ifdef CONFIG_IWLWIFI_DEBUGFS int iwl_alloc_traffic_mem(struct iwl_priv *priv); void iwl_free_traffic_mem(struct iwl_priv *priv); -- cgit v1.2.3 From 3d38f1731e3a8217e228fde0a4bfece865bc7901 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 27 Apr 2010 18:43:33 -0700 Subject: iwlwifi: checking for all the possible failure cases Multiple error condition require fw/rf reset, driver should check all the possible errors as long as the error checking functions for the devices are available. Reported-by: Reinette Chatre Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-rx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 1dff14a67b2c..d661fce000c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -412,9 +412,11 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv, */ IWL_ERR(priv, "low ack count detected, " "restart firmware\n"); - iwl_force_reset(priv, IWL_FW_RESET); + if (!iwl_force_reset(priv, IWL_FW_RESET)) + return; } - } else if (priv->cfg->ops->lib->check_plcp_health) { + } + if (priv->cfg->ops->lib->check_plcp_health) { if (!priv->cfg->ops->lib->check_plcp_health( priv, pkt)) { /* -- cgit v1.2.3 From 459bc732abad5e461da9a06d82dfc0cb1119ef5a Mon Sep 17 00:00:00 2001 From: Shanyu Zhao Date: Tue, 27 Apr 2010 22:05:15 -0700 Subject: iwlwifi: dump firmware build info in error case Dump the firmware version and build number in case of firmware SW error. This would help firmware engineer analyze the error log. Requested-by: Jay Sternberg Signed-off-by: Shanyu Zhao Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 0c3b9846aa52..d609414844db 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1068,6 +1068,9 @@ void iwl_irq_handle_error(struct iwl_priv *priv) /* Cancel currently queued command. */ clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_ERR(priv, "Loaded firmware version: %s\n", + priv->hw->wiphy->fw_version); + priv->cfg->ops->lib->dump_nic_error_log(priv); if (priv->cfg->ops->lib->dump_csr) priv->cfg->ops->lib->dump_csr(priv); -- cgit v1.2.3 From d2e210aef3a8e7472f91d10a50ecbc91c0a53d62 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 23 Apr 2010 10:33:33 -0700 Subject: iwlwifi: make bcast LQ command available for later restore actions When adding the broadcast station the link quality command is generated on demand, sent to device, and disappears. It is thus not available for later cases when we need to restore stations and need to send the link quality command afterwards. Now, when first adding the broadcast station, also generate its link quality command to always be available for later restoring. Also fix an issue when adding local stations where the "in progress" state is never cleared. Reported-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 4 +- drivers/net/wireless/iwlwifi/iwl-core.h | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 91 ++++++++++++++++++++++++--------- drivers/net/wireless/iwlwifi/iwl-sta.h | 7 ++- 4 files changed, 75 insertions(+), 29 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d609414844db..e8c9bcafe564 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2042,7 +2042,9 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) goto out_err; /* Add the broadcast address so we can send broadcast frames */ - priv->cfg->ops->lib->add_bcast_station(priv); + err = priv->cfg->ops->lib->add_bcast_station(priv); + if (err) + goto out_err; goto out; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index f66c1c1848c8..8d53fc973a43 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -201,7 +201,7 @@ struct iwl_lib_ops { /* temperature */ struct iwl_temp_ops temp_ops; /* station management */ - void (*add_bcast_station)(struct iwl_priv *priv); + int (*add_bcast_station)(struct iwl_priv *priv); /* recover from tx queue stall */ void (*recover_from_tx_stall)(unsigned long data); /* check for plcp health */ diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index db934476b5e9..5c6b3262baf9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -418,15 +418,19 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, } EXPORT_SYMBOL(iwl_add_station_common); -static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) +static struct iwl_link_quality_cmd *iwl_sta_init_lq(struct iwl_priv *priv, + const u8 *addr, bool is_ap) { int i, r; - struct iwl_link_quality_cmd link_cmd = { - .reserved1 = 0, - }; + struct iwl_link_quality_cmd *link_cmd; u32 rate_flags; int ret = 0; + link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL); + if (!link_cmd) { + IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n"); + return NULL; + } /* Set up the rate scaling to start at selected rate, fall back * all the way down to 1M in IEEE order, and then spin on 1M */ if (is_ap) @@ -444,35 +448,36 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << RATE_MCS_ANT_POS; - link_cmd.rs_table[i].rate_n_flags = + link_cmd->rs_table[i].rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); r = iwl_get_prev_ieee_rate(r); } - link_cmd.general_params.single_stream_ant_msk = + link_cmd->general_params.single_stream_ant_msk = first_antenna(priv->hw_params.valid_tx_ant); - link_cmd.general_params.dual_stream_ant_msk = + link_cmd->general_params.dual_stream_ant_msk = priv->hw_params.valid_tx_ant & ~first_antenna(priv->hw_params.valid_tx_ant); - if (!link_cmd.general_params.dual_stream_ant_msk) { - link_cmd.general_params.dual_stream_ant_msk = ANT_AB; + if (!link_cmd->general_params.dual_stream_ant_msk) { + link_cmd->general_params.dual_stream_ant_msk = ANT_AB; } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { - link_cmd.general_params.dual_stream_ant_msk = + link_cmd->general_params.dual_stream_ant_msk = priv->hw_params.valid_tx_ant; } - link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; - link_cmd.agg_params.agg_time_limit = + link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; + link_cmd->agg_params.agg_time_limit = cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); /* Update the rate scaling for control frame Tx to AP */ - link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; + link_cmd->sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; - ret = iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, - sizeof(link_cmd), &link_cmd); + ret = iwl_send_lq_cmd(priv, link_cmd, CMD_SYNC, true); if (ret) - IWL_ERR(priv, "REPLY_TX_LINK_QUALITY_CMD failed (%d)\n", ret); + IWL_ERR(priv, "Link quality command failed (%d)\n", ret); + + return link_cmd; } /* @@ -487,6 +492,8 @@ int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs) { int ret; u8 sta_id; + struct iwl_link_quality_cmd *link_cmd; + unsigned long flags; ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); if (ret) { @@ -494,9 +501,23 @@ int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs) return ret; } - if (init_rs) + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].used |= IWL_STA_LOCAL; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + if (init_rs) { /* Set up default rate scaling table in device's station table */ - iwl_sta_init_lq(priv, addr, false); + link_cmd = iwl_sta_init_lq(priv, addr, false); + if (!link_cmd) { + IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n", + addr); + return -ENOMEM; + } + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].lq = link_cmd; + spin_unlock_irqrestore(&priv->sta_lock, flags); + } + return 0; } EXPORT_SYMBOL(iwl_add_local_station); @@ -509,7 +530,8 @@ EXPORT_SYMBOL(iwl_add_local_station); static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) { /* Ucode must be active and driver must be non active */ - if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE) + if ((priv->stations[sta_id].used & + (IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) != IWL_STA_UCODE_ACTIVE) IWL_ERR(priv, "removed non active STA %u\n", sta_id); priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE; @@ -676,8 +698,23 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force) spin_lock_irqsave(&priv->sta_lock, flags_spin); if (force) { IWL_DEBUG_INFO(priv, "Clearing all station information in driver\n"); + /* + * The station entry contains a link to the LQ command. For + * all stations managed by mac80211 this memory will be + * managed by it also. For local stations (broadcast and + * bssid station when in adhoc mode) we need to maintain + * this lq command separately. This memory is created when + * these stations are added. + */ + for (i = 0; i < priv->hw_params.max_stations; i++) { + if (priv->stations[i].used & IWL_STA_LOCAL) { + kfree(priv->stations[i].lq); + priv->stations[i].lq = NULL; + } + } priv->num_stations = 0; memset(priv->stations, 0, sizeof(priv->stations)); + cleared = true; } else { for (i = 0; i < priv->hw_params.max_stations; i++) { if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { @@ -1207,7 +1244,8 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, BUG_ON(init && (cmd.flags & CMD_ASYNC)); ret = iwl_send_cmd(priv, &cmd); - if (ret || (cmd.flags & CMD_ASYNC)) + + if (cmd.flags & CMD_ASYNC) return ret; if (init) { @@ -1217,33 +1255,36 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; spin_unlock_irqrestore(&priv->sta_lock, flags_spin); } - return 0; + return ret; } EXPORT_SYMBOL(iwl_send_lq_cmd); /** * iwl_add_bcast_station - add broadcast station into station table. */ -void iwl_add_bcast_station(struct iwl_priv *priv) +int iwl_add_bcast_station(struct iwl_priv *priv) { IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); - iwl_add_local_station(priv, iwl_bcast_addr, true); + return iwl_add_local_station(priv, iwl_bcast_addr, true); } EXPORT_SYMBOL(iwl_add_bcast_station); /** * iwl3945_add_bcast_station - add broadcast station into station table. */ -void iwl3945_add_bcast_station(struct iwl_priv *priv) +int iwl3945_add_bcast_station(struct iwl_priv *priv) { + int ret; + IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); - iwl_add_local_station(priv, iwl_bcast_addr, false); + ret = iwl_add_local_station(priv, iwl_bcast_addr, false); /* * It is assumed that when station is added more initialization * needs to be done, but for 3945 it is not the case and we can * just release station table access right here. */ priv->stations[priv->hw_params.bcast_sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; + return ret; } EXPORT_SYMBOL(iwl3945_add_bcast_station); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 42cd2f4a01cd..b0ed2eb931fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -36,6 +36,9 @@ #define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */ #define IWL_STA_UCODE_INPROGRESS BIT(2) /* ucode entry is in process of being activated */ +#define IWL_STA_LOCAL BIT(3) /* station state not directed by mac80211 + this is for bcast and bssid (when adhoc) + stations */ /** @@ -57,8 +60,8 @@ void iwl_update_tkip_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, const u8 *addr, u32 iv32, u16 *phase1key); -void iwl_add_bcast_station(struct iwl_priv *priv); -void iwl3945_add_bcast_station(struct iwl_priv *priv); +int iwl_add_bcast_station(struct iwl_priv *priv); +int iwl3945_add_bcast_station(struct iwl_priv *priv); void iwl_restore_stations(struct iwl_priv *priv); void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force); int iwl_get_free_ucode_key_index(struct iwl_priv *priv); -- cgit v1.2.3 From 6e0b9cac681bf9b633397d2d5270e5ab31ca04db Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 28 Apr 2010 08:44:50 -0700 Subject: iwl3945: use iwl3945_add_bcast_station iwl3945 should not use iwl_add_local_station(..., false) because that would leave the IWL_STA_UCODE_INPROGRESS flag set for the station, which is not desirable. Instead it can use iwl3945_add_bcast_station() here. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 04cedef0b006..4f20cca06fb0 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3293,7 +3293,7 @@ void iwl3945_config_ap(struct iwl_priv *priv) /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv); - iwl_add_local_station(priv, iwl_bcast_addr, false); + iwl3945_add_bcast_station(priv); } iwl3945_send_beacon_cmd(priv); -- cgit v1.2.3 From c0222df86e55576ef879795b5a158c46e6653f07 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 28 Apr 2010 08:44:51 -0700 Subject: iwlwifi: pass address to iwl_remove_station We'll need that function for IBSS station management, so pass it the address, which is the only thing it uses from the station struct. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-sta.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 5c6b3262baf9..354eb13a8515 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -596,7 +596,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, /** * iwl_remove_station - Remove driver's knowledge of station. */ -static int iwl_remove_station(struct iwl_priv *priv, struct ieee80211_sta *sta) +static int iwl_remove_station(struct iwl_priv *priv, const u8 *addr) { int sta_id = IWL_INVALID_STATION; int i, ret = -EINVAL; @@ -607,7 +607,7 @@ static int iwl_remove_station(struct iwl_priv *priv, struct ieee80211_sta *sta) if (!iwl_is_ready(priv)) { IWL_DEBUG_INFO(priv, "Unable to remove station %pM, device not ready.\n", - sta->addr); + addr); /* * It is typical for stations to be removed when we are * going down. Return success since device will be down @@ -624,7 +624,7 @@ static int iwl_remove_station(struct iwl_priv *priv, struct ieee80211_sta *sta) for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) if (priv->stations[i].used && !compare_ether_addr(priv->stations[i].sta.sta.addr, - sta->addr)) { + addr)) { sta_id = i; break; } @@ -633,17 +633,17 @@ static int iwl_remove_station(struct iwl_priv *priv, struct ieee80211_sta *sta) goto out; IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", - sta_id, sta->addr); + sta_id, addr); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", - sta->addr); + addr); goto out; } if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n", - sta->addr); + addr); goto out; } @@ -1450,7 +1450,7 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct iwl_priv *priv = hw->priv; IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", sta->addr); - ret = iwl_remove_station(priv, sta); + ret = iwl_remove_station(priv, sta->addr); if (ret) IWL_ERR(priv, "Error removing station %pM\n", sta->addr); -- cgit v1.2.3 From 1fa61b2e793dad51271c7ce39377daade51261d7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 28 Apr 2010 08:44:52 -0700 Subject: iwlwifi: manage IBSS station properly Currently iwlwifi will eventually exhaust the station table when adding the BSSID station for IBSS mode, unless the interface is set down. The new mac80211 ibss joined/left notification allows us to fix that easily by moving the code to add the IBSS station to the notification, and also adding code to remove it again when we leave the IBSS. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 + drivers/net/wireless/iwlwifi/iwl-3945.c | 30 ++++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-3945.h | 9 --------- drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-6000.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 9 +++++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ------ drivers/net/wireless/iwlwifi/iwl-agn.h | 4 ++++ drivers/net/wireless/iwlwifi/iwl-core.c | 9 +++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-sta.c | 7 ++++++- drivers/net/wireless/iwlwifi/iwl-sta.h | 1 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 11 ----------- 14 files changed, 66 insertions(+), 28 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 4d360d74b0cd..ebaf02d47e73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -213,6 +213,7 @@ static struct iwl_lib_ops iwl1000_lib = { .set_ct_kill = iwl1000_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .manage_ibss_station = iwlagn_manage_ibss_station, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 360781326cb7..1e9593968c36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -884,7 +884,8 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); } -u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) +static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, + u16 tx_rate, u8 flags) { unsigned long flags_spin; struct iwl_station_entry *station; @@ -2395,6 +2396,32 @@ static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) return (u16)sizeof(struct iwl3945_addsta_cmd); } +static int iwl3945_manage_ibss_station(struct iwl_priv *priv, + struct ieee80211_vif *vif, bool add) +{ + int ret; + + /* + * NB: this assumes that the station it gets will be + * IWL_STA_ID, which will happen but isn't obvious. + */ + + if (add) { + ret = iwl_add_local_station(priv, vif->bss_conf.bssid, false); + if (ret) + return ret; + + iwl3945_sync_sta(priv, IWL_STA_ID, + (priv->band == IEEE80211_BAND_5GHZ) ? + IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, + CMD_ASYNC); + iwl3945_rate_scale_init(priv->hw, IWL_STA_ID); + + return 0; + } + + return iwl_remove_station(priv, vif->bss_conf.bssid); +} /** * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table @@ -2802,6 +2829,7 @@ static struct iwl_lib_ops iwl3945_lib = { .post_associate = iwl3945_post_associate, .isr = iwl_isr_legacy, .config_ap = iwl3945_config_ap, + .manage_ibss_station = iwl3945_manage_ibss_station, .add_bcast_station = iwl3945_add_bcast_station, .debugfs_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 643adb644bb8..cea824c15bc5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -211,13 +211,6 @@ extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, char **buf, bool display); extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); -/* - * Currently used by iwl-3945-rs... look at restructuring so that it doesn't - * call this... todo... fix that. -*/ -extern u8 iwl3945_sync_station(struct iwl_priv *priv, int sta_id, - u16 tx_rate, u8 flags); - /****************************************************************************** * * Functions implemented in iwl-[34]*.c which are forward declared here @@ -288,8 +281,6 @@ extern __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv); extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv); extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv); extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv); -extern u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, - u16 tx_rate, u8 flags); extern const struct iwl_channel_info *iwl3945_get_channel_info( const struct iwl_priv *priv, enum ieee80211_band band, u16 channel); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 6b0ae74546dd..5904a1beac4d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2219,6 +2219,7 @@ static struct iwl_lib_ops iwl4965_lib = { .set_ct_kill = iwl4965_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .manage_ibss_station = iwlagn_manage_ibss_station, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 8ed616e59631..bde0f18cbae9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -352,6 +352,7 @@ static struct iwl_lib_ops iwl5000_lib = { .set_ct_kill = iwl5000_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .manage_ibss_station = iwlagn_manage_ibss_station, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -414,6 +415,7 @@ static struct iwl_lib_ops iwl5150_lib = { .set_ct_kill = iwl5150_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .manage_ibss_station = iwlagn_manage_ibss_station, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index b69fa36fb87a..5f0f58693104 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -318,6 +318,7 @@ static struct iwl_lib_ops iwl6000_lib = { .set_ct_kill = iwl6000_set_ct_threshold, }, .add_bcast_station = iwl_add_bcast_station, + .manage_ibss_station = iwlagn_manage_ibss_station, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -391,6 +392,7 @@ static struct iwl_lib_ops iwl6050_lib = { .set_calib_version = iwl6050_set_calib_version, }, .add_bcast_station = iwl_add_bcast_station, + .manage_ibss_station = iwlagn_manage_ibss_station, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index a27347425968..50ff313c549c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -38,6 +38,7 @@ #include "iwl-helpers.h" #include "iwl-agn-hw.h" #include "iwl-agn.h" +#include "iwl-sta.h" static inline u32 iwlagn_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) { @@ -1513,3 +1514,11 @@ void iwlagn_request_scan(struct iwl_priv *priv) /* inform mac80211 scan aborted */ queue_work(priv->workqueue, &priv->scan_completed); } + +int iwlagn_manage_ibss_station(struct iwl_priv *priv, + struct ieee80211_vif *vif, bool add) +{ + if (add) + return iwl_add_local_station(priv, vif->bss_conf.bssid, true); + return iwl_remove_station(priv, vif->bss_conf.bssid); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5cf38227c6c7..dd1324d6f4c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2606,17 +2606,11 @@ void iwl_post_associate(struct iwl_priv *priv) switch (priv->iw_mode) { case NL80211_IFTYPE_STATION: break; - case NL80211_IFTYPE_ADHOC: - /* assume default assoc id */ priv->assoc_id = 1; - - iwl_add_local_station(priv, priv->bssid, true); iwl_send_beacon_cmd(priv); - break; - default: IWL_ERR(priv, "%s Should not be called in %d mode\n", __func__, priv->iw_mode); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index cfee9994383e..a9ba9fc6740a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -174,4 +174,8 @@ static inline bool iwl_is_tx_success(u32 status) /* scan */ void iwlagn_request_scan(struct iwl_priv *priv); +/* station mgmt */ +int iwlagn_manage_ibss_station(struct iwl_priv *priv, + struct ieee80211_vif *vif, bool add); + #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index e8c9bcafe564..5c6f25462a09 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1960,6 +1960,15 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, iwl_set_no_assoc(priv); } + if (changes & BSS_CHANGED_IBSS) { + ret = priv->cfg->ops->lib->manage_ibss_station(priv, vif, + bss_conf->ibss_joined); + if (ret) + IWL_ERR(priv, "failed to %s IBSS station %pM\n", + bss_conf->ibss_joined ? "add" : "remove", + bss_conf->bssid); + } + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 8d53fc973a43..0fa99650f75a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -202,6 +202,8 @@ struct iwl_lib_ops { struct iwl_temp_ops temp_ops; /* station management */ int (*add_bcast_station)(struct iwl_priv *priv); + int (*manage_ibss_station)(struct iwl_priv *priv, + struct ieee80211_vif *vif, bool add); /* recover from tx queue stall */ void (*recover_from_tx_stall)(unsigned long data); /* check for plcp health */ diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 354eb13a8515..7da8edeb5256 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -596,7 +596,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, /** * iwl_remove_station - Remove driver's knowledge of station. */ -static int iwl_remove_station(struct iwl_priv *priv, const u8 *addr) +int iwl_remove_station(struct iwl_priv *priv, const u8 *addr) { int sta_id = IWL_INVALID_STATION; int i, ret = -EINVAL; @@ -647,6 +647,10 @@ static int iwl_remove_station(struct iwl_priv *priv, const u8 *addr) goto out; } + if (priv->stations[sta_id].used & IWL_STA_LOCAL) { + kfree(priv->stations[sta_id].lq); + priv->stations[sta_id].lq = NULL; + } priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; @@ -663,6 +667,7 @@ out: spin_unlock_irqrestore(&priv->sta_lock, flags); return ret; } +EXPORT_SYMBOL_GPL(iwl_remove_station); /** * iwl_clear_ucode_stations() - clear entire station table driver and/or ucode diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index b0ed2eb931fd..9a869f1031fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -74,6 +74,7 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, bool is_ap, struct ieee80211_sta_ht_cap *ht_info, u8 *sta_id_r); +int iwl_remove_station(struct iwl_priv *priv, const u8 *addr); int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4f20cca06fb0..9486b3248245 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3103,21 +3103,10 @@ void iwl3945_post_associate(struct iwl_priv *priv) case NL80211_IFTYPE_STATION: iwl3945_rate_scale_init(priv->hw, IWL_AP_ID); break; - case NL80211_IFTYPE_ADHOC: - priv->assoc_id = 1; - iwl_add_local_station(priv, priv->bssid, false); - iwl3945_sync_sta(priv, IWL_STA_ID, - (priv->band == IEEE80211_BAND_5GHZ) ? - IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, - CMD_ASYNC); - iwl3945_rate_scale_init(priv->hw, IWL_STA_ID); - iwl3945_send_beacon_cmd(priv); - break; - default: IWL_ERR(priv, "%s Should not be called in %d mode\n", __func__, priv->iw_mode); -- cgit v1.2.3 From 3e4de7616fea5c68a9300af0e347a7f014ddcc63 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 28 Apr 2010 12:09:12 -0700 Subject: iwlagn: show and store firmware build number We currently display the build number only if debugging is enabled, but it is really helpful so show it all the time. Also store it so it can be retrieved later via ethtool. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index dd1324d6f4c0..f9c9c08ab88e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1552,6 +1552,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) u32 inst_size, data_size, init_size, init_data_size, boot_size; int err; u16 eeprom_ver; + char buildstr[25]; if (!ucode_raw) { IWL_ERR(priv, "request for firmware file '%s' failed.\n", @@ -1599,22 +1600,26 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) "from http://www.intellinuxwireless.org.\n", api_max, api_ver); - IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n", - IWL_UCODE_MAJOR(priv->ucode_ver), - IWL_UCODE_MINOR(priv->ucode_ver), - IWL_UCODE_API(priv->ucode_ver), - IWL_UCODE_SERIAL(priv->ucode_ver)); + if (build) + sprintf(buildstr, " build %u", build); + else + buildstr[0] = '\0'; + + IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u%s\n", + IWL_UCODE_MAJOR(priv->ucode_ver), + IWL_UCODE_MINOR(priv->ucode_ver), + IWL_UCODE_API(priv->ucode_ver), + IWL_UCODE_SERIAL(priv->ucode_ver), + buildstr); snprintf(priv->hw->wiphy->fw_version, sizeof(priv->hw->wiphy->fw_version), - "%u.%u.%u.%u", + "%u.%u.%u.%u%s", IWL_UCODE_MAJOR(priv->ucode_ver), IWL_UCODE_MINOR(priv->ucode_ver), IWL_UCODE_API(priv->ucode_ver), - IWL_UCODE_SERIAL(priv->ucode_ver)); - - if (build) - IWL_DEBUG_INFO(priv, "Build %u\n", build); + IWL_UCODE_SERIAL(priv->ucode_ver), + buildstr); eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n", -- cgit v1.2.3 From 93b1a2f919a752bb689fdb0c5817c643c2f74435 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 28 Apr 2010 12:09:13 -0700 Subject: iwl3945: remove ucode access indirection As these function pointers will always point to the 3945 functions, we can just call them directly and avoid the indirection. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945.c | 40 ----------------------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 39 +++++++++++++++++++++------- 2 files changed, 30 insertions(+), 49 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 1e9593968c36..a4d842a05836 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2751,51 +2751,12 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) return 0; } -#define IWL3945_UCODE_GET(item) \ -static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode,\ - u32 api_ver) \ -{ \ - return le32_to_cpu(ucode->u.v1.item); \ -} - -static u32 iwl3945_ucode_get_header_size(u32 api_ver) -{ - return UCODE_HEADER_SIZE(1); -} -static u32 iwl3945_ucode_get_build(const struct iwl_ucode_header *ucode, - u32 api_ver) -{ - return 0; -} -static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode, - u32 api_ver) -{ - return (u8 *) ucode->u.v1.data; -} - -IWL3945_UCODE_GET(inst_size); -IWL3945_UCODE_GET(data_size); -IWL3945_UCODE_GET(init_size); -IWL3945_UCODE_GET(init_data_size); -IWL3945_UCODE_GET(boot_size); - static struct iwl_hcmd_ops iwl3945_hcmd = { .rxon_assoc = iwl3945_send_rxon_assoc, .commit_rxon = iwl3945_commit_rxon, .send_bt_config = iwl_send_bt_config, }; -static struct iwl_ucode_ops iwl3945_ucode = { - .get_header_size = iwl3945_ucode_get_header_size, - .get_build = iwl3945_ucode_get_build, - .get_inst_size = iwl3945_ucode_get_inst_size, - .get_data_size = iwl3945_ucode_get_data_size, - .get_init_size = iwl3945_ucode_get_init_size, - .get_init_data_size = iwl3945_ucode_get_init_data_size, - .get_boot_size = iwl3945_ucode_get_boot_size, - .get_data = iwl3945_ucode_get_data, -}; - static struct iwl_lib_ops iwl3945_lib = { .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl3945_hw_txq_free_tfd, @@ -2847,7 +2808,6 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { }; static const struct iwl_ops iwl3945_ops = { - .ucode = &iwl3945_ucode, .lib = &iwl3945_lib, .hcmd = &iwl3945_hcmd, .utils = &iwl3945_hcmd_utils, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 9486b3248245..e9de10964c51 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2109,6 +2109,28 @@ static void iwl3945_nic_start(struct iwl_priv *priv) iwl_write32(priv, CSR_RESET, 0); } +#define IWL3945_UCODE_GET(item) \ +static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode)\ +{ \ + return le32_to_cpu(ucode->u.v1.item); \ +} + +static u32 iwl3945_ucode_get_header_size(u32 api_ver) +{ + return UCODE_HEADER_SIZE(1); +} + +static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode) +{ + return (u8 *) ucode->u.v1.data; +} + +IWL3945_UCODE_GET(inst_size); +IWL3945_UCODE_GET(data_size); +IWL3945_UCODE_GET(init_size); +IWL3945_UCODE_GET(init_data_size); +IWL3945_UCODE_GET(boot_size); + /** * iwl3945_read_ucode - Read uCode images from disk file. * @@ -2157,7 +2179,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) goto error; /* Make sure that we got at least our header! */ - if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { + if (ucode_raw->size < iwl3945_ucode_get_header_size(1)) { IWL_ERR(priv, "File size way too small!\n"); ret = -EINVAL; goto err_release; @@ -2168,13 +2190,12 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) priv->ucode_ver = le32_to_cpu(ucode->ver); api_ver = IWL_UCODE_API(priv->ucode_ver); - inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver); - data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver); - init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver); - init_data_size = - priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver); - boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver); - src = priv->cfg->ops->ucode->get_data(ucode, api_ver); + inst_size = iwl3945_ucode_get_inst_size(ucode); + data_size = iwl3945_ucode_get_data_size(ucode); + init_size = iwl3945_ucode_get_init_size(ucode); + init_data_size = iwl3945_ucode_get_init_data_size(ucode); + boot_size = iwl3945_ucode_get_boot_size(ucode); + src = iwl3945_ucode_get_data(ucode); /* api_ver should match the api version forming part of the * firmware filename ... but we don't check for that and only rely @@ -2223,7 +2244,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) /* Verify size of file vs. image size info in file's header */ - if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) + + if (ucode_raw->size != iwl3945_ucode_get_header_size(api_ver) + inst_size + data_size + init_size + init_data_size + boot_size) { -- cgit v1.2.3 From 22adba2a6995dc24663251ffb954f8856968f26e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 28 Apr 2010 12:09:14 -0700 Subject: iwlwifi: remove ucode virtual functions AGN devices all use the same ucode operations, except for 4965, because 4965 uses only v1 file headers. Therefore, we can remove all the indirection we have here and just code the API distinction in place, with a small special case for 4965. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 - drivers/net/wireless/iwlwifi/iwl-4965.c | 39 ------------------ drivers/net/wireless/iwlwifi/iwl-5000.c | 2 - drivers/net/wireless/iwlwifi/iwl-6000.c | 2 - drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 49 ---------------------- drivers/net/wireless/iwlwifi/iwl-agn.c | 61 +++++++++++++++++++++------- drivers/net/wireless/iwlwifi/iwl-agn.h | 1 - drivers/net/wireless/iwlwifi/iwl-core.h | 12 ------ drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 10 files changed, 47 insertions(+), 123 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index ebaf02d47e73..a2f7cbcc2f7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -225,7 +225,6 @@ static struct iwl_lib_ops iwl1000_lib = { }; static const struct iwl_ops iwl1000_ops = { - .ucode = &iwlagn_ucode, .lib = &iwl1000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 5904a1beac4d..a3562a126c93 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2112,34 +2112,6 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) cancel_work_sync(&priv->txpower_work); } -#define IWL4965_UCODE_GET(item) \ -static u32 iwl4965_ucode_get_##item(const struct iwl_ucode_header *ucode,\ - u32 api_ver) \ -{ \ - return le32_to_cpu(ucode->u.v1.item); \ -} - -static u32 iwl4965_ucode_get_header_size(u32 api_ver) -{ - return UCODE_HEADER_SIZE(1); -} -static u32 iwl4965_ucode_get_build(const struct iwl_ucode_header *ucode, - u32 api_ver) -{ - return 0; -} -static u8 *iwl4965_ucode_get_data(const struct iwl_ucode_header *ucode, - u32 api_ver) -{ - return (u8 *) ucode->u.v1.data; -} - -IWL4965_UCODE_GET(inst_size); -IWL4965_UCODE_GET(data_size); -IWL4965_UCODE_GET(init_size); -IWL4965_UCODE_GET(init_data_size); -IWL4965_UCODE_GET(boot_size); - static struct iwl_hcmd_ops iwl4965_hcmd = { .rxon_assoc = iwl4965_send_rxon_assoc, .commit_rxon = iwl_commit_rxon, @@ -2147,16 +2119,6 @@ static struct iwl_hcmd_ops iwl4965_hcmd = { .send_bt_config = iwl_send_bt_config, }; -static struct iwl_ucode_ops iwl4965_ucode = { - .get_header_size = iwl4965_ucode_get_header_size, - .get_build = iwl4965_ucode_get_build, - .get_inst_size = iwl4965_ucode_get_inst_size, - .get_data_size = iwl4965_ucode_get_data_size, - .get_init_size = iwl4965_ucode_get_init_size, - .get_init_data_size = iwl4965_ucode_get_init_data_size, - .get_boot_size = iwl4965_ucode_get_boot_size, - .get_data = iwl4965_ucode_get_data, -}; static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { .get_hcmd_size = iwl4965_get_hcmd_size, .build_addsta_hcmd = iwl4965_build_addsta_hcmd, @@ -2229,7 +2191,6 @@ static struct iwl_lib_ops iwl4965_lib = { }; static const struct iwl_ops iwl4965_ops = { - .ucode = &iwl4965_ucode, .lib = &iwl4965_lib, .hcmd = &iwl4965_hcmd, .utils = &iwl4965_hcmd_utils, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index bde0f18cbae9..efda0e8ccacb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -427,7 +427,6 @@ static struct iwl_lib_ops iwl5150_lib = { }; static const struct iwl_ops iwl5000_ops = { - .ucode = &iwlagn_ucode, .lib = &iwl5000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, @@ -435,7 +434,6 @@ static const struct iwl_ops iwl5000_ops = { }; static const struct iwl_ops iwl5150_ops = { - .ucode = &iwlagn_ucode, .lib = &iwl5150_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 5f0f58693104..03c73244703c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -330,7 +330,6 @@ static struct iwl_lib_ops iwl6000_lib = { }; static const struct iwl_ops iwl6000_ops = { - .ucode = &iwlagn_ucode, .lib = &iwl6000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, @@ -404,7 +403,6 @@ static struct iwl_lib_ops iwl6050_lib = { }; static const struct iwl_ops iwl6050_ops = { - .ucode = &iwlagn_ucode, .lib = &iwl6050_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index c3e3283426a9..637286c396fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -182,55 +182,6 @@ int iwlagn_load_ucode(struct iwl_priv *priv) return ret; } -#define IWL_UCODE_GET(item) \ -static u32 iwlagn_ucode_get_##item(const struct iwl_ucode_header *ucode,\ - u32 api_ver) \ -{ \ - if (api_ver <= 2) \ - return le32_to_cpu(ucode->u.v1.item); \ - return le32_to_cpu(ucode->u.v2.item); \ -} - -static u32 iwlagn_ucode_get_header_size(u32 api_ver) -{ - if (api_ver <= 2) - return UCODE_HEADER_SIZE(1); - return UCODE_HEADER_SIZE(2); -} - -static u32 iwlagn_ucode_get_build(const struct iwl_ucode_header *ucode, - u32 api_ver) -{ - if (api_ver <= 2) - return 0; - return le32_to_cpu(ucode->u.v2.build); -} - -static u8 *iwlagn_ucode_get_data(const struct iwl_ucode_header *ucode, - u32 api_ver) -{ - if (api_ver <= 2) - return (u8 *) ucode->u.v1.data; - return (u8 *) ucode->u.v2.data; -} - -IWL_UCODE_GET(inst_size); -IWL_UCODE_GET(data_size); -IWL_UCODE_GET(init_size); -IWL_UCODE_GET(init_data_size); -IWL_UCODE_GET(boot_size); - -struct iwl_ucode_ops iwlagn_ucode = { - .get_header_size = iwlagn_ucode_get_header_size, - .get_build = iwlagn_ucode_get_build, - .get_inst_size = iwlagn_ucode_get_inst_size, - .get_data_size = iwlagn_ucode_get_data_size, - .get_init_size = iwlagn_ucode_get_init_size, - .get_init_data_size = iwlagn_ucode_get_init_data_size, - .get_boot_size = iwlagn_ucode_get_boot_size, - .get_data = iwlagn_ucode_get_data, -}; - /* * Calibration */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f9c9c08ab88e..7bcc8a3aee4a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1550,7 +1550,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) size_t len; u32 api_ver, build; u32 inst_size, data_size, init_size, init_data_size, boot_size; - int err; + int err, hdr_size; u16 eeprom_ver; char buildstr[25]; @@ -1563,8 +1563,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n", priv->firmware_name, ucode_raw->size); - /* Make sure that we got at least the v1 header! */ - if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { + /* Make sure that we got at least the API version number */ + if (ucode_raw->size < 4) { IWL_ERR(priv, "File size way too small!\n"); goto try_again; } @@ -1574,14 +1574,47 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) priv->ucode_ver = le32_to_cpu(ucode->ver); api_ver = IWL_UCODE_API(priv->ucode_ver); - build = priv->cfg->ops->ucode->get_build(ucode, api_ver); - inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver); - data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver); - init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver); - init_data_size = - priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver); - boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver); - src = priv->cfg->ops->ucode->get_data(ucode, api_ver); + + switch (api_ver) { + default: + /* + * 4965 doesn't revision the firmware file format + * along with the API version, it always uses v1 + * file format. + */ + if (priv->cfg != &iwl4965_agn_cfg) { + hdr_size = 28; + if (ucode_raw->size < hdr_size) { + IWL_ERR(priv, "File size too small!\n"); + goto try_again; + } + build = ucode->u.v2.build; + inst_size = ucode->u.v2.inst_size; + data_size = ucode->u.v2.data_size; + init_size = ucode->u.v2.init_size; + init_data_size = ucode->u.v2.init_data_size; + boot_size = ucode->u.v2.boot_size; + src = ucode->u.v2.data; + break; + } + /* fall through for 4965 */ + case 0: + case 1: + case 2: + hdr_size = 24; + if (ucode_raw->size < hdr_size) { + IWL_ERR(priv, "File size too small!\n"); + goto try_again; + } + build = 0; + inst_size = ucode->u.v1.inst_size; + data_size = ucode->u.v1.data_size; + init_size = ucode->u.v1.init_size; + init_data_size = ucode->u.v1.init_data_size; + boot_size = ucode->u.v1.boot_size; + src = ucode->u.v1.data; + break; + } /* api_ver should match the api version forming part of the * firmware filename ... but we don't check for that and only rely @@ -1646,10 +1679,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) */ /* Verify size of file vs. image size info in file's header */ - if (ucode_raw->size != - priv->cfg->ops->ucode->get_header_size(api_ver) + - inst_size + data_size + init_size + - init_data_size + boot_size) { + if (ucode_raw->size != hdr_size + inst_size + data_size + init_size + + init_data_size + boot_size) { IWL_DEBUG_INFO(priv, "uCode file size %d does not match expected size\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index a9ba9fc6740a..4a1e7b2b7a8e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -66,7 +66,6 @@ #include "iwl-dev.h" extern struct iwl_mod_params iwlagn_mod_params; -extern struct iwl_ucode_ops iwlagn_ucode; extern struct iwl_hcmd_ops iwlagn_hcmd; extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 0fa99650f75a..2f664a3f0484 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -131,17 +131,6 @@ struct iwl_temp_ops { void (*set_calib_version)(struct iwl_priv *priv); }; -struct iwl_ucode_ops { - u32 (*get_header_size)(u32); - u32 (*get_build)(const struct iwl_ucode_header *, u32); - u32 (*get_inst_size)(const struct iwl_ucode_header *, u32); - u32 (*get_data_size)(const struct iwl_ucode_header *, u32); - u32 (*get_init_size)(const struct iwl_ucode_header *, u32); - u32 (*get_init_data_size)(const struct iwl_ucode_header *, u32); - u32 (*get_boot_size)(const struct iwl_ucode_header *, u32); - u8 * (*get_data)(const struct iwl_ucode_header *, u32); -}; - struct iwl_lib_ops { /* set hw dependent parameters */ int (*set_hw_params)(struct iwl_priv *priv); @@ -222,7 +211,6 @@ struct iwl_led_ops { }; struct iwl_ops { - const struct iwl_ucode_ops *ucode; const struct iwl_lib_ops *lib; const struct iwl_hcmd_ops *hcmd; const struct iwl_hcmd_utils_ops *utils; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index e485465e4d56..fe938d9e43cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -541,7 +541,6 @@ struct iwl_ucode_header { } v2; } u; }; -#define UCODE_HEADER_SIZE(ver) ((ver) == 1 ? 24 : 28) struct iwl4965_ibss_seq { u8 mac[ETH_ALEN]; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index e9de10964c51..59c85f55e625 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2117,7 +2117,7 @@ static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode)\ static u32 iwl3945_ucode_get_header_size(u32 api_ver) { - return UCODE_HEADER_SIZE(1); + return 24; } static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode) -- cgit v1.2.3 From d1358f62d47c9e872994e5c6e9c9d6e1f31d24c4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 28 Apr 2010 12:09:15 -0700 Subject: iwlwifi: move eeprom version printout to eeprom init It doesn't belong into firmware loading, it should instead be printed after loading the EEPROM. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ------ drivers/net/wireless/iwlwifi/iwl-eeprom.c | 7 +++++++ 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7bcc8a3aee4a..70094bbe485b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1551,7 +1551,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) u32 api_ver, build; u32 inst_size, data_size, init_size, init_data_size, boot_size; int err, hdr_size; - u16 eeprom_ver; char buildstr[25]; if (!ucode_raw) { @@ -1654,11 +1653,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) IWL_UCODE_SERIAL(priv->ucode_ver), buildstr); - eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); - IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n", - (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) - ? "OTP" : "EEPROM", eeprom_ver); - IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", priv->ucode_ver); IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index fd37152abae3..a8dd2fd78b59 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -589,9 +589,16 @@ int iwl_eeprom_init(struct iwl_priv *priv) e[addr / 2] = cpu_to_le16(r >> 16); } } + + IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n", + (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) + ? "OTP" : "EEPROM", + iwl_eeprom_query16(priv, EEPROM_VERSION)); + ret = 0; done: priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); + err: if (ret) iwl_eeprom_free(priv); -- cgit v1.2.3 From 0e9a44dc0bb718c28b20a48f551818036ef090ab Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 28 Apr 2010 12:09:16 -0700 Subject: iwlagn: prepare for new firmware file format Currently the first four bytes in a firmware file indicate the major, minor and api versions as well as the serial number. These combined can never be zero, so we can use that special case for a new, future, file format. This patch simply shuffles the code and prepares for that new format. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 291 +++++++++++++++++++-------------- 1 file changed, 168 insertions(+), 123 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 70094bbe485b..65ae636eae3e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1534,6 +1534,91 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) iwl_ucode_callback); } +struct iwlagn_firmware_pieces { + const void *inst, *data, *init, *init_data, *boot; + size_t inst_size, data_size, init_size, init_data_size, boot_size; + + u32 build; +}; + +static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, + const struct firmware *ucode_raw, + struct iwlagn_firmware_pieces *pieces) +{ + struct iwl_ucode_header *ucode = (void *)ucode_raw->data; + u32 api_ver, hdr_size; + const u8 *src; + + priv->ucode_ver = le32_to_cpu(ucode->ver); + api_ver = IWL_UCODE_API(priv->ucode_ver); + + switch (api_ver) { + default: + /* + * 4965 doesn't revision the firmware file format + * along with the API version, it always uses v1 + * file format. + */ + if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != + CSR_HW_REV_TYPE_4965) { + hdr_size = 28; + if (ucode_raw->size < hdr_size) { + IWL_ERR(priv, "File size too small!\n"); + return -EINVAL; + } + pieces->build = le32_to_cpu(ucode->u.v2.build); + pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); + pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); + pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); + pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); + pieces->boot_size = le32_to_cpu(ucode->u.v2.boot_size); + src = ucode->u.v2.data; + break; + } + /* fall through for 4965 */ + case 0: + case 1: + case 2: + hdr_size = 24; + if (ucode_raw->size < hdr_size) { + IWL_ERR(priv, "File size too small!\n"); + return -EINVAL; + } + pieces->build = 0; + pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size); + pieces->data_size = le32_to_cpu(ucode->u.v1.data_size); + pieces->init_size = le32_to_cpu(ucode->u.v1.init_size); + pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size); + pieces->boot_size = le32_to_cpu(ucode->u.v1.boot_size); + src = ucode->u.v1.data; + break; + } + + /* Verify size of file vs. image size info in file's header */ + if (ucode_raw->size != hdr_size + pieces->inst_size + + pieces->data_size + pieces->init_size + + pieces->init_data_size + pieces->boot_size) { + + IWL_ERR(priv, + "uCode file size %d does not match expected size\n", + (int)ucode_raw->size); + return -EINVAL; + } + + pieces->inst = src; + src += pieces->inst_size; + pieces->data = src; + src += pieces->data_size; + pieces->init = src; + src += pieces->init_size; + pieces->init_data = src; + src += pieces->init_data_size; + pieces->boot = src; + src += pieces->boot_size; + + return 0; +} + /** * iwl_ucode_callback - callback when firmware was loaded * @@ -1544,14 +1629,15 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) { struct iwl_priv *priv = context; struct iwl_ucode_header *ucode; + int err; + struct iwlagn_firmware_pieces pieces; const unsigned int api_max = priv->cfg->ucode_api_max; const unsigned int api_min = priv->cfg->ucode_api_min; - u8 *src; - size_t len; - u32 api_ver, build; - u32 inst_size, data_size, init_size, init_data_size, boot_size; - int err, hdr_size; + u32 api_ver; char buildstr[25]; + u32 build; + + memset(&pieces, 0, sizeof(pieces)); if (!ucode_raw) { IWL_ERR(priv, "request for firmware file '%s' failed.\n", @@ -1571,54 +1657,22 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) /* Data from ucode file: header followed by uCode images */ ucode = (struct iwl_ucode_header *)ucode_raw->data; - priv->ucode_ver = le32_to_cpu(ucode->ver); - api_ver = IWL_UCODE_API(priv->ucode_ver); + if (ucode->ver) + err = iwlagn_load_legacy_firmware(priv, ucode_raw, &pieces); + else + err = -EINVAL; - switch (api_ver) { - default: - /* - * 4965 doesn't revision the firmware file format - * along with the API version, it always uses v1 - * file format. - */ - if (priv->cfg != &iwl4965_agn_cfg) { - hdr_size = 28; - if (ucode_raw->size < hdr_size) { - IWL_ERR(priv, "File size too small!\n"); - goto try_again; - } - build = ucode->u.v2.build; - inst_size = ucode->u.v2.inst_size; - data_size = ucode->u.v2.data_size; - init_size = ucode->u.v2.init_size; - init_data_size = ucode->u.v2.init_data_size; - boot_size = ucode->u.v2.boot_size; - src = ucode->u.v2.data; - break; - } - /* fall through for 4965 */ - case 0: - case 1: - case 2: - hdr_size = 24; - if (ucode_raw->size < hdr_size) { - IWL_ERR(priv, "File size too small!\n"); - goto try_again; - } - build = 0; - inst_size = ucode->u.v1.inst_size; - data_size = ucode->u.v1.data_size; - init_size = ucode->u.v1.init_size; - init_data_size = ucode->u.v1.init_data_size; - boot_size = ucode->u.v1.boot_size; - src = ucode->u.v1.data; - break; - } + if (err) + goto try_again; - /* api_ver should match the api version forming part of the - * firmware filename ... but we don't check for that and only rely - * on the API version read from firmware header from here on forward */ + api_ver = IWL_UCODE_API(priv->ucode_ver); + build = pieces.build; + /* + * api_ver should match the api version forming part of the + * firmware filename ... but we don't check for that and only rely + * on the API version read from firmware header from here on forward + */ if (api_ver < api_min || api_ver > api_max) { IWL_ERR(priv, "Driver unable to support your firmware API. " "Driver supports v%u, firmware is v%u.\n", @@ -1653,75 +1707,69 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) IWL_UCODE_SERIAL(priv->ucode_ver), buildstr); - IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", - priv->ucode_ver); - IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", - inst_size); - IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n", - data_size); - IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n", - init_size); - IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n", - init_data_size); - IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", - boot_size); - /* * For any of the failures below (before allocating pci memory) * we will try to load a version with a smaller API -- maybe the * user just got a corrupted version of the latest API. */ - /* Verify size of file vs. image size info in file's header */ - if (ucode_raw->size != hdr_size + inst_size + data_size + init_size + - init_data_size + boot_size) { - - IWL_DEBUG_INFO(priv, - "uCode file size %d does not match expected size\n", - (int)ucode_raw->size); - goto try_again; - } + IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", + priv->ucode_ver); + IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %Zd\n", + pieces.inst_size); + IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %Zd\n", + pieces.data_size); + IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %Zd\n", + pieces.init_size); + IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n", + pieces.init_data_size); + IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %Zd\n", + pieces.boot_size); /* Verify that uCode images will fit in card's SRAM */ - if (inst_size > priv->hw_params.max_inst_size) { - IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", - inst_size); + if (pieces.inst_size > priv->hw_params.max_inst_size) { + IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n", + pieces.inst_size); goto try_again; } - if (data_size > priv->hw_params.max_data_size) { - IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", - data_size); + if (pieces.data_size > priv->hw_params.max_data_size) { + IWL_ERR(priv, "uCode data len %Zd too large to fit in\n", + pieces.data_size); goto try_again; } - if (init_size > priv->hw_params.max_inst_size) { - IWL_INFO(priv, "uCode init instr len %d too large to fit in\n", - init_size); + + if (pieces.init_size > priv->hw_params.max_inst_size) { + IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n", + pieces.init_size); goto try_again; } - if (init_data_size > priv->hw_params.max_data_size) { - IWL_INFO(priv, "uCode init data len %d too large to fit in\n", - init_data_size); + + if (pieces.init_data_size > priv->hw_params.max_data_size) { + IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n", + pieces.init_data_size); goto try_again; } - if (boot_size > priv->hw_params.max_bsm_size) { - IWL_INFO(priv, "uCode boot instr len %d too large to fit in\n", - boot_size); + + if (pieces.boot_size > priv->hw_params.max_bsm_size) { + IWL_ERR(priv, "uCode boot instr len %Zd too large to fit in\n", + pieces.boot_size); goto try_again; } + /* Allocate ucode buffers for card's bus-master loading ... */ /* Runtime instructions and 2 copies of data: * 1) unmodified from disk * 2) backup cache for save/restore during power-downs */ - priv->ucode_code.len = inst_size; + priv->ucode_code.len = pieces.inst_size; iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); - priv->ucode_data.len = data_size; + priv->ucode_data.len = pieces.data_size; iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); - priv->ucode_data_backup.len = data_size; + priv->ucode_data_backup.len = pieces.data_size; iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup); if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || @@ -1729,11 +1777,11 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) goto err_pci_alloc; /* Initialization instructions and data */ - if (init_size && init_data_size) { - priv->ucode_init.len = init_size; + if (pieces.init_size && pieces.init_data_size) { + priv->ucode_init.len = pieces.init_size; iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); - priv->ucode_init_data.len = init_data_size; + priv->ucode_init_data.len = pieces.init_data_size; iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) @@ -1741,8 +1789,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) } /* Bootstrap (instructions only, no data) */ - if (boot_size) { - priv->ucode_boot.len = boot_size; + if (pieces.boot_size) { + priv->ucode_boot.len = pieces.boot_size; iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot); if (!priv->ucode_boot.v_addr) @@ -1752,44 +1800,41 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) /* Copy images into buffers for card's bus-master reads ... */ /* Runtime instructions (first block of data in file) */ - len = inst_size; - IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len); - memcpy(priv->ucode_code.v_addr, src, len); - src += len; + IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", + pieces.inst_size); + memcpy(priv->ucode_code.v_addr, pieces.inst, pieces.inst_size); IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); - /* Runtime data (2nd block) - * NOTE: Copy into backup buffer will be done in iwl_up() */ - len = data_size; - IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len); - memcpy(priv->ucode_data.v_addr, src, len); - memcpy(priv->ucode_data_backup.v_addr, src, len); - src += len; - - /* Initialization instructions (3rd block) */ - if (init_size) { - len = init_size; + /* + * Runtime data + * NOTE: Copy into backup buffer will be done in iwl_up() + */ + IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", + pieces.data_size); + memcpy(priv->ucode_data.v_addr, pieces.data, pieces.data_size); + memcpy(priv->ucode_data_backup.v_addr, pieces.data, pieces.data_size); + + /* Initialization instructions */ + if (pieces.init_size) { IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", - len); - memcpy(priv->ucode_init.v_addr, src, len); - src += len; + pieces.init_size); + memcpy(priv->ucode_init.v_addr, pieces.init, pieces.init_size); } - /* Initialization data (4th block) */ - if (init_data_size) { - len = init_data_size; + /* Initialization data */ + if (pieces.init_data_size) { IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", - len); - memcpy(priv->ucode_init_data.v_addr, src, len); - src += len; + pieces.init_data_size); + memcpy(priv->ucode_init_data.v_addr, pieces.init_data, + pieces.init_data_size); } - /* Bootstrap instructions (5th block) */ - len = boot_size; - IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); - memcpy(priv->ucode_boot.v_addr, src, len); + /* Bootstrap instructions */ + IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", + pieces.boot_size); + memcpy(priv->ucode_boot.v_addr, pieces.boot, pieces.boot_size); /************************************************** * This is still part of probe() in a sense... -- cgit v1.2.3 From dd7a2509b3a79b290730a9c6a784bf03fedabb9a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 28 Apr 2010 23:33:10 -0700 Subject: iwlagn: implement loading a new firmware file type The old firmware file type does not allow indicating any firmware capabilities, which we frequently want to make things easier. This implements a new firmware type that is based on a TLV structure, and adds a TLV for the maximum length of probe requests in scans. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 133 ++++++++++++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-commands.h | 1 - drivers/net/wireless/iwlwifi/iwl-dev.h | 58 +++++++++++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 +- 4 files changed, 187 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 65ae636eae3e..97184e14a775 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1505,9 +1505,13 @@ static void iwl_nic_start(struct iwl_priv *priv) iwl_write32(priv, CSR_RESET, 0); } +struct iwlagn_ucode_capabilities { + u32 max_probe_length; +}; static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); -static int iwl_mac_setup_register(struct iwl_priv *priv); +static int iwl_mac_setup_register(struct iwl_priv *priv, + struct iwlagn_ucode_capabilities *capa); static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) { @@ -1619,6 +1623,114 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, return 0; } +static int iwlagn_wanted_ucode_alternative = 1; + +static int iwlagn_load_firmware(struct iwl_priv *priv, + const struct firmware *ucode_raw, + struct iwlagn_firmware_pieces *pieces, + struct iwlagn_ucode_capabilities *capa) +{ + struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data; + struct iwl_ucode_tlv *tlv; + size_t len = ucode_raw->size; + const u8 *data; + int wanted_alternative = iwlagn_wanted_ucode_alternative, tmp; + u64 alternatives; + + if (len < sizeof(*ucode)) + return -EINVAL; + + if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) + return -EINVAL; + + /* + * Check which alternatives are present, and "downgrade" + * when the chosen alternative is not present, warning + * the user when that happens. Some files may not have + * any alternatives, so don't warn in that case. + */ + alternatives = le64_to_cpu(ucode->alternatives); + tmp = wanted_alternative; + if (wanted_alternative > 63) + wanted_alternative = 63; + while (wanted_alternative && !(alternatives & BIT(wanted_alternative))) + wanted_alternative--; + if (wanted_alternative && wanted_alternative != tmp) + IWL_WARN(priv, + "uCode alternative %d not available, choosing %d\n", + tmp, wanted_alternative); + + priv->ucode_ver = le32_to_cpu(ucode->ver); + pieces->build = le32_to_cpu(ucode->build); + data = ucode->data; + + len -= sizeof(*ucode); + + while (len >= sizeof(*tlv)) { + u32 tlv_len; + enum iwl_ucode_tlv_type tlv_type; + u16 tlv_alt; + const u8 *tlv_data; + + len -= sizeof(*tlv); + tlv = (void *)data; + + tlv_len = le32_to_cpu(tlv->length); + tlv_type = le16_to_cpu(tlv->type); + tlv_alt = le16_to_cpu(tlv->alternative); + tlv_data = tlv->data; + + if (len < tlv_len) + return -EINVAL; + len -= ALIGN(tlv_len, 4); + data += sizeof(*tlv) + ALIGN(tlv_len, 4); + + /* + * Alternative 0 is always valid. + * + * Skip alternative TLVs that are not selected. + */ + if (tlv_alt != 0 && tlv_alt != wanted_alternative) + continue; + + switch (tlv_type) { + case IWL_UCODE_TLV_INST: + pieces->inst = tlv_data; + pieces->inst_size = tlv_len; + break; + case IWL_UCODE_TLV_DATA: + pieces->data = tlv_data; + pieces->data_size = tlv_len; + break; + case IWL_UCODE_TLV_INIT: + pieces->init = tlv_data; + pieces->init_size = tlv_len; + break; + case IWL_UCODE_TLV_INIT_DATA: + pieces->init_data = tlv_data; + pieces->init_data_size = tlv_len; + break; + case IWL_UCODE_TLV_BOOT: + pieces->boot = tlv_data; + pieces->boot_size = tlv_len; + break; + case IWL_UCODE_TLV_PROBE_MAX_LEN: + if (tlv_len != 4) + return -EINVAL; + capa->max_probe_length = + le32_to_cpup((__le32 *)tlv_data); + break; + default: + break; + } + } + + if (len) + return -EINVAL; + + return 0; +} + /** * iwl_ucode_callback - callback when firmware was loaded * @@ -1636,6 +1748,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) u32 api_ver; char buildstr[25]; u32 build; + struct iwlagn_ucode_capabilities ucode_capa = { + .max_probe_length = 200, + }; memset(&pieces, 0, sizeof(pieces)); @@ -1660,7 +1775,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) if (ucode->ver) err = iwlagn_load_legacy_firmware(priv, ucode_raw, &pieces); else - err = -EINVAL; + err = iwlagn_load_firmware(priv, ucode_raw, &pieces, + &ucode_capa); if (err) goto try_again; @@ -1757,7 +1873,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) goto try_again; } - /* Allocate ucode buffers for card's bus-master loading ... */ /* Runtime instructions and 2 copies of data: @@ -1841,7 +1956,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) * * 9. Setup and register with mac80211 and debugfs **************************************************/ - err = iwl_mac_setup_register(priv); + err = iwl_mac_setup_register(priv, &ucode_capa); if (err) goto out_unbind; @@ -2716,7 +2831,8 @@ void iwl_post_associate(struct iwl_priv *priv) * Not a mac80211 entry point function, but it fits in with all the * other mac80211 functions grouped here. */ -static int iwl_mac_setup_register(struct iwl_priv *priv) +static int iwl_mac_setup_register(struct iwl_priv *priv, + struct iwlagn_ucode_capabilities *capa) { int ret; struct ieee80211_hw *hw = priv->hw; @@ -2751,7 +2867,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv) hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; /* we create the 802.11 header and a zero-length SSID element */ - hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; + hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 2; /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; @@ -3974,3 +4090,8 @@ MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); module_param_named( disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); + +module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int, + S_IRUGO); +MODULE_PARM_DESC(ucode_alternative, + "specify ucode alternative to use from ucode file"); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 0086019b7a15..449d41f058b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2668,7 +2668,6 @@ struct iwl_ssid_ie { #define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff) #define IWL_MAX_SCAN_SIZE 1024 #define IWL_MAX_CMD_SIZE 4096 -#define IWL_MAX_PROBE_REQUEST 200 /* * REPLY_SCAN_CMD = 0x80 (command) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index fe938d9e43cb..19a5c895f1a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -518,7 +518,7 @@ struct fw_desc { u32 len; /* bytes */ }; -/* uCode file layout */ +/* v1/v2 uCode file layout */ struct iwl_ucode_header { __le32 ver; /* major/minor/API/serial */ union { @@ -542,6 +542,62 @@ struct iwl_ucode_header { } u; }; +/* + * new TLV uCode file layout + * + * The new TLV file format contains TLVs, that each specify + * some piece of data. To facilitate "groups", for example + * different instruction image with different capabilities, + * bundled with the same init image, an alternative mechanism + * is provided: + * When the alternative field is 0, that means that the item + * is always valid. When it is non-zero, then it is only + * valid in conjunction with items of the same alternative, + * in which case the driver (user) selects one alternative + * to use. + */ + +enum iwl_ucode_tlv_type { + IWL_UCODE_TLV_INVALID = 0, /* unused */ + IWL_UCODE_TLV_INST = 1, + IWL_UCODE_TLV_DATA = 2, + IWL_UCODE_TLV_INIT = 3, + IWL_UCODE_TLV_INIT_DATA = 4, + IWL_UCODE_TLV_BOOT = 5, + IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ +}; + +struct iwl_ucode_tlv { + __le16 type; /* see above */ + __le16 alternative; /* see comment */ + __le32 length; /* not including type/length fields */ + u8 data[0]; +} __attribute__ ((packed)); + +#define IWL_TLV_UCODE_MAGIC 0x0a4c5749 + +struct iwl_tlv_ucode_header { + /* + * The TLV style ucode header is distinguished from + * the v1/v2 style header by first four bytes being + * zero, as such is an invalid combination of + * major/minor/API/serial versions. + */ + __le32 zero; + __le32 magic; + u8 human_readable[64]; + __le32 ver; /* major/minor/API/serial */ + __le32 build; + __le64 alternatives; /* bitmask of valid alternatives */ + /* + * The data contained herein has a TLV layout, + * see above for the TLV header and types. + * Note that each TLV is padded to a length + * that is a multiple of 4 for alignment. + */ + u8 data[0]; +}; + struct iwl4965_ibss_seq { u8 mac[ETH_ALEN]; u16 seq_num; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 59c85f55e625..77ab00b98778 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3875,6 +3875,8 @@ err: return ret; } +#define IWL3945_MAX_PROBE_REQUEST 200 + static int iwl3945_setup_mac(struct iwl_priv *priv) { int ret; @@ -3900,7 +3902,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; /* we create the 802.11 header and a zero-length SSID element */ - hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; + hw->wiphy->max_scan_ie_len = IWL3945_MAX_PROBE_REQUEST - 24 - 2; /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; -- cgit v1.2.3 From a29576a7844326c5223f4d4adbfd3f4d64173d4c Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 28 Apr 2010 15:47:04 -0700 Subject: iwl3945: add plcp error checking Add plcp error checking for 3945. After threshold of plcp is reached , it resets the radio Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945.c | 67 ++++++++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-core.h | 2 + drivers/net/wireless/iwlwifi/iwl-rx.c | 3 +- 3 files changed, 69 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index a4d842a05836..05d808b28777 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -390,6 +390,67 @@ static void iwl3945_accumulative_statistics(struct iwl_priv *priv, } #endif +/** + * iwl3945_good_plcp_health - checks for plcp error. + * + * When the plcp error is exceeding the thresholds, reset the radio + * to improve the throughput. + */ +static bool iwl3945_good_plcp_health(struct iwl_priv *priv, + struct iwl_rx_packet *pkt) +{ + bool rc = true; + struct iwl3945_notif_statistics current_stat; + int combined_plcp_delta; + unsigned int plcp_msec; + unsigned long plcp_received_jiffies; + + memcpy(¤t_stat, pkt->u.raw, sizeof(struct + iwl3945_notif_statistics)); + /* + * check for plcp_err and trigger radio reset if it exceeds + * the plcp error threshold plcp_delta. + */ + plcp_received_jiffies = jiffies; + plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies - + (long) priv->plcp_jiffies); + priv->plcp_jiffies = plcp_received_jiffies; + /* + * check to make sure plcp_msec is not 0 to prevent division + * by zero. + */ + if (plcp_msec) { + combined_plcp_delta = + (le32_to_cpu(current_stat.rx.ofdm.plcp_err) - + le32_to_cpu(priv->_3945.statistics.rx.ofdm.plcp_err)); + + if ((combined_plcp_delta > 0) && + ((combined_plcp_delta * 100) / plcp_msec) > + priv->cfg->plcp_delta_threshold) { + /* + * if plcp_err exceed the threshold, the following + * data is printed in csv format: + * Text: plcp_err exceeded %d, + * Received ofdm.plcp_err, + * Current ofdm.plcp_err, + * combined_plcp_delta, + * plcp_msec + */ + IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " + "%u, %d, %u mSecs\n", + priv->cfg->plcp_delta_threshold, + le32_to_cpu(current_stat.rx.ofdm.plcp_err), + combined_plcp_delta, plcp_msec); + /* + * Reset the RF radio due to the high plcp + * error rate + */ + rc = false; + } + } + return rc; +} + void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -401,6 +462,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw); #endif + iwl_recover_from_statistics(priv, pkt); memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics)); } @@ -2792,6 +2854,7 @@ static struct iwl_lib_ops iwl3945_lib = { .config_ap = iwl3945_config_ap, .manage_ibss_station = iwl3945_manage_ibss_station, .add_bcast_station = iwl3945_add_bcast_station, + .check_plcp_health = iwl3945_good_plcp_health, .debugfs_ops = { .rx_stats_read = iwl3945_ucode_rx_stats_read, @@ -2832,7 +2895,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { .ht_greenfield_support = false, .led_compensation = 64, .broken_powersave = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, .tx_power_by_driver = true, @@ -2853,7 +2916,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .ht_greenfield_support = false, .led_compensation = 64, .broken_powersave = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .monitor_recover_period = IWL_MONITORING_PERIOD, .max_event_log_size = 512, .tx_power_by_driver = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 2f664a3f0484..7a3f94926c25 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -441,6 +441,8 @@ bool iwl_good_plcp_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt); bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt); +void iwl_recover_from_statistics(struct iwl_priv *priv, + struct iwl_rx_packet *pkt); void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_reply_statistics(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index d661fce000c2..c7c8d8a43eb3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -397,7 +397,7 @@ bool iwl_good_plcp_health(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_good_plcp_health); -static void iwl_recover_from_statistics(struct iwl_priv *priv, +void iwl_recover_from_statistics(struct iwl_priv *priv, struct iwl_rx_packet *pkt) { if (test_bit(STATUS_EXIT_PENDING, &priv->status)) @@ -428,6 +428,7 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv, } } } +EXPORT_SYMBOL(iwl_recover_from_statistics); void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) -- cgit v1.2.3 From 159605dd5ec6356f5a7f0c56d9b9e63e0e61f3a8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 29 Apr 2010 04:43:02 -0700 Subject: iwlwifi: remove rts_threshold We never use that member of struct iwl_priv. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 19a5c895f1a2..d09c8bc20d17 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1211,7 +1211,6 @@ struct iwl_priv { /* context information */ u8 bssid[ETH_ALEN]; - u16 rts_threshold; u8 mac_addr[ETH_ALEN]; /*station table variables */ -- cgit v1.2.3 From 93286db50130754d9655c457ad0e11cb8f37a10f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 29 Apr 2010 04:43:03 -0700 Subject: iwlagn: move iwl_get_ra_sta_id to 4965 This function is only needed by 4965, so it need not be in core code and can be made static. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-4965.c | 10 ++++++++++ drivers/net/wireless/iwlwifi/iwl-sta.c | 11 ----------- drivers/net/wireless/iwlwifi/iwl-sta.h | 1 - 3 files changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index a3562a126c93..b8bf837af464 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1953,6 +1953,16 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, return 0; } +static int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) +{ + if (priv->iw_mode == NL80211_IFTYPE_STATION) { + return IWL_AP_ID; + } else { + u8 *da = ieee80211_get_DA(hdr); + return iwl_find_station(priv, da); + } +} + /** * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response */ diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 7da8edeb5256..0db742c0aff5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -80,17 +80,6 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) } EXPORT_SYMBOL(iwl_find_station); -int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) -{ - if (priv->iw_mode == NL80211_IFTYPE_STATION) { - return IWL_AP_ID; - } else { - u8 *da = ieee80211_get_DA(hdr); - return iwl_find_station(priv, da); - } -} -EXPORT_SYMBOL(iwl_get_ra_sta_id); - /* priv->sta_lock must be held */ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) { diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 9a869f1031fd..1a0e590a824d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -66,7 +66,6 @@ void iwl_restore_stations(struct iwl_priv *priv); void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force); int iwl_get_free_ucode_key_index(struct iwl_priv *priv); int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); -int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_addsta_cmd *sta, u8 flags); int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs); -- cgit v1.2.3 From eafdfbd32aa9fcaf17733c04d5eb071af3b1ff47 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 29 Apr 2010 04:43:04 -0700 Subject: iwlagn: use vif->type to check station We need not check iw_mode, since we have the vif pointer available. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 97184e14a775..7c3363ab561a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3223,7 +3223,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; - bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; + bool is_ap = vif->type == NL80211_IFTYPE_STATION; int ret; u8 sta_id; -- cgit v1.2.3 From 3474ad635db371b0d8d0ee40086f15d223d5b6a4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 29 Apr 2010 04:43:05 -0700 Subject: iwlwifi: apply filter flags directly Since iwl_configure_filter can now sleep since the mac80211 callback was changed, we can now apply filter flags changes directly. Also, while at it, make the code a bit more generic with a local macro. There's no need to check changed_flags since we apply all at the same time anyway. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 52 ++++++++++++++------------------- 1 file changed, 22 insertions(+), 30 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5c6f25462a09..246538a27fc6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1257,41 +1257,33 @@ void iwl_configure_filter(struct ieee80211_hw *hw, u64 multicast) { struct iwl_priv *priv = hw->priv; - __le32 *filter_flags = &priv->staging_rxon.filter_flags; + __le32 filter_or = 0, filter_nand = 0; + +#define CHK(test, flag) do { \ + if (*total_flags & (test)) \ + filter_or |= (flag); \ + else \ + filter_nand |= (flag); \ + } while (0) IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", changed_flags, *total_flags); - if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) { - if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) - *filter_flags |= RXON_FILTER_PROMISC_MSK; - else - *filter_flags &= ~RXON_FILTER_PROMISC_MSK; - } - if (changed_flags & FIF_ALLMULTI) { - if (*total_flags & FIF_ALLMULTI) - *filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK; - else - *filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK; - } - if (changed_flags & FIF_CONTROL) { - if (*total_flags & FIF_CONTROL) - *filter_flags |= RXON_FILTER_CTL2HOST_MSK; - else - *filter_flags &= ~RXON_FILTER_CTL2HOST_MSK; - } - if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { - if (*total_flags & FIF_BCN_PRBRESP_PROMISC) - *filter_flags |= RXON_FILTER_BCON_AWARE_MSK; - else - *filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK; - } + CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); + CHK(FIF_ALLMULTI, RXON_FILTER_ACCEPT_GRP_MSK); + CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); + CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); - /* We avoid iwl_commit_rxon here to commit the new filter flags - * since mac80211 will call ieee80211_hw_config immediately. - * (mc_list is not supported at this time). Otherwise, we need to - * queue a background iwl_commit_rxon work. - */ +#undef CHK + + mutex_lock(&priv->mutex); + + priv->staging_rxon.filter_flags &= ~filter_nand; + priv->staging_rxon.filter_flags |= filter_or; + + iwlcore_commit_rxon(priv); + + mutex_unlock(&priv->mutex); *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; -- cgit v1.2.3 From 1dda6d28377bec52f96767e8d4a59aa95102b9dd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 29 Apr 2010 04:43:06 -0700 Subject: iwlwifi: push virtual interface through Rather than keeping every bit of information around in priv and the virtual interface, add a virtual interface to many functions and use the information directly from it. This removes beacon_int, assoc_capability and assoc_id from struct iwl_priv. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945.h | 8 ++-- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 18 +++++---- drivers/net/wireless/iwlwifi/iwl-agn.c | 52 ++++++++++++------------ drivers/net/wireless/iwlwifi/iwl-agn.h | 2 +- drivers/net/wireless/iwlwifi/iwl-core.c | 54 ++++++++++++------------- drivers/net/wireless/iwlwifi/iwl-core.h | 25 +++++++----- drivers/net/wireless/iwlwifi/iwl-dev.h | 5 --- drivers/net/wireless/iwlwifi/iwl-scan.c | 13 +++--- drivers/net/wireless/iwlwifi/iwl3945-base.c | 63 ++++++++++++++--------------- 9 files changed, 118 insertions(+), 122 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index cea824c15bc5..8fe24eee1c56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -261,8 +261,10 @@ void iwl3945_reply_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); extern void iwl3945_disable_events(struct iwl_priv *priv); extern int iwl4965_get_temperature(const struct iwl_priv *priv); -extern void iwl3945_post_associate(struct iwl_priv *priv); -extern void iwl3945_config_ap(struct iwl_priv *priv); +extern void iwl3945_post_associate(struct iwl_priv *priv, + struct ieee80211_vif *vif); +extern void iwl3945_config_ap(struct iwl_priv *priv, + struct ieee80211_vif *vif); /** * iwl3945_hw_find_station - Find station id for a given BSSID @@ -288,7 +290,7 @@ extern const struct iwl_channel_info *iwl3945_get_channel_info( extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate); /* scanning */ -void iwl3945_request_scan(struct iwl_priv *priv); +void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); /* Requires full declaration of iwl_priv before including */ #include "iwl-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 50ff313c549c..f05e6002a04e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1114,8 +1114,9 @@ void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, } static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, - enum ieee80211_band band, - struct iwl_scan_channel *scan_ch) + struct ieee80211_vif *vif, + enum ieee80211_band band, + struct iwl_scan_channel *scan_ch) { const struct ieee80211_supported_band *sband; const struct iwl_channel_info *ch_info; @@ -1131,7 +1132,7 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, } active_dwell = iwl_get_active_dwell_time(priv, band, 0); - passive_dwell = iwl_get_passive_dwell_time(priv, band); + passive_dwell = iwl_get_passive_dwell_time(priv, band, vif); if (passive_dwell <= active_dwell) passive_dwell = active_dwell + 1; @@ -1180,6 +1181,7 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, } static int iwl_get_channels_for_scan(struct iwl_priv *priv, + struct ieee80211_vif *vif, enum ieee80211_band band, u8 is_active, u8 n_probes, struct iwl_scan_channel *scan_ch) @@ -1197,7 +1199,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, return 0; active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); - passive_dwell = iwl_get_passive_dwell_time(priv, band); + passive_dwell = iwl_get_passive_dwell_time(priv, band, vif); if (passive_dwell <= active_dwell) passive_dwell = active_dwell + 1; @@ -1257,7 +1259,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, return added; } -void iwlagn_request_scan(struct iwl_priv *priv) +void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) { struct iwl_host_cmd cmd = { .id = REPLY_SCAN_CMD, @@ -1343,7 +1345,7 @@ void iwlagn_request_scan(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); spin_lock_irqsave(&priv->lock, flags); - interval = priv->beacon_int; + interval = vif ? vif->bss_conf.beacon_int : 0; spin_unlock_irqrestore(&priv->lock, flags); scan->suspend_time = 0; @@ -1474,12 +1476,12 @@ void iwlagn_request_scan(struct iwl_priv *priv) if (priv->is_internal_short_scan) { scan->channel_count = - iwl_get_single_channel_for_scan(priv, band, + iwl_get_single_channel_for_scan(priv, vif, band, (void *)&scan->data[le16_to_cpu( scan->tx_cmd.len)]); } else { scan->channel_count = - iwl_get_channels_for_scan(priv, band, + iwl_get_channels_for_scan(priv, vif, band, is_active, n_probes, (void *)&scan->data[le16_to_cpu( scan->tx_cmd.len)]); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7c3363ab561a..270635edb63c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2356,7 +2356,7 @@ static void iwl_alive_start(struct iwl_priv *priv) active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; } else { /* Initialize our rx_config data */ - iwl_connection_init_rx_config(priv, priv->iw_mode); + iwl_connection_init_rx_config(priv, NULL); if (priv->cfg->ops->hcmd->set_rxon_chain) priv->cfg->ops->hcmd->set_rxon_chain(priv); @@ -2729,12 +2729,15 @@ static void iwl_bg_rx_replenish(struct work_struct *data) #define IWL_DELAY_NEXT_SCAN (HZ*2) -void iwl_post_associate(struct iwl_priv *priv) +void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) { struct ieee80211_conf *conf = NULL; int ret = 0; - if (priv->iw_mode == NL80211_IFTYPE_AP) { + if (!vif || !priv->is_open) + return; + + if (vif->type == NL80211_IFTYPE_AP) { IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); return; } @@ -2742,10 +2745,6 @@ void iwl_post_associate(struct iwl_priv *priv) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - - if (!priv->vif || !priv->is_open) - return; - iwl_scan_cancel_timeout(priv, 200); conf = ieee80211_get_hw_conf(priv->hw); @@ -2753,7 +2752,7 @@ void iwl_post_associate(struct iwl_priv *priv) priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv); - iwl_setup_rxon_timing(priv); + iwl_setup_rxon_timing(priv, vif); ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, sizeof(priv->rxon_timing), &priv->rxon_timing); if (ret) @@ -2767,43 +2766,41 @@ void iwl_post_associate(struct iwl_priv *priv) if (priv->cfg->ops->hcmd->set_rxon_chain) priv->cfg->ops->hcmd->set_rxon_chain(priv); - priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); + priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid); IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", - priv->assoc_id, priv->beacon_int); + vif->bss_conf.aid, vif->bss_conf.beacon_int); - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) + if (vif->bss_conf.assoc_capability & + WLAN_CAPABILITY_SHORT_SLOT_TIME) priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) + if (vif->type == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - } iwlcore_commit_rxon(priv); IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", - priv->assoc_id, priv->active_rxon.bssid_addr); + vif->bss_conf.aid, priv->active_rxon.bssid_addr); - switch (priv->iw_mode) { + switch (vif->type) { case NL80211_IFTYPE_STATION: break; case NL80211_IFTYPE_ADHOC: - /* assume default assoc id */ - priv->assoc_id = 1; iwl_send_beacon_cmd(priv); break; default: IWL_ERR(priv, "%s Should not be called in %d mode\n", - __func__, priv->iw_mode); + __func__, vif->type); break; } @@ -2980,7 +2977,7 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } -void iwl_config_ap(struct iwl_priv *priv) +void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) { int ret = 0; @@ -2995,7 +2992,7 @@ void iwl_config_ap(struct iwl_priv *priv) iwlcore_commit_rxon(priv); /* RXON Timing */ - iwl_setup_rxon_timing(priv); + iwl_setup_rxon_timing(priv, vif); ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, sizeof(priv->rxon_timing), &priv->rxon_timing); if (ret) @@ -3009,9 +3006,10 @@ void iwl_config_ap(struct iwl_priv *priv) if (priv->cfg->ops->hcmd->set_rxon_chain) priv->cfg->ops->hcmd->set_rxon_chain(priv); - /* FIXME: what should be the assoc_id for AP? */ - priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + priv->staging_rxon.assoc_id = 0; + + if (vif->bss_conf.assoc_capability & + WLAN_CAPABILITY_SHORT_PREAMBLE) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else @@ -3019,15 +3017,15 @@ void iwl_config_ap(struct iwl_priv *priv) ~RXON_FLG_SHORT_PREAMBLE_MSK; if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { - if (priv->assoc_capability & - WLAN_CAPABILITY_SHORT_SLOT_TIME) + if (vif->bss_conf.assoc_capability & + WLAN_CAPABILITY_SHORT_SLOT_TIME) priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) + if (vif->type == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 4a1e7b2b7a8e..f52bedb8c8b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -171,7 +171,7 @@ static inline bool iwl_is_tx_success(u32 status) } /* scan */ -void iwlagn_request_scan(struct iwl_priv *priv); +void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); /* station mgmt */ int iwlagn_manage_ibss_station(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 246538a27fc6..68c3693a296e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -480,7 +480,7 @@ static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) return new_val; } -void iwl_setup_rxon_timing(struct iwl_priv *priv) +void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) { u64 tsf; s32 interval_tm, rem; @@ -494,15 +494,14 @@ void iwl_setup_rxon_timing(struct iwl_priv *priv) priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp); priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval); - if (priv->iw_mode == NL80211_IFTYPE_STATION) { - beacon_int = priv->beacon_int; - priv->rxon_timing.atim_window = 0; - } else { - beacon_int = priv->vif->bss_conf.beacon_int; + beacon_int = vif->bss_conf.beacon_int; + if (vif->type == NL80211_IFTYPE_ADHOC) { /* TODO: we need to get atim_window from upper stack * for now we set to 0 */ priv->rxon_timing.atim_window = 0; + } else { + priv->rxon_timing.atim_window = 0; } beacon_int = iwl_adjust_beacon_interval(beacon_int, @@ -894,8 +893,9 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) } EXPORT_SYMBOL(iwl_set_rxon_channel); -void iwl_set_flags_for_band(struct iwl_priv *priv, - enum ieee80211_band band) +static void iwl_set_flags_for_band(struct iwl_priv *priv, + enum ieee80211_band band, + struct ieee80211_vif *vif) { if (band == IEEE80211_BAND_5GHZ) { priv->staging_rxon.flags &= @@ -904,12 +904,12 @@ void iwl_set_flags_for_band(struct iwl_priv *priv, priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; } else { /* Copied from iwl_post_associate() */ - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) + if (vif && vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) + if (vif && vif->type == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; @@ -921,13 +921,18 @@ void iwl_set_flags_for_band(struct iwl_priv *priv, /* * initialize rxon structure with default values from eeprom */ -void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) +void iwl_connection_init_rx_config(struct iwl_priv *priv, + struct ieee80211_vif *vif) { const struct iwl_channel_info *ch_info; + enum nl80211_iftype type = NL80211_IFTYPE_STATION; + + if (vif) + type = vif->type; memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); - switch (mode) { + switch (type) { case NL80211_IFTYPE_AP: priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP; break; @@ -945,7 +950,7 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) break; default: - IWL_ERR(priv, "Unsupported interface type %d\n", mode); + IWL_ERR(priv, "Unsupported interface type %d\n", type); break; } @@ -967,7 +972,7 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); priv->band = ch_info->band; - iwl_set_flags_for_band(priv, priv->band); + iwl_set_flags_for_band(priv, priv->band, vif); priv->staging_rxon.ofdm_basic_rates = (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; @@ -1793,7 +1798,6 @@ static void iwl_ht_conf(struct iwl_priv *priv, static inline void iwl_set_no_assoc(struct iwl_priv *priv) { - priv->assoc_id = 0; iwl_led_disassociate(priv); /* * inform the ucode that there is no longer an @@ -1827,7 +1831,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, } if (changes & BSS_CHANGED_BEACON_INT) { - priv->beacon_int = bss_conf->beacon_int; /* TODO: in AP mode, do something to make this take effect */ } @@ -1917,20 +1920,17 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, if (changes & BSS_CHANGED_ASSOC) { IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); if (bss_conf->assoc) { - priv->assoc_id = bss_conf->aid; - priv->beacon_int = bss_conf->beacon_int; priv->timestamp = bss_conf->timestamp; - priv->assoc_capability = bss_conf->assoc_capability; iwl_led_associate(priv); if (!iwl_is_rfkill(priv)) - priv->cfg->ops->lib->post_associate(priv); + priv->cfg->ops->lib->post_associate(priv, vif); } else iwl_set_no_assoc(priv); } - if (changes && iwl_is_associated(priv) && priv->assoc_id) { + if (changes && iwl_is_associated(priv) && bss_conf->aid) { IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n", changes); ret = iwl_send_rxon_assoc(priv); @@ -1947,7 +1947,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, memcpy(priv->staging_rxon.bssid_addr, bss_conf->bssid, ETH_ALEN); memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); - iwlcore_config_ap(priv); + iwlcore_config_ap(priv, vif); } else iwl_set_no_assoc(priv); } @@ -1987,14 +1987,13 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) priv->ibss_beacon = skb; - priv->assoc_id = 0; timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; priv->timestamp = le64_to_cpu(timestamp); IWL_DEBUG_MAC80211(priv, "leave\n"); spin_unlock_irqrestore(&priv->lock, flags); - priv->cfg->ops->lib->post_associate(priv); + priv->cfg->ops->lib->post_associate(priv, priv->vif); return 0; } @@ -2002,7 +2001,7 @@ EXPORT_SYMBOL(iwl_mac_beacon_update); static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) { - iwl_connection_init_rx_config(priv, vif->type); + iwl_connection_init_rx_config(priv, vif); if (priv->cfg->ops->hcmd->set_rxon_chain) priv->cfg->ops->hcmd->set_rxon_chain(priv); @@ -2176,7 +2175,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) iwl_set_rxon_channel(priv, conf->channel); iwl_set_rxon_ht(priv, ht_conf); - iwl_set_flags_for_band(priv, conf->channel->band); + iwl_set_flags_for_band(priv, conf->channel->band, priv->vif); spin_unlock_irqrestore(&priv->lock, flags); if (iwl_is_associated(priv) && (le16_to_cpu(priv->active_rxon.channel) != ch) && @@ -2259,8 +2258,6 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) spin_unlock_irqrestore(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags); - priv->assoc_id = 0; - priv->assoc_capability = 0; /* new association get rid of ibss beacon skb */ if (priv->ibss_beacon) @@ -2268,7 +2265,6 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) priv->ibss_beacon = NULL; - priv->beacon_int = priv->vif->bss_conf.beacon_int; priv->timestamp = 0; spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7a3f94926c25..1774ce9186eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -106,7 +106,7 @@ struct iwl_hcmd_utils_ops { __le32 *tx_flags); int (*calc_rssi)(struct iwl_priv *priv, struct iwl_rx_phy_res *rx_resp); - void (*request_scan)(struct iwl_priv *priv); + void (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif); }; struct iwl_apm_ops { @@ -180,8 +180,9 @@ struct iwl_lib_ops { /* power */ int (*send_tx_power) (struct iwl_priv *priv); void (*update_chain_flags)(struct iwl_priv *priv); - void (*post_associate) (struct iwl_priv *priv); - void (*config_ap) (struct iwl_priv *priv); + void (*post_associate)(struct iwl_priv *priv, + struct ieee80211_vif *vif); + void (*config_ap)(struct iwl_priv *priv, struct ieee80211_vif *vif); irqreturn_t (*isr) (int irq, void *data); /* eeprom operations (as defined in iwl-eeprom.h) */ @@ -334,8 +335,8 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, struct ieee80211_sta_ht_cap *sta_ht_inf); -void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band); -void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode); +void iwl_connection_init_rx_config(struct iwl_priv *priv, + struct ieee80211_vif *vif); int iwl_set_decrypted_flag(struct iwl_priv *priv, struct ieee80211_hdr *hdr, u32 decrypt_res, @@ -345,7 +346,7 @@ void iwl_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, u64 multicast); int iwl_set_hw_params(struct iwl_priv *priv); -void iwl_post_associate(struct iwl_priv *priv); +void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif); void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -357,7 +358,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, void iwl_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); -void iwl_config_ap(struct iwl_priv *priv); +void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif); void iwl_mac_reset_tsf(struct ieee80211_hw *hw); int iwl_alloc_txq_mem(struct iwl_priv *priv); void iwl_free_txq_mem(struct iwl_priv *priv); @@ -520,7 +521,8 @@ u16 iwl_get_active_dwell_time(struct iwl_priv *priv, enum ieee80211_band band, u8 n_probes); u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band); + enum ieee80211_band band, + struct ieee80211_vif *vif); void iwl_bg_scan_check(struct work_struct *data); void iwl_bg_abort_scan(struct work_struct *work); void iwl_bg_scan_completed(struct work_struct *work); @@ -684,7 +686,7 @@ extern int iwl_send_lq_cmd(struct iwl_priv *priv, void iwl_apm_stop(struct iwl_priv *priv); int iwl_apm_init(struct iwl_priv *priv); -void iwl_setup_rxon_timing(struct iwl_priv *priv); +void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif); static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) { return priv->cfg->ops->hcmd->rxon_assoc(priv); @@ -693,9 +695,10 @@ static inline int iwlcore_commit_rxon(struct iwl_priv *priv) { return priv->cfg->ops->hcmd->commit_rxon(priv); } -static inline void iwlcore_config_ap(struct iwl_priv *priv) +static inline void iwlcore_config_ap(struct iwl_priv *priv, + struct ieee80211_vif *vif) { - priv->cfg->ops->lib->config_ap(priv); + priv->cfg->ops->lib->config_ap(priv, vif); } static inline const struct ieee80211_supported_band *iwl_get_hw_mode( struct iwl_priv *priv, enum ieee80211_band band) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index d09c8bc20d17..bcdb663ec923 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1243,7 +1243,6 @@ struct iwl_priv { /* Last Rx'd beacon timestamp */ u64 timestamp; - u16 beacon_int; struct ieee80211_vif *vif; union { @@ -1305,10 +1304,6 @@ struct iwl_priv { struct iwl_hw_params hw_params; u32 inta_mask; - /* Current association information needed to configure the - * hardware */ - u16 assoc_id; - u16 assoc_capability; struct iwl_qos_info qos_data; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 28e2d86ee055..32ca848e9262 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -264,7 +264,8 @@ inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, EXPORT_SYMBOL(iwl_get_active_dwell_time); u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band) + enum ieee80211_band band, + struct ieee80211_vif *vif) { u16 passive = (band == IEEE80211_BAND_2GHZ) ? IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : @@ -274,7 +275,7 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, /* If we're associated, we clamp the maximum passive * dwell time to be 98% of the beacon interval (minus * 2 * channel tune time) */ - passive = priv->beacon_int; + passive = vif ? vif->bss_conf.beacon_int : 0; if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive) passive = IWL_PASSIVE_DWELL_BASE; passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; @@ -294,7 +295,7 @@ void iwl_init_scan_params(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_init_scan_params); -static int iwl_scan_initiate(struct iwl_priv *priv) +static int iwl_scan_initiate(struct iwl_priv *priv, struct ieee80211_vif *vif) { WARN_ON(!mutex_is_locked(&priv->mutex)); @@ -306,7 +307,7 @@ static int iwl_scan_initiate(struct iwl_priv *priv) if (WARN_ON(!priv->cfg->ops->utils->request_scan)) return -EOPNOTSUPP; - priv->cfg->ops->utils->request_scan(priv); + priv->cfg->ops->utils->request_scan(priv, vif); return 0; } @@ -347,7 +348,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, priv->scan_band = req->channels[0]->band; priv->scan_request = req; - ret = iwl_scan_initiate(priv); + ret = iwl_scan_initiate(priv, vif); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -398,7 +399,7 @@ void iwl_bg_start_internal_scan(struct work_struct *work) if (WARN_ON(!priv->cfg->ops->utils->request_scan)) goto unlock; - priv->cfg->ops->utils->request_scan(priv); + priv->cfg->ops->utils->request_scan(priv, NULL); unlock: mutex_unlock(&priv->mutex); } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 77ab00b98778..85a46ad667de 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1847,7 +1847,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, enum ieee80211_band band, u8 is_active, u8 n_probes, - struct iwl3945_scan_channel *scan_ch) + struct iwl3945_scan_channel *scan_ch, + struct ieee80211_vif *vif) { struct ieee80211_channel *chan; const struct ieee80211_supported_band *sband; @@ -1861,7 +1862,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, return 0; active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); - passive_dwell = iwl_get_passive_dwell_time(priv, band); + passive_dwell = iwl_get_passive_dwell_time(priv, band, vif); if (passive_dwell <= active_dwell) passive_dwell = active_dwell + 1; @@ -2543,7 +2544,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; } else { /* Initialize our rx_config data */ - iwl_connection_init_rx_config(priv, priv->iw_mode); + iwl_connection_init_rx_config(priv, NULL); } /* Configure Bluetooth device coexistence support */ @@ -2811,7 +2812,7 @@ static void iwl3945_rfkill_poll(struct work_struct *data) } -void iwl3945_request_scan(struct iwl_priv *priv) +void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) { struct iwl_host_cmd cmd = { .id = REPLY_SCAN_CMD, @@ -2892,7 +2893,7 @@ void iwl3945_request_scan(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); spin_lock_irqsave(&priv->lock, flags); - interval = priv->beacon_int; + interval = vif ? vif->bss_conf.beacon_int : 0; spin_unlock_irqrestore(&priv->lock, flags); scan->suspend_time = 0; @@ -2987,7 +2988,7 @@ void iwl3945_request_scan(struct iwl_priv *priv) scan->channel_count = iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif); if (scan->channel_count == 0) { IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); @@ -3060,26 +3061,25 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data) mutex_unlock(&priv->mutex); } -void iwl3945_post_associate(struct iwl_priv *priv) +void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) { int rc = 0; struct ieee80211_conf *conf = NULL; - if (priv->iw_mode == NL80211_IFTYPE_AP) { + if (!vif || !priv->is_open) + return; + + if (vif->type == NL80211_IFTYPE_AP) { IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); return; } - IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", - priv->assoc_id, priv->active_rxon.bssid_addr); + vif->bss_conf.aid, priv->active_rxon.bssid_addr); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (!priv->vif || !priv->is_open) - return; - iwl_scan_cancel_timeout(priv, 200); conf = ieee80211_get_hw_conf(priv->hw); @@ -3088,7 +3088,7 @@ void iwl3945_post_associate(struct iwl_priv *priv) iwlcore_commit_rxon(priv); memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); - iwl_setup_rxon_timing(priv); + iwl_setup_rxon_timing(priv, vif); rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, sizeof(priv->rxon_timing), &priv->rxon_timing); if (rc) @@ -3097,40 +3097,38 @@ void iwl3945_post_associate(struct iwl_priv *priv) priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); + priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid); IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", - priv->assoc_id, priv->beacon_int); + vif->bss_conf.aid, vif->bss_conf.beacon_int); - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) + if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) + if (vif->type == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - } iwlcore_commit_rxon(priv); - switch (priv->iw_mode) { + switch (vif->type) { case NL80211_IFTYPE_STATION: iwl3945_rate_scale_init(priv->hw, IWL_AP_ID); break; case NL80211_IFTYPE_ADHOC: - priv->assoc_id = 1; iwl3945_send_beacon_cmd(priv); break; default: - IWL_ERR(priv, "%s Should not be called in %d mode\n", - __func__, priv->iw_mode); + IWL_ERR(priv, "%s Should not be called in %d mode\n", + __func__, vif->type); break; } } @@ -3254,7 +3252,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } -void iwl3945_config_ap(struct iwl_priv *priv) +void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) { int rc = 0; @@ -3270,7 +3268,7 @@ void iwl3945_config_ap(struct iwl_priv *priv) /* RXON Timing */ memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); - iwl_setup_rxon_timing(priv); + iwl_setup_rxon_timing(priv, vif); rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, sizeof(priv->rxon_timing), &priv->rxon_timing); @@ -3278,9 +3276,10 @@ void iwl3945_config_ap(struct iwl_priv *priv) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); - /* FIXME: what should be the assoc_id for AP? */ - priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + priv->staging_rxon.assoc_id = 0; + + if (vif->bss_conf.assoc_capability & + WLAN_CAPABILITY_SHORT_PREAMBLE) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else @@ -3288,15 +3287,15 @@ void iwl3945_config_ap(struct iwl_priv *priv) ~RXON_FLG_SHORT_PREAMBLE_MSK; if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { - if (priv->assoc_capability & - WLAN_CAPABILITY_SHORT_SLOT_TIME) + if (vif->bss_conf.assoc_capability & + WLAN_CAPABILITY_SHORT_SLOT_TIME) priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) + if (vif->type == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } -- cgit v1.2.3 From 832f47e333c7d0db632b57e9f07956ae40dd481d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 29 Apr 2010 04:43:07 -0700 Subject: iwlagn: use virtual interface in TX aggregation handling Most of the TX aggregation handling can be passed the virtual interface directly instead of having to rely on priv->vif. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 12 +++++++----- drivers/net/wireless/iwlwifi/iwl-agn.c | 8 ++++---- drivers/net/wireless/iwlwifi/iwl-agn.h | 5 +++-- 3 files changed, 14 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index c2a5c85542bf..6a306e849584 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -961,7 +961,8 @@ static int iwlagn_txq_ctx_activate_free(struct iwl_priv *priv) return -1; } -int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) +int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, + const u8 *ra, u16 tid, u16 *ssn) { int sta_id; int tx_fifo; @@ -1011,7 +1012,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) if (tid_data->tfds_in_queue == 0) { IWL_DEBUG_HT(priv, "HW queue is empty\n"); tid_data->agg.state = IWL_AGG_ON; - ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid); + ieee80211_start_tx_ba_cb_irqsafe(vif, ra, tid); } else { IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", tid_data->tfds_in_queue); @@ -1020,7 +1021,8 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) return ret; } -int iwlagn_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) +int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, + const u8 *ra, u16 tid) { int tx_fifo_id, txq_id, sta_id, ssn = -1; struct iwl_tid_data *tid_data; @@ -1046,7 +1048,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) if (priv->stations[sta_id].tid[tid].agg.state == IWL_EMPTYING_HW_QUEUE_ADDBA) { IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); - ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); + ieee80211_stop_tx_ba_cb_irqsafe(vif, ra, tid); priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; return 0; } @@ -1083,7 +1085,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) tx_fifo_id); spin_unlock_irqrestore(&priv->lock, flags); - ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); + ieee80211_stop_tx_ba_cb_irqsafe(vif, ra, tid); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 270635edb63c..85e045baf5ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3130,8 +3130,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn) { struct iwl_priv *priv = hw->priv; int ret; @@ -3155,7 +3155,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return ret; case IEEE80211_AMPDU_TX_START: IWL_DEBUG_HT(priv, "start Tx\n"); - ret = iwlagn_tx_agg_start(priv, sta->addr, tid, ssn); + ret = iwlagn_tx_agg_start(priv, vif, sta->addr, tid, ssn); if (ret == 0) { priv->_agn.agg_tids_count++; IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", @@ -3164,7 +3164,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return ret; case IEEE80211_AMPDU_TX_STOP: IWL_DEBUG_HT(priv, "stop Tx\n"); - ret = iwlagn_tx_agg_stop(priv, sta->addr, tid); + ret = iwlagn_tx_agg_stop(priv, vif, sta->addr, tid); if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { priv->_agn.agg_tids_count--; IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index f52bedb8c8b3..c4417739a64c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -135,9 +135,10 @@ void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, struct ieee80211_tx_info *info); int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); -int iwlagn_tx_agg_start(struct iwl_priv *priv, +int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, const u8 *ra, u16 tid, u16 *ssn); -int iwlagn_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); +int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, + const u8 *ra, u16 tid); int iwlagn_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, -- cgit v1.2.3 From 3a065ab3b57bedefa1d59c88f731da6513ac482a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 29 Apr 2010 04:43:08 -0700 Subject: iwlwifi: remove useless priv->vif check This check is not useful, since we now no longer dereference priv->vif at this spot. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-power.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 2655dbdc8175..1fe9d844313d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -317,10 +317,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; - if (priv->vif) - dtimper = priv->hw->conf.ps_dtim_period; - else - dtimper = 1; + dtimper = priv->hw->conf.ps_dtim_period ?: 1; if (priv->cfg->broken_powersave) iwl_power_sleep_cam_cmd(priv, &cmd); -- cgit v1.2.3 From ca3c1f59dc469e19431c683383d8205397595806 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 29 Apr 2010 04:43:09 -0700 Subject: iwlwifi: use vif in iwl_ht_conf Pass the virtual interface pointer to iwl_ht_conf() so it doesn't need to rely on iw_mode and other global variables. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 68c3693a296e..d7a36205f0e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1740,10 +1740,11 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, EXPORT_SYMBOL(iwl_mac_conf_tx); static void iwl_ht_conf(struct iwl_priv *priv, - struct ieee80211_bss_conf *bss_conf) + struct ieee80211_vif *vif) { struct iwl_ht_config *ht_conf = &priv->current_ht_config; struct ieee80211_sta *sta; + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; IWL_DEBUG_MAC80211(priv, "enter:\n"); @@ -1757,10 +1758,10 @@ static void iwl_ht_conf(struct iwl_priv *priv, ht_conf->single_chain_sufficient = false; - switch (priv->iw_mode) { + switch (vif->type) { case NL80211_IFTYPE_STATION: rcu_read_lock(); - sta = ieee80211_find_sta(priv->vif, priv->bssid); + sta = ieee80211_find_sta(vif, bss_conf->bssid); if (sta) { struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; int maxstreams; @@ -1911,7 +1912,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, } if (changes & BSS_CHANGED_HT) { - iwl_ht_conf(priv, bss_conf); + iwl_ht_conf(priv, vif); if (priv->cfg->ops->hcmd->set_rxon_chain) priv->cfg->ops->hcmd->set_rxon_chain(priv); -- cgit v1.2.3 From 59c02b4149183cb53d95b1ce3a8188cbee63f57f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 29 Apr 2010 04:43:10 -0700 Subject: iwlwifi: note that priv->bssid is used only by 3945 The bssid member of struct iwl_priv is now only used by 3945 code, so note that. It shouldn't be used by any other code in the future. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index bcdb663ec923..46571f7f7abf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1210,7 +1210,7 @@ struct iwl_priv { #endif /* context information */ - u8 bssid[ETH_ALEN]; + u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */ u8 mac_addr[ETH_ALEN]; /*station table variables */ -- cgit v1.2.3 From 156b70d17ce85778341cfb2a90c5bcb14b28ab3f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 28 Apr 2010 14:44:45 -0700 Subject: iwlwifi: fix iwl_sta_init_lq station ID The "is_ap" argument to iwl_sta_init_lq is never true, so it and the corresponding code can be removed. However, it needs to have the station ID because it is also used for the IBSS BSSID station, and that doesn't have the broadcast ID. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-sta.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 0db742c0aff5..dd1c639074c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -408,7 +408,7 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, EXPORT_SYMBOL(iwl_add_station_common); static struct iwl_link_quality_cmd *iwl_sta_init_lq(struct iwl_priv *priv, - const u8 *addr, bool is_ap) + u8 sta_id) { int i, r; struct iwl_link_quality_cmd *link_cmd; @@ -422,9 +422,7 @@ static struct iwl_link_quality_cmd *iwl_sta_init_lq(struct iwl_priv *priv, } /* Set up the rate scaling to start at selected rate, fall back * all the way down to 1M in IEEE order, and then spin on 1M */ - if (is_ap) - r = IWL_RATE_54M_INDEX; - else if (priv->band == IEEE80211_BAND_5GHZ) + if (priv->band == IEEE80211_BAND_5GHZ) r = IWL_RATE_6M_INDEX; else r = IWL_RATE_1M_INDEX; @@ -459,8 +457,7 @@ static struct iwl_link_quality_cmd *iwl_sta_init_lq(struct iwl_priv *priv, link_cmd->agg_params.agg_time_limit = cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); - /* Update the rate scaling for control frame Tx to AP */ - link_cmd->sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; + link_cmd->sta_id = sta_id; ret = iwl_send_lq_cmd(priv, link_cmd, CMD_SYNC, true); if (ret) @@ -496,7 +493,7 @@ int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs) if (init_rs) { /* Set up default rate scaling table in device's station table */ - link_cmd = iwl_sta_init_lq(priv, addr, false); + link_cmd = iwl_sta_init_lq(priv, sta_id); if (!link_cmd) { IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n", addr); -- cgit v1.2.3 From a6a0345c837346d1b74f4907d4747e6c1053a99f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 29 Apr 2010 10:41:07 -0700 Subject: iwlwifi: split allocation/sending local station LQ Rename iwl_sta_init_lq to iwl_sta_alloc_lq and move sending it out into the caller. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-sta.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index dd1c639074c1..5bf82b9b523b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -407,13 +407,12 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, } EXPORT_SYMBOL(iwl_add_station_common); -static struct iwl_link_quality_cmd *iwl_sta_init_lq(struct iwl_priv *priv, - u8 sta_id) +static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv, + u8 sta_id) { int i, r; struct iwl_link_quality_cmd *link_cmd; u32 rate_flags; - int ret = 0; link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL); if (!link_cmd) { @@ -459,10 +458,6 @@ static struct iwl_link_quality_cmd *iwl_sta_init_lq(struct iwl_priv *priv, link_cmd->sta_id = sta_id; - ret = iwl_send_lq_cmd(priv, link_cmd, CMD_SYNC, true); - if (ret) - IWL_ERR(priv, "Link quality command failed (%d)\n", ret); - return link_cmd; } @@ -493,12 +488,17 @@ int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs) if (init_rs) { /* Set up default rate scaling table in device's station table */ - link_cmd = iwl_sta_init_lq(priv, sta_id); + link_cmd = iwl_sta_alloc_lq(priv, sta_id); if (!link_cmd) { IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n", addr); return -ENOMEM; } + + ret = iwl_send_lq_cmd(priv, link_cmd, CMD_SYNC, true); + if (ret) + IWL_ERR(priv, "Link quality command failed (%d)\n", ret); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].lq = link_cmd; spin_unlock_irqrestore(&priv->sta_lock, flags); -- cgit v1.2.3 From 2c810ccdbac434ae38f4ec5331d3f047dc90f98a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 29 Apr 2010 00:53:29 -0700 Subject: iwlwifi: rework broadcast station management Currently, the broadcast station is managed along with the interface type, rather than always being present. That leads to a bug with injection -- it is currently not possible to inject frames when the only virtual interface is a monitor, because in that the required broadcast station is missing. Additionally, allocating and deallocating the broadcast station's LQ all the time is wasteful, and the code to support this is fairly complex. So this changes completely the way we manage the broadcast station. Rather than manage it along with any interface, we now allocate it when we bring the device up, and remove it again when we bring the device down. When we bring the device up, we don't immediately program the broadcast station into it, instead we just mark it active and rely on the next restore cycle to upload it to the device. This works because an unassociated RXON is always required at least once to set up device parameters, which implies a reprogramming of stations into the device. As we now manage all stations properly, there no longer is a need for forcing a clearing of them via iwl_clear_ucode_stations(), which can become a lot simpler. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 - drivers/net/wireless/iwlwifi/iwl-3945.c | 5 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 1 - drivers/net/wireless/iwlwifi/iwl-5000.c | 2 - drivers/net/wireless/iwlwifi/iwl-6000.c | 2 - drivers/net/wireless/iwlwifi/iwl-agn.c | 12 ++- drivers/net/wireless/iwlwifi/iwl-core.c | 7 -- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - drivers/net/wireless/iwlwifi/iwl-sta.c | 137 ++++++++++++++-------------- drivers/net/wireless/iwlwifi/iwl-sta.h | 12 +-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 8 +- 11 files changed, 89 insertions(+), 99 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index a2f7cbcc2f7c..6be2992f8f21 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -212,7 +212,6 @@ static struct iwl_lib_ops iwl1000_lib = { .temperature = iwlagn_temperature, .set_ct_kill = iwl1000_set_ct_threshold, }, - .add_bcast_station = iwl_add_bcast_station, .manage_ibss_station = iwlagn_manage_ibss_station, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 05d808b28777..7fb159565f68 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1992,7 +1992,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) "configuration (%d).\n", rc); return rc; } - iwl_clear_ucode_stations(priv, false); + iwl_clear_ucode_stations(priv); iwl_restore_stations(priv); } @@ -2025,7 +2025,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); if (!new_assoc) { - iwl_clear_ucode_stations(priv, false); + iwl_clear_ucode_stations(priv); iwl_restore_stations(priv); } @@ -2853,7 +2853,6 @@ static struct iwl_lib_ops iwl3945_lib = { .isr = iwl_isr_legacy, .config_ap = iwl3945_config_ap, .manage_ibss_station = iwl3945_manage_ibss_station, - .add_bcast_station = iwl3945_add_bcast_station, .check_plcp_health = iwl3945_good_plcp_health, .debugfs_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index b8bf837af464..93893aec6cc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2190,7 +2190,6 @@ static struct iwl_lib_ops iwl4965_lib = { .temperature = iwl4965_temperature_calib, .set_ct_kill = iwl4965_set_ct_threshold, }, - .add_bcast_station = iwl_add_bcast_station, .manage_ibss_station = iwlagn_manage_ibss_station, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index efda0e8ccacb..a28af7eb67eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -351,7 +351,6 @@ static struct iwl_lib_ops iwl5000_lib = { .temperature = iwlagn_temperature, .set_ct_kill = iwl5000_set_ct_threshold, }, - .add_bcast_station = iwl_add_bcast_station, .manage_ibss_station = iwlagn_manage_ibss_station, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, @@ -414,7 +413,6 @@ static struct iwl_lib_ops iwl5150_lib = { .temperature = iwl5150_temperature, .set_ct_kill = iwl5150_set_ct_threshold, }, - .add_bcast_station = iwl_add_bcast_station, .manage_ibss_station = iwlagn_manage_ibss_station, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 03c73244703c..9fbf54cd3e1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -317,7 +317,6 @@ static struct iwl_lib_ops iwl6000_lib = { .temperature = iwlagn_temperature, .set_ct_kill = iwl6000_set_ct_threshold, }, - .add_bcast_station = iwl_add_bcast_station, .manage_ibss_station = iwlagn_manage_ibss_station, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, @@ -390,7 +389,6 @@ static struct iwl_lib_ops iwl6050_lib = { .set_ct_kill = iwl6000_set_ct_threshold, .set_calib_version = iwl6050_set_calib_version, }, - .add_bcast_station = iwl_add_bcast_station, .manage_ibss_station = iwlagn_manage_ibss_station, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 85e045baf5ae..0c913ea71f1e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -156,7 +156,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); return ret; } - iwl_clear_ucode_stations(priv, false); + iwl_clear_ucode_stations(priv); iwl_restore_stations(priv); ret = iwl_restore_default_wep_keys(priv); if (ret) { @@ -188,7 +188,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) } IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); - iwl_clear_ucode_stations(priv, false); + iwl_clear_ucode_stations(priv); iwl_restore_stations(priv); ret = iwl_restore_default_wep_keys(priv); if (ret) { @@ -2403,7 +2403,8 @@ static void __iwl_down(struct iwl_priv *priv) if (!exit_pending) set_bit(STATUS_EXIT_PENDING, &priv->status); - iwl_clear_ucode_stations(priv, true); + iwl_clear_ucode_stations(priv); + iwl_dealloc_bcast_station(priv); /* Unblock any waiting calls */ wake_up_interruptible_all(&priv->wait_command_queue); @@ -2550,6 +2551,10 @@ static int __iwl_up(struct iwl_priv *priv) return -EIO; } + ret = iwl_alloc_bcast_station(priv, true); + if (ret) + return ret; + iwl_prepare_card_hw(priv); if (!priv->hw_ready) { @@ -3032,7 +3037,6 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv); - iwl_add_bcast_station(priv); } iwl_send_beacon_cmd(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d7a36205f0e1..f007b36ec54e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2042,11 +2042,6 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) if (err) goto out_err; - /* Add the broadcast address so we can send broadcast frames */ - err = priv->cfg->ops->lib->add_bcast_station(priv); - if (err) - goto out_err; - goto out; out_err: @@ -2069,8 +2064,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); - iwl_clear_ucode_stations(priv, true); - if (iwl_is_ready_rf(priv)) { iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 1774ce9186eb..d80aa6c8d785 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -191,7 +191,6 @@ struct iwl_lib_ops { /* temperature */ struct iwl_temp_ops temp_ops; /* station management */ - int (*add_bcast_station)(struct iwl_priv *priv); int (*manage_ibss_station)(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add); /* recover from tx queue stall */ diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 5bf82b9b523b..7e51647cf02d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -656,63 +656,27 @@ out: EXPORT_SYMBOL_GPL(iwl_remove_station); /** - * iwl_clear_ucode_stations() - clear entire station table driver and/or ucode - * @priv: - * @force: If set then the uCode station table needs to be cleared here. If - * not set then the uCode station table has already been cleared, - * for example after sending it a RXON command without ASSOC bit - * set, and we just need to change driver state here. + * iwl_clear_ucode_stations - clear ucode station table bits + * + * This function clears all the bits in the driver indicating + * which stations are active in the ucode. Call when something + * other than explicit station management would cause this in + * the ucode, e.g. unassociated RXON. */ -void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force) +void iwl_clear_ucode_stations(struct iwl_priv *priv) { int i; unsigned long flags_spin; bool cleared = false; - IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver%s\n", - force ? " and ucode" : ""); - - if (force) { - if (!iwl_is_ready(priv)) { - /* - * If device is not ready at this point the station - * table is likely already empty (uCode not ready - * to receive station requests) or will soon be - * due to interface going down. - */ - IWL_DEBUG_INFO(priv, "Unable to remove stations from device - device not ready\n"); - } else { - iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL); - } - } + IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n"); spin_lock_irqsave(&priv->sta_lock, flags_spin); - if (force) { - IWL_DEBUG_INFO(priv, "Clearing all station information in driver\n"); - /* - * The station entry contains a link to the LQ command. For - * all stations managed by mac80211 this memory will be - * managed by it also. For local stations (broadcast and - * bssid station when in adhoc mode) we need to maintain - * this lq command separately. This memory is created when - * these stations are added. - */ - for (i = 0; i < priv->hw_params.max_stations; i++) { - if (priv->stations[i].used & IWL_STA_LOCAL) { - kfree(priv->stations[i].lq); - priv->stations[i].lq = NULL; - } - } - priv->num_stations = 0; - memset(priv->stations, 0, sizeof(priv->stations)); - cleared = true; - } else { - for (i = 0; i < priv->hw_params.max_stations; i++) { - if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { - IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i); - priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; - cleared = true; - } + for (i = 0; i < priv->hw_params.max_stations; i++) { + if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { + IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i); + priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; + cleared = true; } } spin_unlock_irqrestore(&priv->sta_lock, flags_spin); @@ -1251,34 +1215,67 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, EXPORT_SYMBOL(iwl_send_lq_cmd); /** - * iwl_add_bcast_station - add broadcast station into station table. + * iwl_alloc_bcast_station - add broadcast station into driver's station table. + * + * This adds the broadcast station into the driver's station table + * and marks it driver active, so that it will be restored to the + * device at the next best time. */ -int iwl_add_bcast_station(struct iwl_priv *priv) +int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq) { - IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); - return iwl_add_local_station(priv, iwl_bcast_addr, true); + struct iwl_link_quality_cmd *link_cmd; + unsigned long flags; + u8 sta_id; + + spin_lock_irqsave(&priv->sta_lock, flags); + sta_id = iwl_prep_station(priv, iwl_bcast_addr, false, NULL); + if (sta_id == IWL_INVALID_STATION) { + IWL_ERR(priv, "Unable to prepare broadcast station\n"); + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return -EINVAL; + } + + priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; + priv->stations[sta_id].used |= IWL_STA_BCAST; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + if (init_lq) { + link_cmd = iwl_sta_alloc_lq(priv, sta_id); + if (!link_cmd) { + IWL_ERR(priv, + "Unable to initialize rate scaling for bcast station.\n"); + return -ENOMEM; + } + + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].lq = link_cmd; + spin_unlock_irqrestore(&priv->sta_lock, flags); + } + + return 0; } -EXPORT_SYMBOL(iwl_add_bcast_station); +EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station); -/** - * iwl3945_add_bcast_station - add broadcast station into station table. - */ -int iwl3945_add_bcast_station(struct iwl_priv *priv) +void iwl_dealloc_bcast_station(struct iwl_priv *priv) { - int ret; - - IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); - ret = iwl_add_local_station(priv, iwl_bcast_addr, false); - /* - * It is assumed that when station is added more initialization - * needs to be done, but for 3945 it is not the case and we can - * just release station table access right here. - */ - priv->stations[priv->hw_params.bcast_sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; - return ret; + unsigned long flags; + int i; + spin_lock_irqsave(&priv->sta_lock, flags); + for (i = 0; i < priv->hw_params.max_stations; i++) { + if (!(priv->stations[i].used & IWL_STA_BCAST)) + continue; + + priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; + priv->num_stations--; + BUG_ON(priv->num_stations < 0); + kfree(priv->stations[i].lq); + priv->stations[i].lq = NULL; + } + spin_unlock_irqrestore(&priv->sta_lock, flags); } -EXPORT_SYMBOL(iwl3945_add_bcast_station); +EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station); /** * iwl_get_sta_id - Find station's index within station table diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 1a0e590a824d..50c9d5138a4b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -36,9 +36,9 @@ #define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */ #define IWL_STA_UCODE_INPROGRESS BIT(2) /* ucode entry is in process of being activated */ -#define IWL_STA_LOCAL BIT(3) /* station state not directed by mac80211 - this is for bcast and bssid (when adhoc) - stations */ +#define IWL_STA_LOCAL BIT(3) /* station state not directed by mac80211; + (this is for the IBSS BSSID stations) */ +#define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */ /** @@ -60,10 +60,10 @@ void iwl_update_tkip_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, const u8 *addr, u32 iv32, u16 *phase1key); -int iwl_add_bcast_station(struct iwl_priv *priv); -int iwl3945_add_bcast_station(struct iwl_priv *priv); void iwl_restore_stations(struct iwl_priv *priv); -void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force); +void iwl_clear_ucode_stations(struct iwl_priv *priv); +int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq); +void iwl_dealloc_bcast_station(struct iwl_priv *priv); int iwl_get_free_ucode_key_index(struct iwl_priv *priv); int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); int iwl_send_add_sta(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 85a46ad667de..1a445711e34a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2583,7 +2583,8 @@ static void __iwl3945_down(struct iwl_priv *priv) set_bit(STATUS_EXIT_PENDING, &priv->status); /* Station information will now be cleared in device */ - iwl_clear_ucode_stations(priv, true); + iwl_clear_ucode_stations(priv); + iwl_dealloc_bcast_station(priv); /* Unblock any waiting calls */ wake_up_interruptible_all(&priv->wait_command_queue); @@ -2664,6 +2665,10 @@ static int __iwl3945_up(struct iwl_priv *priv) { int rc, i; + rc = iwl_alloc_bcast_station(priv, false); + if (rc) + return rc; + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); return -EIO; @@ -3302,7 +3307,6 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv); - iwl3945_add_bcast_station(priv); } iwl3945_send_beacon_cmd(priv); -- cgit v1.2.3 From 3bce6066263efb5733ee2141ac8b56684fb3b0a7 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Tue, 13 Apr 2010 16:11:19 -0700 Subject: iwlagn: work around rate scaling reset delay When station is using an HT channel to communicate to AP and communication is lost then driver will first be notified that channel is not an HT channel anymore before AP station is removed. A consequence of that is that the driver will know that it is not communicating on HT anymore, but the rate scaling table is still under the impression it is operating in HT. Any time after driver has been notified channel is not HT anymore there will thus be a firmware SYSASSERT when the current active LQ command is sent. A workaround for this issue is to not send a LQ command in the short time between being notified channel is not HT anymore and rate scaling table being updated. This fixes http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2173 Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-sta.c | 38 +++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 7e51647cf02d..e95282b93c3a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1169,6 +1169,39 @@ static inline void iwl_dump_lq_cmd(struct iwl_priv *priv, } #endif +/** + * is_lq_table_valid() - Test one aspect of LQ cmd for validity + * + * It sometimes happens when a HT rate has been in use and we + * loose connectivity with AP then mac80211 will first tell us that the + * current channel is not HT anymore before removing the station. In such a + * scenario the RXON flags will be updated to indicate we are not + * communicating HT anymore, but the LQ command may still contain HT rates. + * Test for this to prevent driver from sending LQ command between the time + * RXON flags are updated and when LQ command is updated. + */ +static bool is_lq_table_valid(struct iwl_priv *priv, + struct iwl_link_quality_cmd *lq) +{ + int i; + struct iwl_ht_config *ht_conf = &priv->current_ht_config; + + if (ht_conf->is_ht) + return true; + + IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n", + priv->active_rxon.channel); + for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { + if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) { + IWL_DEBUG_INFO(priv, + "index %d of LQ expects HT channel\n", + i); + return false; + } + } + return true; +} + /** * iwl_send_lq_cmd() - Send link quality command * @init: This command is sent as part of station initialization right @@ -1198,7 +1231,10 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, iwl_dump_lq_cmd(priv, lq); BUG_ON(init && (cmd.flags & CMD_ASYNC)); - ret = iwl_send_cmd(priv, &cmd); + if (is_lq_table_valid(priv, lq)) + ret = iwl_send_cmd(priv, &cmd); + else + ret = -EINVAL; if (cmd.flags & CMD_ASYNC) return ret; -- cgit v1.2.3 From 470356b891f1d18e87d5fdc393976fab6d0a978d Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 30 Apr 2010 11:35:15 -0700 Subject: iwlwifi: "tx power per chain" are part of ucode_tx_stats Move "tx power per chain" into ucode_tx_stats, it is debugging information provided by uCode as part of statistics notification. The "tx power per chain" parameters are optional parameters which only supported by 6000 series device today; those are reserved fields for all the other devices. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c | 16 ++++++++++ drivers/net/wireless/iwlwifi/iwl-commands.h | 5 +++ drivers/net/wireless/iwlwifi/iwl-debugfs.c | 42 -------------------------- 3 files changed, 21 insertions(+), 42 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index f249b706bf17..48c023b4ca36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c @@ -709,6 +709,22 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, delta_tx->agg.rx_ba_rsp_cnt, max_tx->agg.rx_ba_rsp_cnt); + if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { + pos += scnprintf(buf + pos, bufsz - pos, + "tx power: (1/2 dB step)\n"); + if ((priv->cfg->valid_tx_ant & ANT_A) && tx->tx_power.ant_a) + pos += scnprintf(buf + pos, bufsz - pos, + "\tantenna A: 0x%X\n", + tx->tx_power.ant_a); + if ((priv->cfg->valid_tx_ant & ANT_B) && tx->tx_power.ant_b) + pos += scnprintf(buf + pos, bufsz - pos, + "\tantenna B: 0x%X\n", + tx->tx_power.ant_b); + if ((priv->cfg->valid_tx_ant & ANT_C) && tx->tx_power.ant_c) + pos += scnprintf(buf + pos, bufsz - pos, + "\tantenna C: 0x%X\n", + tx->tx_power.ant_c); + } ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 449d41f058b8..9aab020c474b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -3127,6 +3127,11 @@ struct statistics_tx { __le32 cts_timeout_collision; __le32 ack_or_ba_timeout_collision; struct statistics_tx_non_phy_agg agg; + /* + * "tx_power" are optional parameters provided by uCode, + * 6000 series is the only device provide the information, + * Those are reserved fields for all the other devices + */ struct statistics_tx_power tx_power; __le32 reserved1; } __attribute__ ((packed)); diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 06905bb9238d..4d6de2dfedd1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1214,46 +1214,6 @@ static ssize_t iwl_dbgfs_chain_noise_read(struct file *file, return ret; } -static ssize_t iwl_dbgfs_chain_tx_power_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - - struct iwl_priv *priv = file->private_data; - char buf[128]; - int pos = 0; - const size_t bufsz = sizeof(buf); - struct statistics_tx *tx; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - else { - tx = &priv->statistics.tx; - if (tx->tx_power.ant_a || - tx->tx_power.ant_b || - tx->tx_power.ant_c) { - pos += scnprintf(buf + pos, bufsz - pos, - "tx power: (1/2 dB step)\n"); - if ((priv->cfg->valid_tx_ant & ANT_A) && - tx->tx_power.ant_a) - pos += scnprintf(buf + pos, bufsz - pos, - "\tantenna A: 0x%X\n", - tx->tx_power.ant_a); - if ((priv->cfg->valid_tx_ant & ANT_B) && - tx->tx_power.ant_b) - pos += scnprintf(buf + pos, bufsz - pos, - "\tantenna B: 0x%X\n", - tx->tx_power.ant_b); - if ((priv->cfg->valid_tx_ant & ANT_C) && - tx->tx_power.ant_c) - pos += scnprintf(buf + pos, bufsz - pos, - "\tantenna C: 0x%X\n", - tx->tx_power.ant_c); - } else - pos += scnprintf(buf + pos, bufsz - pos, "N/A\n"); - } - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -1565,7 +1525,6 @@ DEBUGFS_READ_FILE_OPS(ucode_tx_stats); DEBUGFS_READ_FILE_OPS(ucode_general_stats); DEBUGFS_READ_FILE_OPS(sensitivity); DEBUGFS_READ_FILE_OPS(chain_noise); -DEBUGFS_READ_FILE_OPS(chain_tx_power); DEBUGFS_READ_FILE_OPS(power_save_status); DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); @@ -1624,7 +1583,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); - DEBUGFS_ADD_FILE(chain_tx_power, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); -- cgit v1.2.3 From 4ff739747de20506e478269221f22f3d8d24c706 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 30 Apr 2010 11:35:16 -0700 Subject: iwlwifi: provide more comments for cfg structure Provide comments for newly added cfg parameters Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index d80aa6c8d785..7e5a5ba41fd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -247,6 +247,18 @@ struct iwl_mod_params { * @support_wimax_coexist: support wimax/wifi co-exist * @plcp_delta_threshold: plcp error rate threshold used to trigger * radio tuning when there is a high receiving plcp error rate + * @chain_noise_scale: default chain noise scale used for gain computation + * @monitor_recover_period: default timer used to check stuck queues + * @temperature_kelvin: temperature report by uCode in kelvin + * @max_event_log_size: size of event log buffer size for ucode event logging + * @tx_power_by_driver: tx power calibration performed by driver + * instead of uCode + * @ucode_tracing: support ucode continuous tracing + * @sensitivity_calib_by_driver: driver has the capability to perform + * sensitivity calibration operation + * @chain_noise_calib_by_driver: driver has the capability to perform + * chain noise calibration operation + * @scan_antennas: available antenna for scan operation * * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the -- cgit v1.2.3 From fd1af15d0a82ae681ecf34192150e27455c9c494 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Apr 2010 11:30:43 -0700 Subject: iwlwifi: track station IDs mac80211 allows us to store private data per station, so put the station ID there. This allows us to avoid the station ID lookup when removing regular stations. To also be able to avoid the lookup to remove the special IBSS BSSID station, track its ID in the per-vif private data. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945.c | 16 ++++---- drivers/net/wireless/iwlwifi/iwl-3945.h | 5 +++ drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 8 +++- drivers/net/wireless/iwlwifi/iwl-agn.c | 8 +++- drivers/net/wireless/iwlwifi/iwl-dev.h | 18 +++++++++ drivers/net/wireless/iwlwifi/iwl-sta.c | 61 +++++++++++++---------------- drivers/net/wireless/iwlwifi/iwl-sta.h | 6 ++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 12 +++--- 8 files changed, 82 insertions(+), 52 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 7fb159565f68..306e23aee1ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2461,28 +2461,26 @@ static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) static int iwl3945_manage_ibss_station(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add) { + struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; int ret; - /* - * NB: this assumes that the station it gets will be - * IWL_STA_ID, which will happen but isn't obvious. - */ - if (add) { - ret = iwl_add_local_station(priv, vif->bss_conf.bssid, false); + ret = iwl_add_local_station(priv, vif->bss_conf.bssid, false, + &vif_priv->ibss_bssid_sta_id); if (ret) return ret; - iwl3945_sync_sta(priv, IWL_STA_ID, + iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id, (priv->band == IEEE80211_BAND_5GHZ) ? IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, CMD_ASYNC); - iwl3945_rate_scale_init(priv->hw, IWL_STA_ID); + iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id); return 0; } - return iwl_remove_station(priv, vif->bss_conf.bssid); + return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, + vif->bss_conf.bssid); } /** diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 8fe24eee1c56..bb2aeebf3652 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -106,7 +106,12 @@ struct iwl3945_rs_sta { }; +/* + * The common struct MUST be first because it is shared between + * 3945 and agn! + */ struct iwl3945_sta_priv { + struct iwl_station_priv_common common; struct iwl3945_rs_sta rs_sta; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index f05e6002a04e..81de88ef745e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1520,7 +1520,11 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) int iwlagn_manage_ibss_station(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add) { + struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; + if (add) - return iwl_add_local_station(priv, vif->bss_conf.bssid, true); - return iwl_remove_station(priv, vif->bss_conf.bssid); + return iwl_add_local_station(priv, vif->bss_conf.bssid, true, + &vif_priv->ibss_bssid_sta_id); + return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, + vif->bss_conf.bssid); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 0c913ea71f1e..b2c5665c516e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2854,6 +2854,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, IEEE80211_HW_SUPPORTS_STATIC_SMPS; hw->sta_data_size = sizeof(struct iwl_station_priv); + hw->vif_data_size = sizeof(struct iwl_vif_priv); + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); @@ -3229,6 +3231,8 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, int ret; u8 sta_id; + sta_priv->common.sta_id = IWL_INVALID_STATION; + IWL_DEBUG_INFO(priv, "received request to add station %pM\n", sta->addr); @@ -3245,12 +3249,14 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, return ret; } + sta_priv->common.sta_id = sta_id; + /* Initialize rate scaling */ IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", sta->addr); iwl_rs_rate_init(priv, sta, sta_id); - return ret; + return 0; } /***************************************************************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 46571f7f7abf..f3f3473c5c7e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -497,20 +497,38 @@ struct iwl_station_entry { struct iwl_link_quality_cmd *lq; }; +struct iwl_station_priv_common { + u8 sta_id; +}; + /* * iwl_station_priv: Driver's private station information * * When mac80211 creates a station it reserves some space (hw->sta_data_size) * in the structure for use by driver. This structure is places in that * space. + * + * The common struct MUST be first because it is shared between + * 3945 and agn! */ struct iwl_station_priv { + struct iwl_station_priv_common common; struct iwl_lq_sta lq_sta; atomic_t pending_frames; bool client; bool asleep; }; +/** + * struct iwl_vif_priv - driver's private per-interface information + * + * When mac80211 allocates a virtual interface, it can allocate + * space for us to put data into. + */ +struct iwl_vif_priv { + u8 ibss_bssid_sta_id; +}; + /* one for each uCode image (inst/data, boot/init/runtime) */ struct fw_desc { void *v_addr; /* access by driver */ diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index e95282b93c3a..d1986dedc863 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -462,26 +462,33 @@ static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv, } /* - * iwl_add_local_stations - Add stations not requested by mac80211 + * iwl_add_local_station - Add stations not requested by mac80211 * * This will be either the broadcast station or the bssid station needed by * ad-hoc. * * Function sleeps. */ -int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs) +int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, + u8 *sta_id_r) { int ret; u8 sta_id; struct iwl_link_quality_cmd *link_cmd; unsigned long flags; + if (*sta_id_r) + *sta_id_r = IWL_INVALID_STATION; + ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); if (ret) { IWL_ERR(priv, "Unable to add station %pM\n", addr); return ret; } + if (sta_id_r) + *sta_id_r = sta_id; + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].used |= IWL_STA_LOCAL; spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -582,13 +589,11 @@ static int iwl_send_remove_station(struct iwl_priv *priv, /** * iwl_remove_station - Remove driver's knowledge of station. */ -int iwl_remove_station(struct iwl_priv *priv, const u8 *addr) +int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, + const u8 *addr) { - int sta_id = IWL_INVALID_STATION; - int i, ret = -EINVAL; - unsigned long flags; - bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; struct iwl_station_entry *station; + unsigned long flags; if (!iwl_is_ready(priv)) { IWL_DEBUG_INFO(priv, @@ -602,35 +607,24 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr) return 0; } - spin_lock_irqsave(&priv->sta_lock, flags); - - if (is_ap) - sta_id = IWL_AP_ID; - else - for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) - if (priv->stations[i].used && - !compare_ether_addr(priv->stations[i].sta.sta.addr, - addr)) { - sta_id = i; - break; - } + IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", + sta_id, addr); - if (unlikely(sta_id == IWL_INVALID_STATION)) - goto out; + if (WARN_ON(sta_id == IWL_INVALID_STATION)) + return -EINVAL; - IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", - sta_id, addr); + spin_lock_irqsave(&priv->sta_lock, flags); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", addr); - goto out; + goto out_err; } if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n", addr); - goto out; + goto out_err; } if (priv->stations[sta_id].used & IWL_STA_LOCAL) { @@ -647,11 +641,10 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr) station = &priv->stations[sta_id]; spin_unlock_irqrestore(&priv->sta_lock, flags); - ret = iwl_send_remove_station(priv, station); - return ret; -out: + return iwl_send_remove_station(priv, station); +out_err: spin_unlock_irqrestore(&priv->sta_lock, flags); - return ret; + return -EINVAL; } EXPORT_SYMBOL_GPL(iwl_remove_station); @@ -1467,14 +1460,16 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); int iwl_mac_sta_remove(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { - int ret; struct iwl_priv *priv = hw->priv; + struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv; + int ret; + IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", sta->addr); - ret = iwl_remove_station(priv, sta->addr); + ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr); if (ret) IWL_ERR(priv, "Error removing station %pM\n", sta->addr); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 50c9d5138a4b..8efb83d6cf5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -68,12 +68,14 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv); int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_addsta_cmd *sta, u8 flags); -int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs); +int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, + u8 *sta_id_r); int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, bool is_ap, struct ieee80211_sta_ht_cap *ht_info, u8 *sta_id_r); -int iwl_remove_station(struct iwl_priv *priv, const u8 *addr); +int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, + const u8 *addr); int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 1a445711e34a..48fb59bbfbd9 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3378,10 +3378,13 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct iwl_priv *priv = hw->priv; + struct iwl3945_sta_priv *sta_priv = (void *)sta->drv_priv; int ret; - bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; + bool is_ap = vif->type == NL80211_IFTYPE_STATION; u8 sta_id; + sta_priv->common.sta_id = IWL_INVALID_STATION; + IWL_DEBUG_INFO(priv, "received request to add station %pM\n", sta->addr); @@ -3394,16 +3397,14 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, return ret; } + sta_priv->common.sta_id = sta_id; + /* Initialize rate scaling */ IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", sta->addr); iwl3945_rs_rate_init(priv, sta, sta_id); return 0; - - - - return ret; } /***************************************************************************** * @@ -3887,6 +3888,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) hw->rate_control_algorithm = "iwl-3945-rs"; hw->sta_data_size = sizeof(struct iwl3945_sta_priv); + hw->vif_data_size = sizeof(struct iwl_vif_priv); /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | -- cgit v1.2.3 From 64ba9a54c60990416c4098c63792c37d8fccb9e1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Apr 2010 11:30:44 -0700 Subject: iwlwifi: add iwl_sta_id() In places where the station struct is guaranteed to exist (presumably), use this helper to get the station ID out of it (and warn if there's no station struct after all). Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-sta.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 8efb83d6cf5c..7229e2c0f770 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -84,4 +84,12 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid); void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id); void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt); + +static inline int iwl_sta_id(struct ieee80211_sta *sta) +{ + if (WARN_ON(!sta)) + return IWL_INVALID_STATION; + + return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id; +} #endif /* __iwl_sta_h__ */ -- cgit v1.2.3 From 2a87c26bbe9587baeb9e56d3ce0b4971bd777643 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Apr 2010 11:30:45 -0700 Subject: iwlwifi: use iwl_find_station less Since we now store the station ID in each station struct, many places need not look at the station table any more since they can just pull the station ID out of the struct. Remove iwl_get_sta_id() and use iwl_sta_id() instead as appropriate. This reduces the amount of code needed to find the right station significantly, and works since mac80211 passes the station only after it has been fully initialised, ie. even if TX races with station addition it will only be passed to TX once the addition is complete. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 6 ++-- drivers/net/wireless/iwlwifi/iwl-agn.c | 19 +++++----- drivers/net/wireless/iwlwifi/iwl-sta.c | 56 ----------------------------- drivers/net/wireless/iwlwifi/iwl-sta.h | 3 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 23 ++++++------ 5 files changed, 29 insertions(+), 78 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 6a306e849584..89c85d1043ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -566,11 +566,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) hdr_len = ieee80211_hdrlen(fc); - /* Find (or create) index into station table for destination station */ - if (info->flags & IEEE80211_TX_CTL_INJECTED) + /* Find index into station table for destination station */ + if (!info->control.sta) sta_id = priv->hw_params.bcast_sta_id; else - sta_id = iwl_get_sta_id(priv, hdr); + sta_id = iwl_sta_id(info->control.sta); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b2c5665c516e..8a4b83073540 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3070,7 +3070,6 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key) { struct iwl_priv *priv = hw->priv; - const u8 *addr; int ret; u8 sta_id; bool is_default_wep_key = false; @@ -3081,13 +3080,17 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); return -EOPNOTSUPP; } - addr = sta ? sta->addr : iwl_bcast_addr; - sta_id = iwl_find_station(priv, addr); - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", - addr); - return -EINVAL; + if (sta) { + sta_id = iwl_sta_id(sta); + + if (sta_id == IWL_INVALID_STATION) { + IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", + sta->addr); + return -EINVAL; + } + } else { + sta_id = priv->hw_params.bcast_sta_id; } mutex_lock(&priv->mutex); @@ -3212,7 +3215,7 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, if (!sta_priv->asleep) break; sta_priv->asleep = false; - sta_id = iwl_find_station(priv, sta->addr); + sta_id = iwl_sta_id(sta); if (sta_id != IWL_INVALID_STATION) iwl_sta_modify_ps_wake(priv, sta_id); break; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index d1986dedc863..4be7940ad566 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1306,62 +1306,6 @@ void iwl_dealloc_bcast_station(struct iwl_priv *priv) } EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station); -/** - * iwl_get_sta_id - Find station's index within station table - * - * If new IBSS station, create new entry in station table - */ -int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) -{ - int sta_id; - __le16 fc = hdr->frame_control; - - /* If this frame is broadcast or management, use broadcast station id */ - if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) - return priv->hw_params.bcast_sta_id; - - switch (priv->iw_mode) { - - /* If we are a client station in a BSS network, use the special - * AP station entry (that's the only station we communicate with) */ - case NL80211_IFTYPE_STATION: - /* - * If addition of station not complete yet, which means - * that rate scaling has not been initialized, then return - * the broadcast station. - */ - if (!(priv->stations[IWL_AP_ID].used & IWL_STA_UCODE_ACTIVE)) - return priv->hw_params.bcast_sta_id; - return IWL_AP_ID; - - /* If we are an AP, then find the station, or use BCAST */ - case NL80211_IFTYPE_AP: - sta_id = iwl_find_station(priv, hdr->addr1); - if (sta_id != IWL_INVALID_STATION) - return sta_id; - return priv->hw_params.bcast_sta_id; - - /* If this frame is going out to an IBSS network, find the station, - * or create a new station table entry */ - case NL80211_IFTYPE_ADHOC: - sta_id = iwl_find_station(priv, hdr->addr1); - if (sta_id != IWL_INVALID_STATION) - return sta_id; - - IWL_DEBUG_DROP(priv, "Station %pM not in station map. " - "Defaulting to broadcast...\n", - hdr->addr1); - iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); - return priv->hw_params.bcast_sta_id; - - default: - IWL_WARN(priv, "Unknown mode of operation: %d\n", - priv->iw_mode); - return priv->hw_params.bcast_sta_id; - } -} -EXPORT_SYMBOL(iwl_get_sta_id); - /** * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table */ diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 7229e2c0f770..646f644974ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -29,6 +29,8 @@ #ifndef __iwl_sta_h__ #define __iwl_sta_h__ +#include "iwl-dev.h" + #define HW_KEY_DYNAMIC 0 #define HW_KEY_DEFAULT 1 @@ -65,7 +67,6 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv); int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq); void iwl_dealloc_bcast_station(struct iwl_priv *priv); int iwl_get_free_ucode_key_index(struct iwl_priv *priv); -int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_addsta_cmd *sta, u8 flags); int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 48fb59bbfbd9..4916f2365501 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -508,11 +508,11 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) hdr_len = ieee80211_hdrlen(fc); - /* Find (or create) index into station table for destination station */ - if (info->flags & IEEE80211_TX_CTL_INJECTED) + /* Find index into station table for destination station */ + if (!info->control.sta) sta_id = priv->hw_params.bcast_sta_id; else - sta_id = iwl_get_sta_id(priv, hdr); + sta_id = iwl_sta_id(info->control.sta); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); @@ -3321,7 +3321,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key) { struct iwl_priv *priv = hw->priv; - const u8 *addr; int ret = 0; u8 sta_id = IWL_INVALID_STATION; u8 static_key; @@ -3333,15 +3332,19 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - addr = sta ? sta->addr : iwl_bcast_addr; static_key = !iwl_is_associated(priv); if (!static_key) { - sta_id = iwl_find_station(priv, addr); - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", - addr); - return -EINVAL; + if (!sta) { + sta_id = priv->hw_params.bcast_sta_id; + } else { + sta_id = iwl_sta_id(sta); + if (sta_id == IWL_INVALID_STATION) { + IWL_DEBUG_MAC80211(priv, + "leave - %pM not in station map.\n", + sta->addr); + return -EINVAL; + } } } -- cgit v1.2.3 From 619753ff57a2e15b58546b856536928d1a3daef9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Apr 2010 11:30:46 -0700 Subject: iwlagn: use iwl_sta_id() for aggregation With the station ID being stored in the station struct, which mac80211 gives us for aggregation callbacks, we can also remove the use of iwl_find_station() in those code paths. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 21 ++++++++------------- drivers/net/wireless/iwlwifi/iwl-agn.c | 8 ++++---- drivers/net/wireless/iwlwifi/iwl-agn.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-sta.c | 13 +++++++------ drivers/net/wireless/iwlwifi/iwl-sta.h | 7 ++++--- 5 files changed, 25 insertions(+), 28 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 89c85d1043ba..c402bfc83f36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -962,7 +962,7 @@ static int iwlagn_txq_ctx_activate_free(struct iwl_priv *priv) } int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, - const u8 *ra, u16 tid, u16 *ssn) + struct ieee80211_sta *sta, u16 tid, u16 *ssn) { int sta_id; int tx_fifo; @@ -976,9 +976,9 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, return tx_fifo; IWL_WARN(priv, "%s on ra = %pM tid = %d\n", - __func__, ra, tid); + __func__, sta->addr, tid); - sta_id = iwl_find_station(priv, ra); + sta_id = iwl_sta_id(sta); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Start AGG on invalid station\n"); return -ENXIO; @@ -1012,7 +1012,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, if (tid_data->tfds_in_queue == 0) { IWL_DEBUG_HT(priv, "HW queue is empty\n"); tid_data->agg.state = IWL_AGG_ON; - ieee80211_start_tx_ba_cb_irqsafe(vif, ra, tid); + ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); } else { IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", tid_data->tfds_in_queue); @@ -1022,23 +1022,18 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, } int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, - const u8 *ra, u16 tid) + struct ieee80211_sta *sta, u16 tid) { int tx_fifo_id, txq_id, sta_id, ssn = -1; struct iwl_tid_data *tid_data; int write_ptr, read_ptr; unsigned long flags; - if (!ra) { - IWL_ERR(priv, "ra = NULL\n"); - return -EINVAL; - } - tx_fifo_id = get_fifo_from_tid(tid); if (unlikely(tx_fifo_id < 0)) return tx_fifo_id; - sta_id = iwl_find_station(priv, ra); + sta_id = iwl_sta_id(sta); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); @@ -1048,7 +1043,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, if (priv->stations[sta_id].tid[tid].agg.state == IWL_EMPTYING_HW_QUEUE_ADDBA) { IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); - ieee80211_stop_tx_ba_cb_irqsafe(vif, ra, tid); + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; return 0; } @@ -1085,7 +1080,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, tx_fifo_id); spin_unlock_irqrestore(&priv->lock, flags); - ieee80211_stop_tx_ba_cb_irqsafe(vif, ra, tid); + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8a4b83073540..3265b637db2e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3154,17 +3154,17 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: IWL_DEBUG_HT(priv, "start Rx\n"); - return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn); + return iwl_sta_rx_agg_start(priv, sta, tid, *ssn); case IEEE80211_AMPDU_RX_STOP: IWL_DEBUG_HT(priv, "stop Rx\n"); - ret = iwl_sta_rx_agg_stop(priv, sta->addr, tid); + ret = iwl_sta_rx_agg_stop(priv, sta, tid); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return 0; else return ret; case IEEE80211_AMPDU_TX_START: IWL_DEBUG_HT(priv, "start Tx\n"); - ret = iwlagn_tx_agg_start(priv, vif, sta->addr, tid, ssn); + ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); if (ret == 0) { priv->_agn.agg_tids_count++; IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", @@ -3173,7 +3173,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return ret; case IEEE80211_AMPDU_TX_STOP: IWL_DEBUG_HT(priv, "stop Tx\n"); - ret = iwlagn_tx_agg_stop(priv, vif, sta->addr, tid); + ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { priv->_agn.agg_tids_count--; IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index c4417739a64c..2d748053358e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -136,9 +136,9 @@ void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, struct ieee80211_tx_info *info); int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, - const u8 *ra, u16 tid, u16 *ssn); + struct ieee80211_sta *sta, u16 tid, u16 *ssn); int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, - const u8 *ra, u16 tid); + struct ieee80211_sta *sta, u16 tid); int iwlagn_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 4be7940ad566..8fec0263f016 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1324,13 +1324,13 @@ void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) } EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); -int iwl_sta_rx_agg_start(struct iwl_priv *priv, - const u8 *addr, int tid, u16 ssn) +int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, + int tid, u16 ssn) { unsigned long flags; int sta_id; - sta_id = iwl_find_station(priv, addr); + sta_id = iwl_sta_id(sta); if (sta_id == IWL_INVALID_STATION) return -ENXIO; @@ -1343,16 +1343,17 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, spin_unlock_irqrestore(&priv->sta_lock, flags); return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, - CMD_ASYNC); + CMD_ASYNC); } EXPORT_SYMBOL(iwl_sta_rx_agg_start); -int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid) +int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, + int tid) { unsigned long flags; int sta_id; - sta_id = iwl_find_station(priv, addr); + sta_id = iwl_sta_id(sta); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); return -ENXIO; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 646f644974ca..d0ab3f8f7c0f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -80,9 +80,10 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); -int iwl_sta_rx_agg_start(struct iwl_priv *priv, - const u8 *addr, int tid, u16 ssn); -int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid); +int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, + int tid, u16 ssn); +int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, + int tid); void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id); void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt); -- cgit v1.2.3 From bdbb612fb2c49111d393a69a08b0328e51913c17 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Apr 2010 13:53:37 -0700 Subject: iwlwifi: use iwl_sta_id() for TKIP key update With the station ID being stored in the station struct, which mac80211 gives us for TKIP phase 1 key updates, we can also remove the use of iwl_find_station() in that code path. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-sta.c | 21 +++++++++++++-------- drivers/net/wireless/iwlwifi/iwl-sta.h | 2 +- 3 files changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3265b637db2e..dd26965e75f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3057,8 +3057,7 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211(priv, "enter\n"); - iwl_update_tkip_key(priv, keyconf, - sta ? sta->addr : iwl_bcast_addr, + iwl_update_tkip_key(priv, keyconf, sta, iv32, phase1key); IWL_DEBUG_MAC80211(priv, "leave\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 8fec0263f016..b8053e7f16ac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1012,18 +1012,23 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, void iwl_update_tkip_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, - const u8 *addr, u32 iv32, u16 *phase1key) + struct ieee80211_sta *sta, u32 iv32, u16 *phase1key) { - u8 sta_id = IWL_INVALID_STATION; + u8 sta_id; unsigned long flags; int i; - sta_id = iwl_find_station(priv, addr); - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", - addr); - return; - } + if (sta) { + sta_id = iwl_sta_id(sta); + + if (sta_id == IWL_INVALID_STATION) { + IWL_DEBUG_MAC80211(priv, "leave - %pM not initialised.\n", + sta->addr); + return; + } + } else + sta_id = priv->hw_params.bcast_sta_id; + if (iwl_scan_cancel(priv)) { /* cancel scan failed, just live w/ bad key and rely diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index d0ab3f8f7c0f..08d4bc1363f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -60,7 +60,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, struct ieee80211_key_conf *key, u8 sta_id); void iwl_update_tkip_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, - const u8 *addr, u32 iv32, u16 *phase1key); + struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); void iwl_restore_stations(struct iwl_priv *priv); void iwl_clear_ucode_stations(struct iwl_priv *priv); -- cgit v1.2.3 From c1182743b688bce7b0bbd7cff78b049e45672cb5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Apr 2010 11:30:48 -0700 Subject: iwlwifi: move iwl_find_station() to 4965 4965 code is the only thing that now still needs iwl_find_station(), so move it there and make it static. Everything else can rely on the station data passed by mac80211. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-4965.c | 44 ++++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-sta.c | 45 --------------------------------- drivers/net/wireless/iwlwifi/iwl-sta.h | 6 ----- 3 files changed, 44 insertions(+), 51 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 93893aec6cc4..d3afddae8d9f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1953,6 +1953,50 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, return 0; } +static u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) +{ + int i; + int start = 0; + int ret = IWL_INVALID_STATION; + unsigned long flags; + + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) || + (priv->iw_mode == NL80211_IFTYPE_AP)) + start = IWL_STA_ID; + + if (is_broadcast_ether_addr(addr)) + return priv->hw_params.bcast_sta_id; + + spin_lock_irqsave(&priv->sta_lock, flags); + for (i = start; i < priv->hw_params.max_stations; i++) + if (priv->stations[i].used && + (!compare_ether_addr(priv->stations[i].sta.sta.addr, + addr))) { + ret = i; + goto out; + } + + IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n", + addr, priv->num_stations); + + out: + /* + * It may be possible that more commands interacting with stations + * arrive before we completed processing the adding of + * station + */ + if (ret != IWL_INVALID_STATION && + (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) || + ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) && + (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) { + IWL_ERR(priv, "Requested station info for sta %d before ready.\n", + ret); + ret = IWL_INVALID_STATION; + } + spin_unlock_irqrestore(&priv->sta_lock, flags); + return ret; +} + static int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) { if (priv->iw_mode == NL80211_IFTYPE_STATION) { diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index b8053e7f16ac..ba36df5e2c78 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -35,51 +35,6 @@ #include "iwl-core.h" #include "iwl-sta.h" -u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) -{ - int i; - int start = 0; - int ret = IWL_INVALID_STATION; - unsigned long flags; - - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) || - (priv->iw_mode == NL80211_IFTYPE_AP)) - start = IWL_STA_ID; - - if (is_broadcast_ether_addr(addr)) - return priv->hw_params.bcast_sta_id; - - spin_lock_irqsave(&priv->sta_lock, flags); - for (i = start; i < priv->hw_params.max_stations; i++) - if (priv->stations[i].used && - (!compare_ether_addr(priv->stations[i].sta.sta.addr, - addr))) { - ret = i; - goto out; - } - - IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n", - addr, priv->num_stations); - - out: - /* - * It may be possible that more commands interacting with stations - * arrive before we completed processing the adding of - * station - */ - if (ret != IWL_INVALID_STATION && - (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) || - ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) && - (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) { - IWL_ERR(priv, "Requested station info for sta %d before ready.\n", - ret); - ret = IWL_INVALID_STATION; - } - spin_unlock_irqrestore(&priv->sta_lock, flags); - return ret; -} -EXPORT_SYMBOL(iwl_find_station); - /* priv->sta_lock must be held */ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) { diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 08d4bc1363f1..6872bcfe7de1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -43,12 +43,6 @@ #define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */ -/** - * iwl_find_station - Find station id for a given BSSID - * @bssid: MAC address of station ID to find - */ -u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid); - int iwl_remove_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *key); int iwl_set_default_wep_key(struct iwl_priv *priv, -- cgit v1.2.3 From 57f8db89340f6ba5d913a1950b8dad4431d2beda Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Apr 2010 11:30:49 -0700 Subject: iwlwifi: rename iwl_add_local_station This function is now only used for the special IBSS BSSID station, so rename it to indicate this. The new name is iwl_add_bssid_station. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 9 +++------ drivers/net/wireless/iwlwifi/iwl-sta.h | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 306e23aee1ed..0eb0faa9d3cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2465,7 +2465,7 @@ static int iwl3945_manage_ibss_station(struct iwl_priv *priv, int ret; if (add) { - ret = iwl_add_local_station(priv, vif->bss_conf.bssid, false, + ret = iwl_add_bssid_station(priv, vif->bss_conf.bssid, false, &vif_priv->ibss_bssid_sta_id); if (ret) return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 81de88ef745e..637d7b62fb56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1523,7 +1523,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; if (add) - return iwl_add_local_station(priv, vif->bss_conf.bssid, true, + return iwl_add_bssid_station(priv, vif->bss_conf.bssid, true, &vif_priv->ibss_bssid_sta_id); return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, vif->bss_conf.bssid); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index ba36df5e2c78..c15098ed0416 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -417,14 +417,11 @@ static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv, } /* - * iwl_add_local_station - Add stations not requested by mac80211 - * - * This will be either the broadcast station or the bssid station needed by - * ad-hoc. + * iwl_add_bssid_station - Add the special IBSS BSSID station * * Function sleeps. */ -int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, +int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, u8 *sta_id_r) { int ret; @@ -468,7 +465,7 @@ int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, return 0; } -EXPORT_SYMBOL(iwl_add_local_station); +EXPORT_SYMBOL(iwl_add_bssid_station); /** * iwl_sta_ucode_deactivate - deactivate ucode status for a station diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 6872bcfe7de1..64271487daa7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -63,7 +63,7 @@ void iwl_dealloc_bcast_station(struct iwl_priv *priv); int iwl_get_free_ucode_key_index(struct iwl_priv *priv); int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_addsta_cmd *sta, u8 flags); -int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, +int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, u8 *sta_id_r); int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, bool is_ap, -- cgit v1.2.3 From 63d4176933a5c4d9387eb79e1d50a9232e58c06e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Apr 2010 11:30:50 -0700 Subject: iwlwifi: remove pointless HT check Remove the check before invoking iwl_set_ht_add_station(), since neither of the conditions in this check makes sense, as either we pass in a NULL ht_info (first branch) or in the IBSS case an ht_info with ht_enabled=false. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-sta.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index c15098ed0416..85ed235ac901 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -284,10 +284,12 @@ static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr, station->sta.sta.sta_id = sta_id; station->sta.station_flags = 0; - /* BCAST station and IBSS stations do not work in HT mode */ - if (sta_id != priv->hw_params.bcast_sta_id && - priv->iw_mode != NL80211_IFTYPE_ADHOC) - iwl_set_ht_add_station(priv, sta_id, ht_info); + /* + * OK to call unconditionally, since local stations (IBSS BSSID + * STA and broadcast STA) pass in a NULL ht_info, and mac80211 + * doesn't allow HT IBSS. + */ + iwl_set_ht_add_station(priv, sta_id, ht_info); /* 3945 only */ rate = (priv->band == IEEE80211_BAND_5GHZ) ? -- cgit v1.2.3 From db125c787bc2c07ad97ba94707b653885d723a40 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 7 May 2010 01:49:15 -0700 Subject: iwlwifi: clear driver stations when going down During a hw restart, mac80211 will attempt to reconfigure all stations. Currently, that fails and leads to warnings because we still have the stations marked active. Therefore, clear all stations when doing down. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 + drivers/net/wireless/iwlwifi/iwl-sta.h | 19 +++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 + 3 files changed, 21 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index dd26965e75f3..47563cf9cbaa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2405,6 +2405,7 @@ static void __iwl_down(struct iwl_priv *priv) iwl_clear_ucode_stations(priv); iwl_dealloc_bcast_station(priv); + iwl_clear_driver_stations(priv); /* Unblock any waiting calls */ wake_up_interruptible_all(&priv->wait_command_queue); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 64271487daa7..c2a453a1a991 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -81,6 +81,25 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id); void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt); +/** + * iwl_clear_driver_stations - clear knowledge of all stations from driver + * @priv: iwl priv struct + * + * This is called during iwl_down() to make sure that in the case + * we're coming there from a hardware restart mac80211 will be + * able to reconfigure stations -- if we're getting there in the + * normal down flow then the stations will already be cleared. + */ +static inline void iwl_clear_driver_stations(struct iwl_priv *priv) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->sta_lock, flags); + memset(priv->stations, 0, sizeof(priv->stations)); + priv->num_stations = 0; + spin_unlock_irqrestore(&priv->sta_lock, flags); +} + static inline int iwl_sta_id(struct ieee80211_sta *sta) { if (WARN_ON(!sta)) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4916f2365501..4c78783a6035 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2585,6 +2585,7 @@ static void __iwl3945_down(struct iwl_priv *priv) /* Station information will now be cleared in device */ iwl_clear_ucode_stations(priv); iwl_dealloc_bcast_station(priv); + iwl_clear_driver_stations(priv); /* Unblock any waiting calls */ wake_up_interruptible_all(&priv->wait_command_queue); -- cgit v1.2.3 From 5a147e8bf982f9dd414c1dd751fe02c1942506b2 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 3 Mar 2010 17:08:11 +1100 Subject: ar9170: fix for driver-core ABI change Signed-off-by: Stephen Rothwell Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/usb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index c1c7c427501c..c8121a6a9d3a 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include "ar9170.h" #include "cmd.h" @@ -739,10 +740,10 @@ static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) /* unbind anything failed */ if (parent) - down(&parent->sem); + device_lock(parent); device_release_driver(&aru->udev->dev); if (parent) - up(&parent->sem); + device_unlock(parent); } static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) -- cgit v1.2.3 From cdd0864a495a4c6a6f60cae854ca962cfa1f1026 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 8 May 2010 18:25:17 +0200 Subject: wl1271: add missing spin_lock() We should start the loop consistently with the "wl_lock" lock held. Signed-off-by: Dan Carpenter Acked-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 3e4b9fbe8a00..b61cd102752f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -466,6 +466,7 @@ static void wl1271_irq_work(struct work_struct *work) intr = le32_to_cpu(wl->fw_status->intr); if (!intr) { wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); + spin_lock_irqsave(&wl->wl_lock, flags); continue; } -- cgit v1.2.3 From 8607b79c794a706e6df79d44da261887c5f5def2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 8 May 2010 18:25:51 +0200 Subject: wl1271: fix notifier interface supported test The "(wl == NULL)" test doesn't work here because "wl" is always non-null. The intent of the code is to return if the interface was not supported by the driver. Signed-off-by: Dan Carpenter Acked-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b61cd102752f..55aa813c82c7 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -852,7 +852,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, if (wl == wl_temp) break; } - if (wl == NULL) + if (wl != wl_temp) return NOTIFY_DONE; /* Get the interface IP address for the device. "ifa" will become -- cgit v1.2.3 From b1b3751c750277c92684c932b46eeb723babe196 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 8 May 2010 18:26:38 +0200 Subject: wl1271: remove some unneeded code The goto and the break are equivelent. I removed the goto in memory of Edsger Dijkstra who famously hated gotos and who would have been eighty years old next Tuesday. Signed-off-by: Dan Carpenter Acked-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 55aa813c82c7..da40ceec4f8e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1563,8 +1563,6 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, default: wl1271_error("Unsupported key cmd 0x%x", cmd); ret = -EOPNOTSUPP; - goto out_sleep; - break; } -- cgit v1.2.3 From 9637e516d16a58b13f6098cfe899e22963132be3 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 10 May 2010 15:26:27 -0400 Subject: ath5k: drop warning on jumbo frames Jumbo frames are not supported, and if they are seen it is likely a bogus frame so just silently discard them instead of warning on them all time. Also, instead of dropping them immediately though move the check *after* we check for all sort of frame errors. This should enable us to discard these frames if the hardware picks other bogus items first. Lets see if we still get those jumbo counters increasing still with this. Jumbo frames would happen if we tell hardware we can support a small 802.11 chunks of DMA'd frame, hardware would split RX'd frames into parts and we'd have to reconstruct them in software. This is done with USB due to the bulk size but with ath5k we already provide a good limit to hardware and this should not be happening. This is reported quite often and if it fills the logs then this needs to be addressed and to avoid spurious reports. Cc: stable@kernel.org Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index feb7b9ea80ab..febd0367867e 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1931,12 +1931,6 @@ ath5k_tasklet_rx(unsigned long data) sc->stats.rx_all_count++; - if (unlikely(rs.rs_more)) { - ATH5K_WARN(sc, "unsupported jumbo\n"); - sc->stats.rxerr_jumbo++; - goto next; - } - if (unlikely(rs.rs_status)) { if (rs.rs_status & AR5K_RXERR_CRC) sc->stats.rxerr_crc++; @@ -1976,6 +1970,12 @@ ath5k_tasklet_rx(unsigned long data) sc->opmode != NL80211_IFTYPE_MONITOR) goto next; } + + if (unlikely(rs.rs_more)) { + sc->stats.rxerr_jumbo++; + goto next; + + } accept: next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); -- cgit v1.2.3 From 7fca8e26662e83fec0a0c55b9a977fe9e79f01da Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 10 May 2010 21:42:11 -0400 Subject: ath9k_hw: new initialization values for AR9003 These changes include: * For PAPRD, the TXRF3.capdiv5G, TXRF3.rdiv5G and TXRF3.rdiv2G are set to 0x0, the TXRF6.capdiv2G is set to 0x2 for all three chains. * The d2cas5G/d3cas5G/d4cas5G was updated to 4/4/4 in lowest_ob_db Tx gain table. * To improve DPPM, three parameters were updated (Released from Madhan): 1. RANGE_OSDAC is set to 0x1 for 2G, 0x0 for 5G 2. offsetC1 is set to 0xc 3. inv_clk320_adc is set to 0x1 * To reduce PHY error(from spur), cycpwr_thr1 and cycpwr_thr1_ext are increased to 0x8 at 2G. * The 2G Rx gain tables are updated with mixer gain setting 3,1,0. The new checksums yield: initvals -f ar9003 0x00000000c2bfa7d5 ar9300_2p0_radio_postamble 0x00000000ada2b114 ar9300Modes_lowest_ob_db_tx_gain_table_2p0 0x00000000e0bc2c84 ar9300Modes_fast_clock_2p0 0x00000000056eaf74 ar9300_2p0_radio_core 0x0000000000000000 ar9300Common_rx_gain_table_merlin_2p0 0x0000000078658fb5 ar9300_2p0_mac_postamble 0x0000000023235333 ar9300_2p0_soc_postamble 0x0000000054d41904 ar9200_merlin_2p0_radio_core 0x00000000748572cf ar9300_2p0_baseband_postamble 0x000000009aa5a0a4 ar9300_2p0_baseband_core 0x000000003df9a326 ar9300Modes_high_power_tx_gain_table_2p0 0x000000001cfba124 ar9300Modes_high_ob_db_tx_gain_table_2p0 0x0000000011302700 ar9300Common_rx_gain_table_2p0 0x00000000e3eab114 ar9300Modes_low_ob_db_tx_gain_table_2p0 0x00000000c9d66d40 ar9300_2p0_mac_core 0x000000001e1d0800 ar9300Common_wo_xlna_rx_gain_table_2p0 0x00000000a0c54980 ar9300_2p0_soc_preamble 0x00000000292e2544 ar9300PciePhy_pll_on_clkreq_disable_L1_2p0 0x000000002d3e2544 ar9300PciePhy_clkreq_enable_L1_2p0 0x00000000293e2544 ar9300PciePhy_clkreq_disable_L1_2p0 Cc: Don Breslin Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_initvals.h | 268 +++++++++++------------ 1 file changed, 134 insertions(+), 134 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_initvals.h index ef6116e13033..db019dd220b7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_initvals.h @@ -25,8 +25,11 @@ static const u32 ar9300_2p0_radio_postamble[][5] = { {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800}, {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20}, {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, }; static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = { @@ -97,13 +100,13 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = { {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x60001a61, 0x60001a61, 0x60001a61, 0x60001a61}, + {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016448, 0x60001a61, 0x60001a61, 0x60001a61, 0x60001a61}, + {0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016848, 0x60001a61, 0x60001a61, 0x60001a61, 0x60001a61}, + {0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; @@ -129,7 +132,7 @@ static const u32 ar9300_2p0_radio_core[][2] = { {0x00016040, 0x7f80fff8}, {0x0001604c, 0x76d005b5}, {0x00016050, 0x556cf031}, - {0x00016054, 0x43449440}, + {0x00016054, 0x13449440}, {0x00016058, 0x0c51c92c}, {0x0001605c, 0x3db7fffc}, {0x00016060, 0xfffffffc}, @@ -152,12 +155,11 @@ static const u32 ar9300_2p0_radio_core[][2] = { {0x00016100, 0x3fffbe01}, {0x00016104, 0xfff80000}, {0x00016108, 0x00080010}, - {0x00016140, 0x10804008}, {0x00016144, 0x02084080}, {0x00016148, 0x00000000}, {0x00016280, 0x058a0001}, {0x00016284, 0x3d840208}, - {0x00016288, 0x01a20408}, + {0x00016288, 0x05a20408}, {0x0001628c, 0x00038c07}, {0x00016290, 0x40000004}, {0x00016294, 0x458aa14f}, @@ -190,7 +192,7 @@ static const u32 ar9300_2p0_radio_core[][2] = { {0x00016440, 0x7f80fff8}, {0x0001644c, 0x76d005b5}, {0x00016450, 0x556cf031}, - {0x00016454, 0x43449440}, + {0x00016454, 0x13449440}, {0x00016458, 0x0c51c92c}, {0x0001645c, 0x3db7fffc}, {0x00016460, 0xfffffffc}, @@ -199,7 +201,6 @@ static const u32 ar9300_2p0_radio_core[][2] = { {0x00016500, 0x3fffbe01}, {0x00016504, 0xfff80000}, {0x00016508, 0x00080010}, - {0x00016540, 0x10804008}, {0x00016544, 0x02084080}, {0x00016548, 0x00000000}, {0x00016780, 0x00000000}, @@ -231,7 +232,7 @@ static const u32 ar9300_2p0_radio_core[][2] = { {0x00016840, 0x7f80fff8}, {0x0001684c, 0x76d005b5}, {0x00016850, 0x556cf031}, - {0x00016854, 0x43449440}, + {0x00016854, 0x13449440}, {0x00016858, 0x0c51c92c}, {0x0001685c, 0x3db7fffc}, {0x00016860, 0xfffffffc}, @@ -240,7 +241,6 @@ static const u32 ar9300_2p0_radio_core[][2] = { {0x00016900, 0x3fffbe01}, {0x00016904, 0xfff80000}, {0x00016908, 0x00080010}, - {0x00016940, 0x10804008}, {0x00016944, 0x02084080}, {0x00016948, 0x00000000}, {0x00016b80, 0x00000000}, @@ -588,12 +588,12 @@ static const u32 ar9200_merlin_2p0_radio_core[][2] = { static const u32 ar9300_2p0_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a800b}, + {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, - {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x00000b9c}, + {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, {0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044}, {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, @@ -604,8 +604,8 @@ static const u32 ar9300_2p0_baseband_postamble[][5] = { {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, - {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, + {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, + {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0}, {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, @@ -674,7 +674,7 @@ static const u32 ar9300_2p0_baseband_core[][2] = { {0x00009d10, 0x01834061}, {0x00009d14, 0x00c0040b}, {0x00009d18, 0x00000000}, - {0x00009e08, 0x0038233c}, + {0x00009e08, 0x0038230c}, {0x00009e24, 0x990bb515}, {0x00009e28, 0x0c6f0000}, {0x00009e30, 0x06336f77}, @@ -901,13 +901,13 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { {0x0000a5f8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, {0x0000a5fc, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, - {0x00016048, 0xae481a61, 0xae481a61, 0xae481a61, 0xae481a61}, + {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, {0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, - {0x00016448, 0xae481a61, 0xae481a61, 0xae481a61, 0xae481a61}, + {0x00016448, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, {0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, {0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, - {0x00016848, 0xae481a61, 0xae481a61, 0xae481a61, 0xae481a61}, + {0x00016848, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, {0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, }; @@ -979,13 +979,13 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { {0x0000a5f8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, {0x0000a5fc, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, - {0x00016048, 0x8e481a61, 0x8e481a61, 0x8e481a61, 0x8e481a61}, + {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, - {0x00016448, 0x8e481a61, 0x8e481a61, 0x8e481a61, 0x8e481a61}, + {0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, - {0x00016848, 0x8e481a61, 0x8e481a61, 0x8e481a61, 0x8e481a61}, + {0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; @@ -995,22 +995,22 @@ static const u32 ar9300Common_rx_gain_table_2p0[][2] = { {0x0000a004, 0x00030002}, {0x0000a008, 0x00050004}, {0x0000a00c, 0x00810080}, - {0x0000a010, 0x01800082}, - {0x0000a014, 0x01820181}, - {0x0000a018, 0x01840183}, - {0x0000a01c, 0x01880185}, - {0x0000a020, 0x018a0189}, - {0x0000a024, 0x02850284}, - {0x0000a028, 0x02890288}, - {0x0000a02c, 0x028b028a}, - {0x0000a030, 0x028d028c}, - {0x0000a034, 0x02910290}, - {0x0000a038, 0x02930292}, - {0x0000a03c, 0x03910390}, - {0x0000a040, 0x03930392}, - {0x0000a044, 0x03950394}, - {0x0000a048, 0x00000396}, - {0x0000a04c, 0x00000000}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x01910190}, + {0x0000a030, 0x01930192}, + {0x0000a034, 0x01950194}, + {0x0000a038, 0x038a0196}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, {0x0000a050, 0x00000000}, {0x0000a054, 0x00000000}, {0x0000a058, 0x00000000}, @@ -1023,14 +1023,14 @@ static const u32 ar9300Common_rx_gain_table_2p0[][2] = { {0x0000a074, 0x00000000}, {0x0000a078, 0x00000000}, {0x0000a07c, 0x00000000}, - {0x0000a080, 0x28282828}, - {0x0000a084, 0x21212128}, - {0x0000a088, 0x21212121}, - {0x0000a08c, 0x1c1c1c21}, - {0x0000a090, 0x1c1c1c1c}, - {0x0000a094, 0x17171c1c}, - {0x0000a098, 0x02020212}, - {0x0000a09c, 0x02020202}, + {0x0000a080, 0x22222229}, + {0x0000a084, 0x1d1d1d1d}, + {0x0000a088, 0x1d1d1d1d}, + {0x0000a08c, 0x1d1d1d1d}, + {0x0000a090, 0x171d1d1d}, + {0x0000a094, 0x11111717}, + {0x0000a098, 0x00030311}, + {0x0000a09c, 0x00000000}, {0x0000a0a0, 0x00000000}, {0x0000a0a4, 0x00000000}, {0x0000a0a8, 0x00000000}, @@ -1040,26 +1040,26 @@ static const u32 ar9300Common_rx_gain_table_2p0[][2] = { {0x0000a0b8, 0x00000000}, {0x0000a0bc, 0x00000000}, {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x011f0100}, - {0x0000a0c8, 0x011d011e}, - {0x0000a0cc, 0x011b011c}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, {0x0000a0d0, 0x02030204}, {0x0000a0d4, 0x02010202}, {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x021d021e}, - {0x0000a0e0, 0x03010302}, - {0x0000a0e4, 0x031f0300}, - {0x0000a0e8, 0x0402031e}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, {0x0000a0ec, 0x04000401}, {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x05010502}, - {0x0000a0f8, 0x051f0500}, - {0x0000a0fc, 0x0602051e}, - {0x0000a100, 0x06000601}, - {0x0000a104, 0x061e061f}, - {0x0000a108, 0x0703061d}, - {0x0000a10c, 0x07010702}, - {0x0000a110, 0x00000700}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, {0x0000a114, 0x00000000}, {0x0000a118, 0x00000000}, {0x0000a11c, 0x00000000}, @@ -1072,26 +1072,26 @@ static const u32 ar9300Common_rx_gain_table_2p0[][2] = { {0x0000a138, 0x00000000}, {0x0000a13c, 0x00000000}, {0x0000a140, 0x001f0000}, - {0x0000a144, 0x011f0100}, - {0x0000a148, 0x011d011e}, - {0x0000a14c, 0x011b011c}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, {0x0000a150, 0x02030204}, {0x0000a154, 0x02010202}, {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x021d021e}, - {0x0000a160, 0x03010302}, - {0x0000a164, 0x031f0300}, - {0x0000a168, 0x0402031e}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, {0x0000a16c, 0x04000401}, {0x0000a170, 0x041e041f}, - {0x0000a174, 0x05010502}, - {0x0000a178, 0x051f0500}, - {0x0000a17c, 0x0602051e}, - {0x0000a180, 0x06000601}, - {0x0000a184, 0x061e061f}, - {0x0000a188, 0x0703061d}, - {0x0000a18c, 0x07010702}, - {0x0000a190, 0x00000700}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, {0x0000a194, 0x00000000}, {0x0000a198, 0x00000000}, {0x0000a19c, 0x00000000}, @@ -1317,13 +1317,13 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p0[][5] = { {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x64001a61, 0x64001a61, 0x64001a61, 0x64001a61}, + {0x00016048, 0x64000001, 0x64000001, 0x64000001, 0x64000001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016448, 0x64001a61, 0x64001a61, 0x64001a61, 0x64001a61}, + {0x00016448, 0x64000001, 0x64000001, 0x64000001, 0x64000001}, {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016848, 0x64001a61, 0x64001a61, 0x64001a61, 0x64001a61}, + {0x00016848, 0x64000001, 0x64000001, 0x64000001, 0x64000001}, {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; @@ -1497,22 +1497,22 @@ static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = { {0x0000a004, 0x00030002}, {0x0000a008, 0x00050004}, {0x0000a00c, 0x00810080}, - {0x0000a010, 0x01800082}, - {0x0000a014, 0x01820181}, - {0x0000a018, 0x01840183}, - {0x0000a01c, 0x01880185}, - {0x0000a020, 0x018a0189}, - {0x0000a024, 0x02850284}, - {0x0000a028, 0x02890288}, - {0x0000a02c, 0x03850384}, - {0x0000a030, 0x03890388}, - {0x0000a034, 0x038b038a}, - {0x0000a038, 0x038d038c}, - {0x0000a03c, 0x03910390}, - {0x0000a040, 0x03930392}, - {0x0000a044, 0x03950394}, - {0x0000a048, 0x00000396}, - {0x0000a04c, 0x00000000}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x03820190}, + {0x0000a030, 0x03840383}, + {0x0000a034, 0x03880385}, + {0x0000a038, 0x038a0389}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, {0x0000a050, 0x00000000}, {0x0000a054, 0x00000000}, {0x0000a058, 0x00000000}, @@ -1525,15 +1525,15 @@ static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = { {0x0000a074, 0x00000000}, {0x0000a078, 0x00000000}, {0x0000a07c, 0x00000000}, - {0x0000a080, 0x28282828}, - {0x0000a084, 0x28282828}, - {0x0000a088, 0x28282828}, - {0x0000a08c, 0x28282828}, - {0x0000a090, 0x28282828}, - {0x0000a094, 0x21212128}, - {0x0000a098, 0x171c1c1c}, - {0x0000a09c, 0x02020212}, - {0x0000a0a0, 0x00000202}, + {0x0000a080, 0x29292929}, + {0x0000a084, 0x29292929}, + {0x0000a088, 0x29292929}, + {0x0000a08c, 0x29292929}, + {0x0000a090, 0x22292929}, + {0x0000a094, 0x1d1d2222}, + {0x0000a098, 0x0c111117}, + {0x0000a09c, 0x00030303}, + {0x0000a0a0, 0x00000000}, {0x0000a0a4, 0x00000000}, {0x0000a0a8, 0x00000000}, {0x0000a0ac, 0x00000000}, @@ -1542,26 +1542,26 @@ static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = { {0x0000a0b8, 0x00000000}, {0x0000a0bc, 0x00000000}, {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x011f0100}, - {0x0000a0c8, 0x011d011e}, - {0x0000a0cc, 0x011b011c}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, {0x0000a0d0, 0x02030204}, {0x0000a0d4, 0x02010202}, {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x021d021e}, - {0x0000a0e0, 0x03010302}, - {0x0000a0e4, 0x031f0300}, - {0x0000a0e8, 0x0402031e}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, {0x0000a0ec, 0x04000401}, {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x05010502}, - {0x0000a0f8, 0x051f0500}, - {0x0000a0fc, 0x0602051e}, - {0x0000a100, 0x06000601}, - {0x0000a104, 0x061e061f}, - {0x0000a108, 0x0703061d}, - {0x0000a10c, 0x07010702}, - {0x0000a110, 0x00000700}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, {0x0000a114, 0x00000000}, {0x0000a118, 0x00000000}, {0x0000a11c, 0x00000000}, @@ -1574,26 +1574,26 @@ static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = { {0x0000a138, 0x00000000}, {0x0000a13c, 0x00000000}, {0x0000a140, 0x001f0000}, - {0x0000a144, 0x011f0100}, - {0x0000a148, 0x011d011e}, - {0x0000a14c, 0x011b011c}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, {0x0000a150, 0x02030204}, {0x0000a154, 0x02010202}, {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x021d021e}, - {0x0000a160, 0x03010302}, - {0x0000a164, 0x031f0300}, - {0x0000a168, 0x0402031e}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, {0x0000a16c, 0x04000401}, {0x0000a170, 0x041e041f}, - {0x0000a174, 0x05010502}, - {0x0000a178, 0x051f0500}, - {0x0000a17c, 0x0602051e}, - {0x0000a180, 0x06000601}, - {0x0000a184, 0x061e061f}, - {0x0000a188, 0x0703061d}, - {0x0000a18c, 0x07010702}, - {0x0000a190, 0x00000700}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, {0x0000a194, 0x00000000}, {0x0000a198, 0x00000000}, {0x0000a19c, 0x00000000}, @@ -1620,7 +1620,7 @@ static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = { {0x0000a1f0, 0x00000396}, {0x0000a1f4, 0x00000396}, {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000296}, + {0x0000a1fc, 0x00000196}, {0x0000b000, 0x00010000}, {0x0000b004, 0x00030002}, {0x0000b008, 0x00050004}, -- cgit v1.2.3 From 083e3e8d3dfeb191f349081c052ad3d20e8861f3 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Mon, 10 May 2010 19:41:34 -0700 Subject: ath9k: Fix bug in handling rx frames with invalid descriptor content Don't send them for further processing. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index ac60c4ee62d3..da54ff5f3d7e 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -718,6 +718,7 @@ static bool ath_edma_get_buffers(struct ath_softc *sc, __skb_unlink(skb, &rx_edma->rx_fifo); list_add_tail(&bf->list, &sc->rx.rxbuf); ath_rx_edma_buf_link(sc, qtype); + return true; } skb_queue_tail(&rx_edma->rx_buffers, skb); -- cgit v1.2.3 From b29e7eb4b8b3e5f4ff8066af648e9fe2fc707b16 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Mon, 10 May 2010 19:41:35 -0700 Subject: ath9k: Remove unused rx_edma in ath_rx_addbuffer_edma() Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index da54ff5f3d7e..ba139132c85f 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -150,11 +150,9 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc, static void ath_rx_addbuffer_edma(struct ath_softc *sc, enum ath9k_rx_qtype qtype, int size) { - struct ath_rx_edma *rx_edma; struct ath_common *common = ath9k_hw_common(sc->sc_ah); u32 nbuf = 0; - rx_edma = &sc->rx.rx_edma[qtype]; if (list_empty(&sc->rx.rxbuf)) { ath_print(common, ATH_DBG_QUEUE, "No free rx buf available\n"); return; -- cgit v1.2.3 From 05a30f9cf2a57ebbb2b616b5394e06b893179f13 Mon Sep 17 00:00:00 2001 From: "Sujith.Manoharan@atheros.com" Date: Tue, 11 May 2010 16:24:38 +0530 Subject: ath9k_htc: Lock sta_notify() callback Since ->sta_notify() can sleep, protect the callback with a mutex. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 6c386dad1d40..9d371c18eb41 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1452,6 +1452,8 @@ static void ath9k_htc_sta_notify(struct ieee80211_hw *hw, struct ath9k_htc_priv *priv = hw->priv; int ret; + mutex_lock(&priv->mutex); + switch (cmd) { case STA_NOTIFY_ADD: ret = ath9k_htc_add_station(priv, vif, sta); @@ -1464,6 +1466,8 @@ static void ath9k_htc_sta_notify(struct ieee80211_hw *hw, default: break; } + + mutex_unlock(&priv->mutex); } static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, -- cgit v1.2.3 From 1d8af8caccceab91ba65b7f659678b92093f9203 Mon Sep 17 00:00:00 2001 From: "Sujith.Manoharan@atheros.com" Date: Tue, 11 May 2010 16:24:40 +0530 Subject: ath9k_htc: Allocate URBs properly The URBs have to be allocated before uploading the firmware to the target. This is needed to process the target ready message properly. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 36 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 74872ca76f9a..453cf56eba78 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -735,6 +735,14 @@ err: return -ENOMEM; } +static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) +{ + usb_kill_anchored_urbs(&hif_dev->regout_submitted); + ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); + ath9k_hif_usb_dealloc_tx_urbs(hif_dev); + ath9k_hif_usb_dealloc_rx_urbs(hif_dev); +} + static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) { int transfer, err; @@ -794,14 +802,6 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, goto err_fw_req; } - /* Download firmware */ - ret = ath9k_hif_usb_download_fw(hif_dev); - if (ret) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: Firmware - %s download failed\n", fw_name); - goto err_fw_download; - } - /* Alloc URBs */ ret = ath9k_hif_usb_alloc_urbs(hif_dev); if (ret) { @@ -810,25 +810,25 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, goto err_urb; } + /* Download firmware */ + ret = ath9k_hif_usb_download_fw(hif_dev); + if (ret) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Firmware - %s download failed\n", fw_name); + goto err_fw_download; + } + return 0; -err_urb: - /* Nothing */ err_fw_download: + ath9k_hif_usb_dealloc_urbs(hif_dev); +err_urb: release_firmware(hif_dev->firmware); err_fw_req: hif_dev->firmware = NULL; return ret; } -static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) -{ - usb_kill_anchored_urbs(&hif_dev->regout_submitted); - ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); - ath9k_hif_usb_dealloc_tx_urbs(hif_dev); - ath9k_hif_usb_dealloc_rx_urbs(hif_dev); -} - static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev) { ath9k_hif_usb_dealloc_urbs(hif_dev); -- cgit v1.2.3 From 47fce026d5de5d11e161da73208171e9c91b659a Mon Sep 17 00:00:00 2001 From: "Sujith.Manoharan@atheros.com" Date: Tue, 11 May 2010 16:24:41 +0530 Subject: ath9k_htc: Reorder HTC initialization The HTC state has to be setup before initializing the target because the ready message could possibly come before the control endpoints in HTC have been identified. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 22 +++++++++--------- drivers/net/wireless/ath/ath9k/htc_hst.c | 38 ++++++++++++++++---------------- drivers/net/wireless/ath/ath9k/htc_hst.h | 9 ++++---- 3 files changed, 35 insertions(+), 34 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 453cf56eba78..46dc41a16faa 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -859,21 +859,21 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, #endif usb_set_intfdata(interface, hif_dev); + hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev, &hif_usb, + &hif_dev->udev->dev); + if (hif_dev->htc_handle == NULL) { + ret = -ENOMEM; + goto err_htc_hw_alloc; + } + ret = ath9k_hif_usb_dev_init(hif_dev, fw_name); if (ret) { ret = -EINVAL; goto err_hif_init_usb; } - hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev); - if (hif_dev->htc_handle == NULL) { - ret = -ENOMEM; - goto err_htc_hw_alloc; - } - - ret = ath9k_htc_hw_init(&hif_usb, hif_dev->htc_handle, hif_dev, - &hif_dev->udev->dev, hif_dev->device_id, - ATH9K_HIF_USB); + ret = ath9k_htc_hw_init(hif_dev->htc_handle, + &hif_dev->udev->dev, hif_dev->device_id); if (ret) { ret = -EINVAL; goto err_htc_hw_init; @@ -884,10 +884,10 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, return 0; err_htc_hw_init: - ath9k_htc_hw_free(hif_dev->htc_handle); -err_htc_hw_alloc: ath9k_hif_usb_dev_deinit(hif_dev); err_hif_init_usb: + ath9k_htc_hw_free(hif_dev->htc_handle); +err_htc_hw_alloc: usb_set_intfdata(interface, NULL); kfree(hif_dev); usb_put_dev(udev); diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 7bf6ce1e7e2e..2c8006ae2786 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -425,29 +425,19 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, } } -struct htc_target *ath9k_htc_hw_alloc(void *hif_handle) +struct htc_target *ath9k_htc_hw_alloc(void *hif_handle, + struct ath9k_htc_hif *hif, + struct device *dev) { + struct htc_endpoint *endpoint; struct htc_target *target; target = kzalloc(sizeof(struct htc_target), GFP_KERNEL); - if (!target) + if (!target) { printk(KERN_ERR "Unable to allocate memory for" "target device\n"); - - return target; -} - -void ath9k_htc_hw_free(struct htc_target *htc) -{ - kfree(htc); -} - -int ath9k_htc_hw_init(struct ath9k_htc_hif *hif, struct htc_target *target, - void *hif_handle, struct device *dev, u16 devid, - enum ath9k_hif_transports transport) -{ - struct htc_endpoint *endpoint; - int err = 0; + return NULL; + } init_completion(&target->target_wait); init_completion(&target->cmd_wait); @@ -461,8 +451,18 @@ int ath9k_htc_hw_init(struct ath9k_htc_hif *hif, struct htc_target *target, endpoint->ul_pipeid = hif->control_ul_pipe; endpoint->dl_pipeid = hif->control_dl_pipe; - err = ath9k_htc_probe_device(target, dev, devid); - if (err) { + return target; +} + +void ath9k_htc_hw_free(struct htc_target *htc) +{ + kfree(htc); +} + +int ath9k_htc_hw_init(struct htc_target *target, + struct device *dev, u16 devid) +{ + if (ath9k_htc_probe_device(target, dev, devid)) { printk(KERN_ERR "Failed to initialize the device\n"); return -ENODEV; } diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index ea50ab032d20..d216c0f4d168 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -236,11 +236,12 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, struct sk_buff *skb, bool txok); -struct htc_target *ath9k_htc_hw_alloc(void *hif_handle); +struct htc_target *ath9k_htc_hw_alloc(void *hif_handle, + struct ath9k_htc_hif *hif, + struct device *dev); void ath9k_htc_hw_free(struct htc_target *htc); -int ath9k_htc_hw_init(struct ath9k_htc_hif *hif, struct htc_target *target, - void *hif_handle, struct device *dev, u16 devid, - enum ath9k_hif_transports transport); +int ath9k_htc_hw_init(struct htc_target *target, + struct device *dev, u16 devid); void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug); #endif /* HTC_HST_H */ -- cgit v1.2.3 From d8c49ffb2e2a47b23fec7f469435e7b112e2e569 Mon Sep 17 00:00:00 2001 From: "Sujith.Manoharan@atheros.com" Date: Tue, 11 May 2010 16:24:43 +0530 Subject: ath9k_htc: Fix target ready race condition The ready message from the target could be processed before the host HW init has completed. In this case, htc_process_target_rdy() would assume the target has timed out, when it hasn't. Fix this by checking if the target has sent the ready message properly. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 7 +++++++ drivers/net/wireless/ath/ath9k/htc_hst.c | 3 +++ drivers/net/wireless/ath/ath9k/htc_hst.h | 1 + 3 files changed, 11 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 17111fc1d2cc..dc015077a8d9 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -81,6 +81,11 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) { int time_left; + if (atomic_read(&priv->htc->tgt_ready) > 0) { + atomic_dec(&priv->htc->tgt_ready); + return 0; + } + /* Firmware can take up to 50ms to get ready, to be safe use 1 second */ time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ); if (!time_left) { @@ -88,6 +93,8 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) return -ETIMEDOUT; } + atomic_dec(&priv->htc->tgt_ready); + return 0; } diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 2c8006ae2786..e86e1728c8de 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -95,6 +95,7 @@ static void htc_process_target_rdy(struct htc_target *target, endpoint = &target->endpoint[ENDPOINT0]; endpoint->service_id = HTC_CTRL_RSVD_SVC; endpoint->max_msglen = HTC_MAX_CONTROL_MESSAGE_LENGTH; + atomic_inc(&target->tgt_ready); complete(&target->target_wait); } @@ -451,6 +452,8 @@ struct htc_target *ath9k_htc_hw_alloc(void *hif_handle, endpoint->ul_pipeid = hif->control_ul_pipe; endpoint->dl_pipeid = hif->control_dl_pipe; + atomic_set(&target->tgt_ready, 0); + return target; } diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index d216c0f4d168..4f1cdb003cce 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -147,6 +147,7 @@ struct htc_target { u16 credits; u16 credit_size; u8 htc_flags; + atomic_t tgt_ready; }; enum htc_msg_id { -- cgit v1.2.3 From 8116daf2146d8fbc5d8d925984b3d4fd34dba1b4 Mon Sep 17 00:00:00 2001 From: "Sujith.Manoharan@atheros.com" Date: Tue, 11 May 2010 17:03:36 +0530 Subject: ath9k_htc: Fix array overflow Use ENDPOINT_MAX instead of HST_ENDPOINT_MAX. This fixes a stack corruption issue. This is based on a patch sent by Dan Carpenter . Signed-off-by: Dan Carpenter Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_hst.c | 10 +++++----- drivers/net/wireless/ath/ath9k/htc_hst.h | 5 +---- 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index e86e1728c8de..064397fd738e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -39,7 +39,7 @@ static struct htc_endpoint *get_next_avail_ep(struct htc_endpoint *endpoint) { enum htc_endpoint_id avail_epid; - for (avail_epid = ENDPOINT_MAX; avail_epid > ENDPOINT0; avail_epid--) + for (avail_epid = (ENDPOINT_MAX - 1); avail_epid > ENDPOINT0; avail_epid--) if (endpoint[avail_epid].service_id == 0) return &endpoint[avail_epid]; return NULL; @@ -117,7 +117,7 @@ static void htc_process_conn_rsp(struct htc_target *target, max_msglen = be16_to_cpu(svc_rspmsg->max_msg_len); endpoint = &target->endpoint[epid]; - for (tepid = ENDPOINT_MAX; tepid > ENDPOINT0; tepid--) { + for (tepid = (ENDPOINT_MAX - 1); tepid > ENDPOINT0; tepid--) { tmp_endpoint = &target->endpoint[tepid]; if (tmp_endpoint->service_id == service_id) { tmp_endpoint->service_id = 0; @@ -125,7 +125,7 @@ static void htc_process_conn_rsp(struct htc_target *target, } } - if (!tmp_endpoint) + if (tepid == ENDPOINT0) return; endpoint->service_id = service_id; @@ -298,7 +298,7 @@ void htc_stop(struct htc_target *target) enum htc_endpoint_id epid; struct htc_endpoint *endpoint; - for (epid = ENDPOINT0; epid <= ENDPOINT_MAX; epid++) { + for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) { endpoint = &target->endpoint[epid]; if (endpoint->service_id != 0) target->hif->stop(target->hif_dev, endpoint->ul_pipeid); @@ -310,7 +310,7 @@ void htc_start(struct htc_target *target) enum htc_endpoint_id epid; struct htc_endpoint *endpoint; - for (epid = ENDPOINT0; epid <= ENDPOINT_MAX; epid++) { + for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) { endpoint = &target->endpoint[epid]; if (endpoint->service_id != 0) target->hif->start(target->hif_dev, diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index 4f1cdb003cce..faba6790328b 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -123,9 +123,6 @@ struct htc_endpoint { #define HTC_CONTROL_BUFFER_SIZE \ (HTC_MAX_CONTROL_MESSAGE_LENGTH + sizeof(struct htc_frame_hdr)) -#define NUM_CONTROL_BUFFERS 8 -#define HST_ENDPOINT_MAX 8 - struct htc_control_buf { struct htc_packet htc_pkt; u8 buf[HTC_CONTROL_BUFFER_SIZE]; @@ -139,7 +136,7 @@ struct htc_target { struct ath9k_htc_priv *drv_priv; struct device *dev; struct ath9k_htc_hif *hif; - struct htc_endpoint endpoint[HST_ENDPOINT_MAX]; + struct htc_endpoint endpoint[ENDPOINT_MAX]; struct completion target_wait; struct completion cmd_wait; struct list_head list; -- cgit v1.2.3 From c8a72c00c6a58186c35901c5fb15584ebc2a081d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 11 May 2010 17:23:00 +0200 Subject: ath9k: use debugfs_remove_recursive() instead of keeping pointers to all entries Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 55 ++++++++++------------------------ drivers/net/wireless/ath/ath9k/debug.h | 7 ----- 2 files changed, 16 insertions(+), 46 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index ab59e2ec18c6..59252ce24d7f 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -721,52 +721,36 @@ int ath9k_init_debug(struct ath_hw *ah) sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), ath9k_debugfs_root); if (!sc->debug.debugfs_phy) - goto err; + return -ENOMEM; #ifdef CONFIG_ATH_DEBUG - sc->debug.debugfs_debug = debugfs_create_file("debug", - S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_debug); - if (!sc->debug.debugfs_debug) + if (!debugfs_create_file("debug", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_debug)) goto err; #endif - sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUSR, - sc->debug.debugfs_phy, sc, &fops_dma); - if (!sc->debug.debugfs_dma) + if (!debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, + sc, &fops_dma)) goto err; - sc->debug.debugfs_interrupt = debugfs_create_file("interrupt", - S_IRUSR, - sc->debug.debugfs_phy, - sc, &fops_interrupt); - if (!sc->debug.debugfs_interrupt) + if (!debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, + sc, &fops_interrupt)) goto err; - sc->debug.debugfs_rcstat = debugfs_create_file("rcstat", - S_IRUSR, - sc->debug.debugfs_phy, - sc, &fops_rcstat); - if (!sc->debug.debugfs_rcstat) + if (!debugfs_create_file("rcstat", S_IRUSR, sc->debug.debugfs_phy, + sc, &fops_rcstat)) goto err; - sc->debug.debugfs_wiphy = debugfs_create_file( - "wiphy", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, - &fops_wiphy); - if (!sc->debug.debugfs_wiphy) + if (!debugfs_create_file("wiphy", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_wiphy)) goto err; - sc->debug.debugfs_xmit = debugfs_create_file("xmit", - S_IRUSR, - sc->debug.debugfs_phy, - sc, &fops_xmit); - if (!sc->debug.debugfs_xmit) + if (!debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, + sc, &fops_xmit)) goto err; - sc->debug.debugfs_recv = debugfs_create_file("recv", - S_IRUSR, - sc->debug.debugfs_phy, - sc, &fops_recv); - if (!sc->debug.debugfs_recv) + if (!debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, + sc, &fops_recv)) goto err; return 0; @@ -780,14 +764,7 @@ void ath9k_exit_debug(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); struct ath_softc *sc = (struct ath_softc *) common->priv; - debugfs_remove(sc->debug.debugfs_recv); - debugfs_remove(sc->debug.debugfs_xmit); - debugfs_remove(sc->debug.debugfs_wiphy); - debugfs_remove(sc->debug.debugfs_rcstat); - debugfs_remove(sc->debug.debugfs_interrupt); - debugfs_remove(sc->debug.debugfs_dma); - debugfs_remove(sc->debug.debugfs_debug); - debugfs_remove(sc->debug.debugfs_phy); + debugfs_remove_recursive(sc->debug.debugfs_phy); } int ath9k_debug_create_root(void) diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index c545960e7ec5..731436035bac 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -153,13 +153,6 @@ struct ath_stats { struct ath9k_debug { struct dentry *debugfs_phy; - struct dentry *debugfs_debug; - struct dentry *debugfs_dma; - struct dentry *debugfs_interrupt; - struct dentry *debugfs_rcstat; - struct dentry *debugfs_wiphy; - struct dentry *debugfs_xmit; - struct dentry *debugfs_recv; struct ath_stats stats; }; -- cgit v1.2.3 From 1534069491c67619bfaeb25368a1249b669503c3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 11 May 2010 17:23:01 +0200 Subject: ath9k: add debugfs files for reading/writing the rx and tx chainmask Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 92 ++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 59252ce24d7f..7a2fe09d4a99 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -77,6 +77,90 @@ static const struct file_operations fops_debug = { #define DMA_BUF_LEN 1024 +static ssize_t read_file_tx_chainmask(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + char buf[32]; + unsigned int len; + + len = snprintf(buf, sizeof(buf), "0x%08x\n", common->tx_chainmask); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_tx_chainmask(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + unsigned long mask; + char buf[32]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EINVAL; + + buf[len] = '\0'; + if (strict_strtoul(buf, 0, &mask)) + return -EINVAL; + + common->tx_chainmask = mask; + sc->sc_ah->caps.tx_chainmask = mask; + return count; +} + +static const struct file_operations fops_tx_chainmask = { + .read = read_file_tx_chainmask, + .write = write_file_tx_chainmask, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + + +static ssize_t read_file_rx_chainmask(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + char buf[32]; + unsigned int len; + + len = snprintf(buf, sizeof(buf), "0x%08x\n", common->rx_chainmask); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_rx_chainmask(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + unsigned long mask; + char buf[32]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EINVAL; + + buf[len] = '\0'; + if (strict_strtoul(buf, 0, &mask)) + return -EINVAL; + + common->rx_chainmask = mask; + sc->sc_ah->caps.rx_chainmask = mask; + return count; +} + +static const struct file_operations fops_rx_chainmask = { + .read = read_file_rx_chainmask, + .write = write_file_rx_chainmask, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + + static ssize_t read_file_dma(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -753,6 +837,14 @@ int ath9k_init_debug(struct ath_hw *ah) sc, &fops_recv)) goto err; + if (!debugfs_create_file("rx_chainmask", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_rx_chainmask)) + goto err; + + if (!debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_tx_chainmask)) + goto err; + return 0; err: ath9k_exit_debug(ah); -- cgit v1.2.3 From 9bff0bc4012c7f079b297eb45b47780e3713f367 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 11 May 2010 17:23:02 +0200 Subject: ath9k: add debugfs files for reading/writing registers Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 89 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/debug.h | 1 + 2 files changed, 90 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 7a2fe09d4a99..2ca9bba8a6af 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -794,6 +794,86 @@ static const struct file_operations fops_recv = { .owner = THIS_MODULE }; +static ssize_t read_file_regidx(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[32]; + unsigned int len; + + len = snprintf(buf, sizeof(buf), "0x%08x\n", sc->debug.regidx); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_regidx(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + unsigned long regidx; + char buf[32]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EINVAL; + + buf[len] = '\0'; + if (strict_strtoul(buf, 0, ®idx)) + return -EINVAL; + + sc->debug.regidx = regidx; + return count; +} + +static const struct file_operations fops_regidx = { + .read = read_file_regidx, + .write = write_file_regidx, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + +static ssize_t read_file_regval(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + struct ath_hw *ah = sc->sc_ah; + char buf[32]; + unsigned int len; + u32 regval; + + regval = REG_READ_D(ah, sc->debug.regidx); + len = snprintf(buf, sizeof(buf), "0x%08x\n", regval); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_regval(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + struct ath_hw *ah = sc->sc_ah; + unsigned long regval; + char buf[32]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EINVAL; + + buf[len] = '\0'; + if (strict_strtoul(buf, 0, ®val)) + return -EINVAL; + + REG_WRITE_D(ah, sc->debug.regidx, regval); + return count; +} + +static const struct file_operations fops_regval = { + .read = read_file_regval, + .write = write_file_regval, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -845,6 +925,15 @@ int ath9k_init_debug(struct ath_hw *ah) sc->debug.debugfs_phy, sc, &fops_tx_chainmask)) goto err; + if (!debugfs_create_file("regidx", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_regidx)) + goto err; + + if (!debugfs_create_file("regval", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_regval)) + goto err; + + sc->debug.regidx = 0; return 0; err: ath9k_exit_debug(ah); diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 731436035bac..5147b8709e10 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -153,6 +153,7 @@ struct ath_stats { struct ath9k_debug { struct dentry *debugfs_phy; + u32 regidx; struct ath_stats stats; }; -- cgit v1.2.3 From ffdc4cbe5b17c83af779f45de8536c6ece297e42 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 11 May 2010 17:23:03 +0200 Subject: ath9k_hw: clean up EEPROM endian handling on AR9003 Remove the double swapping of the descriptor data structure, instead keep it little-endian (native format of the eeprom data), and byteswap on access. This allows sparse to verify endian access to the eeprom struct. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 174 +++++++++++-------------- drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 10 +- 2 files changed, 81 insertions(+), 103 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 8a79550dff71..23eb60ea5455 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -38,6 +38,9 @@ #define AR_SWITCH_TABLE_ALL (0xfff) #define AR_SWITCH_TABLE_ALL_S (0) +#define LE16(x) __constant_cpu_to_le16(x) +#define LE32(x) __constant_cpu_to_le32(x) + static const struct ar9300_eeprom ar9300_default = { .eepromVersion = 2, .templateVersion = 2, @@ -45,7 +48,7 @@ static const struct ar9300_eeprom ar9300_default = { .custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, .baseEepHeader = { - .regDmn = {0, 0x1f}, + .regDmn = { LE16(0), LE16(0x1f) }, .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ .opCapFlags = { .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A, @@ -76,15 +79,15 @@ static const struct ar9300_eeprom ar9300_default = { .modalHeader2G = { /* ar9300_modal_eep_header 2g */ /* 4 idle,t1,t2,b(4 bits per setting) */ - .antCtrlCommon = 0x110, + .antCtrlCommon = LE32(0x110), /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ - .antCtrlCommon2 = 0x22222, + .antCtrlCommon2 = LE32(0x22222), /* * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r, * rx1, rx12, b (2 bits each) */ - .antCtrlChain = {0x150, 0x150, 0x150}, + .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) }, /* * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db @@ -287,12 +290,12 @@ static const struct ar9300_eeprom ar9300_default = { }, .modalHeader5G = { /* 4 idle,t1,t2,b (4 bits per setting) */ - .antCtrlCommon = 0x110, + .antCtrlCommon = LE32(0x110), /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ - .antCtrlCommon2 = 0x22222, + .antCtrlCommon2 = LE32(0x22222), /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ .antCtrlChain = { - 0x000, 0x000, 0x000, + LE16(0x000), LE16(0x000), LE16(0x000), }, /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ .xatten1DB = {0, 0, 0}, @@ -620,9 +623,9 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, case EEP_MAC_MSW: return eep->macAddr[4] << 8 | eep->macAddr[5]; case EEP_REG_0: - return pBase->regDmn[0]; + return le16_to_cpu(pBase->regDmn[0]); case EEP_REG_1: - return pBase->regDmn[1]; + return le16_to_cpu(pBase->regDmn[1]); case EEP_OP_CAP: return pBase->deviceCap; case EEP_OP_MODE: @@ -640,93 +643,80 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, /* Bit 4 is internal regulator flag */ return (pBase->featureEnable & 0x10) >> 4; case EEP_SWREG: - return pBase->swreg; + return le32_to_cpu(pBase->swreg); default: return 0; } } -#ifdef __BIG_ENDIAN -static void ar9300_swap_eeprom(struct ar9300_eeprom *eep) +static bool ar9300_eeprom_read_byte(struct ath_common *common, int address, + u8 *buffer) { - u32 dword; - u16 word; - int i; - - word = swab16(eep->baseEepHeader.regDmn[0]); - eep->baseEepHeader.regDmn[0] = word; - - word = swab16(eep->baseEepHeader.regDmn[1]); - eep->baseEepHeader.regDmn[1] = word; - - dword = swab32(eep->baseEepHeader.swreg); - eep->baseEepHeader.swreg = dword; + u16 val; - dword = swab32(eep->modalHeader2G.antCtrlCommon); - eep->modalHeader2G.antCtrlCommon = dword; + if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val))) + return false; - dword = swab32(eep->modalHeader2G.antCtrlCommon2); - eep->modalHeader2G.antCtrlCommon2 = dword; + *buffer = (val >> (8 * (address % 2))) & 0xff; + return true; +} - dword = swab32(eep->modalHeader5G.antCtrlCommon); - eep->modalHeader5G.antCtrlCommon = dword; +static bool ar9300_eeprom_read_word(struct ath_common *common, int address, + u8 *buffer) +{ + u16 val; - dword = swab32(eep->modalHeader5G.antCtrlCommon2); - eep->modalHeader5G.antCtrlCommon2 = dword; + if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val))) + return false; - for (i = 0; i < AR9300_MAX_CHAINS; i++) { - word = swab16(eep->modalHeader2G.antCtrlChain[i]); - eep->modalHeader2G.antCtrlChain[i] = word; + buffer[0] = val >> 8; + buffer[1] = val & 0xff; - word = swab16(eep->modalHeader5G.antCtrlChain[i]); - eep->modalHeader5G.antCtrlChain[i] = word; - } + return true; } -#endif -static bool ar9300_hw_read_eeprom(struct ath_hw *ah, - long address, u8 *buffer, int many) +static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer, + int count) { - int i; - u8 value[2]; - unsigned long eepAddr; - unsigned long byteAddr; - u16 *svalue; struct ath_common *common = ath9k_hw_common(ah); + int i; - if ((address < 0) || ((address + many) > AR9300_EEPROM_SIZE - 1)) { + if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) { ath_print(common, ATH_DBG_EEPROM, "eeprom address not in range\n"); return false; } - for (i = 0; i < many; i++) { - eepAddr = (u16) (address + i) / 2; - byteAddr = (u16) (address + i) % 2; - svalue = (u16 *) value; - if (!ath9k_hw_nvram_read(common, eepAddr, svalue)) { - ath_print(common, ATH_DBG_EEPROM, - "unable to read eeprom region\n"); - return false; - } - *svalue = le16_to_cpu(*svalue); - buffer[i] = value[byteAddr]; + /* + * Since we're reading the bytes in reverse order from a little-endian + * word stream, an even address means we only use the lower half of + * the 16-bit word at that address + */ + if (address % 2 == 0) { + if (!ar9300_eeprom_read_byte(common, address--, buffer++)) + goto error; + + count--; } - return true; -} + for (i = 0; i < count / 2; i++) { + if (!ar9300_eeprom_read_word(common, address, buffer)) + goto error; -static bool ar9300_read_eeprom(struct ath_hw *ah, - int address, u8 *buffer, int many) -{ - int it; + address -= 2; + buffer += 2; + } + + if (count % 2) + if (!ar9300_eeprom_read_byte(common, address, buffer)) + goto error; - for (it = 0; it < many; it++) - if (!ar9300_hw_read_eeprom(ah, - (address - it), - (buffer + it), 1)) - return false; return true; + +error: + ath_print(common, ATH_DBG_EEPROM, + "unable to read eeprom region at offset %d\n", address); + return false; } static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference, @@ -927,30 +917,13 @@ fail: */ static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah) { - u8 *mptr = NULL; - int mdata_size; + u8 *mptr = (u8 *) &ah->eeprom.ar9300_eep; - mptr = (u8 *) &ah->eeprom.ar9300_eep; - mdata_size = sizeof(struct ar9300_eeprom); + if (ar9300_eeprom_restore_internal(ah, mptr, + sizeof(struct ar9300_eeprom)) < 0) + return false; - if (mptr && mdata_size > 0) { - /* At this point, mptr points to the eeprom data structure - * in it's "default" state. If this is big endian, swap the - * data structures back to "little endian" - */ - /* First swap, default to Little Endian */ -#ifdef __BIG_ENDIAN - ar9300_swap_eeprom((struct ar9300_eeprom *)mptr); -#endif - if (ar9300_eeprom_restore_internal(ah, mptr, mdata_size) >= 0) - return true; - - /* Second Swap, back to Big Endian */ -#ifdef __BIG_ENDIAN - ar9300_swap_eeprom((struct ar9300_eeprom *)mptr); -#endif - } - return false; + return true; } /* XXX: review hardware docs */ @@ -998,21 +971,25 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz) { struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + __le32 val; if (is2ghz) - return eep->modalHeader2G.antCtrlCommon; + val = eep->modalHeader2G.antCtrlCommon; else - return eep->modalHeader5G.antCtrlCommon; + val = eep->modalHeader5G.antCtrlCommon; + return le32_to_cpu(val); } static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz) { struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + __le32 val; if (is2ghz) - return eep->modalHeader2G.antCtrlCommon2; + val = eep->modalHeader2G.antCtrlCommon2; else - return eep->modalHeader5G.antCtrlCommon2; + val = eep->modalHeader5G.antCtrlCommon2; + return le32_to_cpu(val); } static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, @@ -1020,15 +997,16 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, bool is2ghz) { struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + __le16 val = 0; if (chain >= 0 && chain < AR9300_MAX_CHAINS) { if (is2ghz) - return eep->modalHeader2G.antCtrlChain[chain]; + val = eep->modalHeader2G.antCtrlChain[chain]; else - return eep->modalHeader5G.antCtrlChain[chain]; + val = eep->modalHeader5G.antCtrlChain[chain]; } - return 0; + return le16_to_cpu(val); } static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index d8c0318f416f..23fb353c3bba 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -169,7 +169,7 @@ enum CompressAlgorithm { }; struct ar9300_base_eep_hdr { - u16 regDmn[2]; + __le16 regDmn[2]; /* 4 bits tx and 4 bits rx */ u8 txrxMask; struct eepFlags opCapFlags; @@ -199,16 +199,16 @@ struct ar9300_base_eep_hdr { u8 rxBandSelectGpio; u8 txrxgain; /* SW controlled internal regulator fields */ - u32 swreg; + __le32 swreg; } __packed; struct ar9300_modal_eep_header { /* 4 idle, t1, t2, b (4 bits per setting) */ - u32 antCtrlCommon; + __le32 antCtrlCommon; /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ - u32 antCtrlCommon2; + __le32 antCtrlCommon2; /* 6 idle, t, r, rx1, rx12, b (2 bits each) */ - u16 antCtrlChain[AR9300_MAX_CHAINS]; + __le16 antCtrlChain[AR9300_MAX_CHAINS]; /* 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ u8 xatten1DB[AR9300_MAX_CHAINS]; /* 3 xatten1_margin for merlin (0xa20c/b20c 16:12 */ -- cgit v1.2.3 From aca8c6fa46aed6db36043cd2edbdc42fd20c3208 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 11 May 2010 20:25:56 +0200 Subject: drivers/net/wireless/hostap: Drop memory allocation cast Drop cast on the result of kmalloc and similar functions. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ type T; @@ - (T *) (\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\| kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(...)) // Signed-off-by: Julia Lawall Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_80211_rx.c | 3 +-- drivers/net/wireless/hostap/hostap_ioctl.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c index 3816df96a663..fa592cb6bf9a 100644 --- a/drivers/net/wireless/hostap/hostap_80211_rx.c +++ b/drivers/net/wireless/hostap/hostap_80211_rx.c @@ -354,8 +354,7 @@ static struct hostap_bss_info *__hostap_add_bss(local_info_t *local, u8 *bssid, list_del(&bss->list); local->num_bss_info--; } else { - bss = (struct hostap_bss_info *) - kmalloc(sizeof(*bss), GFP_ATOMIC); + bss = kmalloc(sizeof(*bss), GFP_ATOMIC); if (bss == NULL) return NULL; } diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index 9419cebca8a5..f12a79786fbd 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c @@ -3038,8 +3038,7 @@ static int prism2_ioctl_priv_download(local_info_t *local, struct iw_point *p) p->length > 1024 || !p->pointer) return -EINVAL; - param = (struct prism2_download_param *) - kmalloc(p->length, GFP_KERNEL); + param = kmalloc(p->length, GFP_KERNEL); if (param == NULL) return -ENOMEM; -- cgit v1.2.3 From 2cb1ba153787e195c62eafc2e794b25509fdd26d Mon Sep 17 00:00:00 2001 From: Steve Tanner Date: Tue, 11 May 2010 14:34:16 -0700 Subject: ar9170usb: add vendor and device ID for Qwest/Actiontec 802AIN Wireless N USB Network Adapter * add support for the Qwest/Actiontec 802AIN Wireless N USB Network Adapter. lsusb identifies the device as: "ID 1668:1200 Actiontec Electronics, Inc. [hex]" usb_modeswitch package and appropriate rules are required to switch the device from "ID 0ace:20ff ZyDas" Changes-licensed-under: GPL Signed-off-by: Steve Tanner Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/usb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index c7405b642fef..e0ca1d7359fa 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -108,6 +108,8 @@ static struct usb_device_id ar9170_usb_ids[] = { { USB_DEVICE(0x0409, 0x0249) }, /* AVM FRITZ!WLAN USB Stick N 2.4 */ { USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY }, + /* Qwest/Actiontec 802AIN Wireless N USB Network Adapter */ + { USB_DEVICE(0x1668, 0x1200) }, /* terminate */ {} -- cgit v1.2.3 From 878f7045d8ae24f5a9e3a8a7ee5c33d30c30a553 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Tue, 11 May 2010 23:51:37 +0200 Subject: rt2x00: Consistently name skb frame descriptor skbdesc. The skb frame descriptor is called everywhere skbdesc, except in one place in rt2x00debug_dump_frame. Change that occurence to have consistent naming. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00debug.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 70c04c282efc..9e2eed51e167 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -155,7 +155,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, enum rt2x00_dump_type type, struct sk_buff *skb) { struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf; - struct skb_frame_desc *desc = get_skb_frame_desc(skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); struct sk_buff *skbcopy; struct rt2x00dump_hdr *dump_hdr; struct timeval timestamp; @@ -170,7 +170,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, return; } - skbcopy = alloc_skb(sizeof(*dump_hdr) + desc->desc_len + skb->len, + skbcopy = alloc_skb(sizeof(*dump_hdr) + skbdesc->desc_len + skb->len, GFP_ATOMIC); if (!skbcopy) { DEBUG(rt2x00dev, "Failed to copy skb for dump.\n"); @@ -180,18 +180,19 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr)); dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION); dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr)); - dump_hdr->desc_length = cpu_to_le32(desc->desc_len); + dump_hdr->desc_length = cpu_to_le32(skbdesc->desc_len); dump_hdr->data_length = cpu_to_le32(skb->len); dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt); dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf); dump_hdr->chip_rev = cpu_to_le16(rt2x00dev->chip.rev); dump_hdr->type = cpu_to_le16(type); - dump_hdr->queue_index = desc->entry->queue->qid; - dump_hdr->entry_index = desc->entry->entry_idx; + dump_hdr->queue_index = skbdesc->entry->queue->qid; + dump_hdr->entry_index = skbdesc->entry->entry_idx; dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec); dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec); - memcpy(skb_put(skbcopy, desc->desc_len), desc->desc, desc->desc_len); + memcpy(skb_put(skbcopy, skbdesc->desc_len), skbdesc->desc, + skbdesc->desc_len); memcpy(skb_put(skbcopy, skb->len), skb->data, skb->len); skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy); -- cgit v1.2.3 From 6b97cb04f2766513c57b57f8ac4b44915296230f Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Tue, 11 May 2010 23:51:38 +0200 Subject: rt2x00: Fix beacon descriptor writing for rt61pci. The buffer address descriptor word is not part of the TXINFO structure needed for beacons. The current writing of that word for beacons is therefore an out-of-bounds write. Fix this by only writing the buffer address descriptor word for TX queues. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 24363634e6fd..99c298100fb6 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1801,12 +1801,12 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); - rt2x00_desc_read(txd, 6, &word); - rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, - skbdesc->skb_dma); - rt2x00_desc_write(txd, 6, word); + if (txdesc->queue != QID_BEACON) { + rt2x00_desc_read(txd, 6, &word); + rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, + skbdesc->skb_dma); + rt2x00_desc_write(txd, 6, word); - if (skbdesc->desc_len > TXINFO_SIZE) { rt2x00_desc_read(txd, 11, &word); rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, txdesc->length); -- cgit v1.2.3 From e01f1ec35ff91c8a3f4a3e48a0c8ab476124b973 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Tue, 11 May 2010 23:51:39 +0200 Subject: rt2x00: Re-order tx descriptor writing code in drivers. Where possible, write the tx descriptor words from start to end, to follow a logical ordering of words. Where this is not possible (in rt2400pci, rt2500pci and rt61pci) add a comment as to why word 0 needs to be written last. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 5 ++++ drivers/net/wireless/rt2x00/rt2500pci.c | 5 ++++ drivers/net/wireless/rt2x00/rt2500usb.c | 36 +++++++++++------------ drivers/net/wireless/rt2x00/rt61pci.c | 5 ++++ drivers/net/wireless/rt2x00/rt73usb.c | 52 ++++++++++++++++----------------- 5 files changed, 59 insertions(+), 44 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 4b3845152e1f..1eff6ec88457 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1039,6 +1039,11 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1); rt2x00_desc_write(txd, 4, word); + /* + * Writing TXD word 0 must the last to prevent a race condition with + * the device, whereby the device may take hold of the TXD before we + * finished updating it. + */ rt2x00_desc_read(txd, 0, &word); rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); rt2x00_set_field32(&word, TXD_W0_VALID, 1); diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d876c6d87591..8d3e95e0dcfe 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1193,6 +1193,11 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)); rt2x00_desc_write(txd, 10, word); + /* + * Writing TXD word 0 must the last to prevent a race condition with + * the device, whereby the device may take hold of the TXD before we + * finished updating it. + */ rt2x00_desc_read(txd, 0, &word); rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); rt2x00_set_field32(&word, TXD_W0_VALID, 1); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 30c0544e8036..9a915be547b3 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1039,6 +1039,24 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * Start writing the descriptor words. */ + rt2x00_desc_read(txd, 0, &word); + rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit); + rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_ACK, + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_OFDM, + (txdesc->rate_mode == RATE_MODE_OFDM)); + rt2x00_set_field32(&word, TXD_W0_NEW_SEQ, + test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length); + rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher); + rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx); + rt2x00_desc_write(txd, 0, word); + rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs); @@ -1057,24 +1075,6 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, _rt2x00_desc_write(txd, 3, skbdesc->iv[0]); _rt2x00_desc_write(txd, 4, skbdesc->iv[1]); } - - rt2x00_desc_read(txd, 0, &word); - rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit); - rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_OFDM, - (txdesc->rate_mode == RATE_MODE_OFDM)); - rt2x00_set_field32(&word, TXD_W0_NEW_SEQ, - test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length); - rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher); - rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx); - rt2x00_desc_write(txd, 0, word); } /* diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 99c298100fb6..55aa010aeee2 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1813,6 +1813,11 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 11, word); } + /* + * Writing TXD word 0 must the last to prevent a race condition with + * the device, whereby the device may take hold of the TXD before we + * finished updating it. + */ rt2x00_desc_read(txd, 0, &word); rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); rt2x00_set_field32(&word, TXD_W0_VALID, 1); diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 81f6db1b16f2..fa40d434e729 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1446,6 +1446,32 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * Start writing the descriptor words. */ + rt2x00_desc_read(txd, 0, &word); + rt2x00_set_field32(&word, TXD_W0_BURST, + test_bit(ENTRY_TXD_BURST, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_VALID, 1); + rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_ACK, + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_OFDM, + (txdesc->rate_mode == RATE_MODE_OFDM)); + rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); + rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, + test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, + test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_KEY_TABLE, + test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length); + rt2x00_set_field32(&word, TXD_W0_BURST2, + test_bit(ENTRY_TXD_BURST, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); + rt2x00_desc_write(txd, 0, word); + rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue); rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); @@ -1473,32 +1499,6 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, TXPOWER_TO_DEV(rt2x00dev->tx_power)); rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); - - rt2x00_desc_read(txd, 0, &word); - rt2x00_set_field32(&word, TXD_W0_BURST, - test_bit(ENTRY_TXD_BURST, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_VALID, 1); - rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_OFDM, - (txdesc->rate_mode == RATE_MODE_OFDM)); - rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); - rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, - test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, - test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_KEY_TABLE, - test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length); - rt2x00_set_field32(&word, TXD_W0_BURST2, - test_bit(ENTRY_TXD_BURST, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); - rt2x00_desc_write(txd, 0, word); } /* -- cgit v1.2.3 From 85b7a8b3871bde7885516fed2a1c8da699913318 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Tue, 11 May 2010 23:51:40 +0200 Subject: rt2x00: Simplify TXD handling of beacons. The handling of tx descriptors for beacons can be simplified by updating write_tx_desc implementations of each driver to write directly to the queue entry descriptor instead of to a provided memory area. This is also a preparation for further clean ups where descriptors are properly reserved in the skb instead of fiddling with the skb data pointer. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 21 +++++++++------------ drivers/net/wireless/rt2x00/rt2500pci.c | 21 +++++++++------------ drivers/net/wireless/rt2x00/rt2500usb.c | 21 ++++++++++++--------- drivers/net/wireless/rt2x00/rt2800pci.c | 14 ++++++++++---- drivers/net/wireless/rt2x00/rt2800usb.c | 8 +++++++- drivers/net/wireless/rt2x00/rt2x00pci.c | 9 --------- drivers/net/wireless/rt2x00/rt2x00queue.c | 10 ---------- drivers/net/wireless/rt2x00/rt2x00usb.c | 8 -------- drivers/net/wireless/rt2x00/rt61pci.c | 20 +++++++++++++------- drivers/net/wireless/rt2x00/rt73usb.c | 21 ++++++++++++--------- 10 files changed, 72 insertions(+), 81 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 1eff6ec88457..def3fa45ae7a 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1006,15 +1006,15 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data; - __le32 *txd = skbdesc->desc; + __le32 *txd = entry_priv->desc; u32 word; /* * Start writing the descriptor words. */ - rt2x00_desc_read(entry_priv->desc, 1, &word); + rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); - rt2x00_desc_write(entry_priv->desc, 1, word); + rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 2, &word); rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, txdesc->length); @@ -1059,6 +1059,12 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); rt2x00_desc_write(txd, 0, word); + + /* + * Register descriptor details in skb frame descriptor. + */ + skbdesc->desc = txd; + skbdesc->desc_len = TXD_DESC_SIZE; } /* @@ -1081,15 +1087,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry, rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); rt2x00pci_register_write(rt2x00dev, CSR14, reg); - /* - * Replace rt2x00lib allocated descriptor with the - * pointer to the _real_ hardware descriptor. - * After that, map the beacon to DMA and update the - * descriptor. - */ - memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len); - skbdesc->desc = entry_priv->desc; - rt2x00queue_map_txskb(rt2x00dev, entry->skb); rt2x00_desc_read(entry_priv->desc, 1, &word); diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 8d3e95e0dcfe..070c23ed4013 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1164,15 +1164,15 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data; - __le32 *txd = skbdesc->desc; + __le32 *txd = entry_priv->desc; u32 word; /* * Start writing the descriptor words. */ - rt2x00_desc_read(entry_priv->desc, 1, &word); + rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); - rt2x00_desc_write(entry_priv->desc, 1, word); + rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 2, &word); rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER); @@ -1216,6 +1216,12 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); + + /* + * Register descriptor details in skb frame descriptor. + */ + skbdesc->desc = txd; + skbdesc->desc_len = TXD_DESC_SIZE; } /* @@ -1238,15 +1244,6 @@ static void rt2500pci_write_beacon(struct queue_entry *entry, rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); rt2x00pci_register_write(rt2x00dev, CSR14, reg); - /* - * Replace rt2x00lib allocated descriptor with the - * pointer to the _real_ hardware descriptor. - * After that, map the beacon to DMA and update the - * descriptor. - */ - memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len); - skbdesc->desc = entry_priv->desc; - rt2x00queue_map_txskb(rt2x00dev, entry->skb); rt2x00_desc_read(entry_priv->desc, 1, &word); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 9a915be547b3..b985d8f8cc6e 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1033,7 +1033,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txd = skbdesc->desc; + __le32 *txd = (__le32 *)(skb->data - TXD_DESC_SIZE); u32 word; /* @@ -1075,6 +1075,12 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, _rt2x00_desc_write(txd, 3, skbdesc->iv[0]); _rt2x00_desc_write(txd, 4, skbdesc->iv[1]); } + + /* + * Register descriptor details in skb frame descriptor. + */ + skbdesc->desc = txd; + skbdesc->desc_len = TXD_DESC_SIZE; } /* @@ -1088,18 +1094,10 @@ static void rt2500usb_write_beacon(struct queue_entry *entry, struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint); int length; u16 reg, reg0; - /* - * Add the descriptor in front of the skb. - */ - skb_push(entry->skb, entry->queue->desc_size); - memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); - skbdesc->desc = entry->skb->data; - /* * Disable beaconing while we are reloading the beacon data, * otherwise we might be sending out invalid data. @@ -1108,6 +1106,11 @@ static void rt2500usb_write_beacon(struct queue_entry *entry, rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + /* + * Take the descriptor in front of the skb into account. + */ + skb_push(entry->skb, TXD_DESC_SIZE); + /* * USB devices cannot blindly pass the skb->len as the * length of the data to usb_fill_bulk_urb. Pass the skb diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 7d4778d66e77..b2f23272c3aa 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -633,7 +633,8 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txd = skbdesc->desc; + struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data; + __le32 *txd = entry_priv->desc; u32 word; /* @@ -657,15 +658,14 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W1_BURST, test_bit(ENTRY_TXD_BURST, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W1_SD_LEN0, - rt2x00dev->ops->extra_tx_headroom); + rt2x00_set_field32(&word, TXD_W1_SD_LEN0, TXWI_DESC_SIZE); rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0); rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0); rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 2, &word); rt2x00_set_field32(&word, TXD_W2_SD_PTR1, - skbdesc->skb_dma + rt2x00dev->ops->extra_tx_headroom); + skbdesc->skb_dma + TXWI_DESC_SIZE); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 3, &word); @@ -673,6 +673,12 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W3_QSEL, 2); rt2x00_desc_write(txd, 3, word); + + /* + * Register descriptor details in skb frame descriptor. + */ + skbdesc->desc = txd; + skbdesc->desc_len = TXD_DESC_SIZE; } /* diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index d48d705d1808..1b87daa19456 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -400,7 +400,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txi = skbdesc->desc; + __le32 *txi = (__le32 *)(skb->data - TXWI_DESC_SIZE - TXINFO_DESC_SIZE); u32 word; /* @@ -422,6 +422,12 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_BURST, test_bit(ENTRY_TXD_BURST, &txdesc->flags)); rt2x00_desc_write(txi, 0, word); + + /* + * Register descriptor details in skb frame descriptor. + */ + skbdesc->desc = txi; + skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; } /* diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 2fe9f295351f..ff80ef710d4e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -66,8 +66,6 @@ int rt2x00pci_write_tx_data(struct queue_entry *entry, struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc; /* * This should not happen, we already checked the entry @@ -82,13 +80,6 @@ int rt2x00pci_write_tx_data(struct queue_entry *entry, return -EINVAL; } - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(entry->skb); - skbdesc->desc = entry_priv->desc; - skbdesc->desc_len = entry->queue->desc_size; - return 0; } EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 97b2c7650656..891d5f72716e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -552,7 +552,6 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf = vif_to_intf(vif); struct skb_frame_desc *skbdesc; struct txentry_desc txdesc; - __le32 desc[16]; if (unlikely(!intf->beacon)) return -ENOBUFS; @@ -584,20 +583,11 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, */ rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); - /* - * For the descriptor we use a local array from where the - * driver can move it to the correct location required for - * the hardware. - */ - memset(desc, 0, sizeof(desc)); - /* * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(intf->beacon->skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->desc = desc; - skbdesc->desc_len = intf->beacon->queue->desc_size; skbdesc->entry = intf->beacon; /* diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index acf3282fc13e..a4f0551422ae 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -221,7 +221,6 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry, struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); struct queue_entry_priv_usb *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc; u32 length; /* @@ -230,13 +229,6 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry, skb_push(entry->skb, entry->queue->desc_size); memset(entry->skb->data, 0, entry->queue->desc_size); - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(entry->skb); - skbdesc->desc = entry->skb->data; - skbdesc->desc_len = entry->queue->desc_size; - /* * USB devices cannot blindly pass the skb->len as the * length of the data to usb_fill_bulk_urb. Pass the skb diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 55aa010aeee2..1be1d7d585d8 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1763,7 +1763,8 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txd = skbdesc->desc; + struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data; + __le32 *txd = entry_priv->desc; u32 word; /* @@ -1842,6 +1843,13 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, test_bit(ENTRY_TXD_BURST, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); rt2x00_desc_write(txd, 0, word); + + /* + * Register descriptor details in skb frame descriptor. + */ + skbdesc->desc = txd; + skbdesc->desc_len = + (txdesc->queue == QID_BEACON) ? TXINFO_SIZE : TXD_DESC_SIZE; } /* @@ -1851,7 +1859,7 @@ static void rt61pci_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + struct queue_entry_priv_pci *entry_priv = entry->priv_data; unsigned int beacon_base; u32 reg; @@ -1867,11 +1875,9 @@ static void rt61pci_write_beacon(struct queue_entry *entry, * Write entire beacon with descriptor to register. */ beacon_base = HW_BEACON_OFFSET(entry->entry_idx); - rt2x00pci_register_multiwrite(rt2x00dev, - beacon_base, - skbdesc->desc, skbdesc->desc_len); - rt2x00pci_register_multiwrite(rt2x00dev, - beacon_base + skbdesc->desc_len, + rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, + entry_priv->desc, TXINFO_SIZE); + rt2x00pci_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE, entry->skb->data, entry->skb->len); /* diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index fa40d434e729..fca661c2e2a3 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1440,7 +1440,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txd = skbdesc->desc; + __le32 *txd = (__le32 *)(skb->data - TXD_DESC_SIZE); u32 word; /* @@ -1499,6 +1499,12 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, TXPOWER_TO_DEV(rt2x00dev->tx_power)); rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); + + /* + * Register descriptor details in skb frame descriptor. + */ + skbdesc->desc = txd; + skbdesc->desc_len = TXD_DESC_SIZE; } /* @@ -1508,17 +1514,9 @@ static void rt73usb_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); unsigned int beacon_base; u32 reg; - /* - * Add the descriptor in front of the skb. - */ - skb_push(entry->skb, entry->queue->desc_size); - memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); - skbdesc->desc = entry->skb->data; - /* * Disable beaconing while we are reloading the beacon data, * otherwise we might be sending out invalid data. @@ -1527,6 +1525,11 @@ static void rt73usb_write_beacon(struct queue_entry *entry, rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); + /* + * Take the descriptor in front of the skb into account. + */ + skb_push(entry->skb, TXD_DESC_SIZE); + /* * Write entire beacon with descriptor to register. */ -- cgit v1.2.3 From 185e5f77f891d5bc7a0d8c8eb2b1edf6c317edab Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Tue, 11 May 2010 23:51:41 +0200 Subject: rt2x00: Dump beacons under a different identifier than TX frames. This allows for specific identification of beacons in the debugfs frame stream. Preparation for later differences between dumped TX frames and dumped beacons. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dump.h | 3 +++ drivers/net/wireless/rt2x00/rt2x00queue.c | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h index 727019a748e7..ed303b423e41 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dump.h +++ b/drivers/net/wireless/rt2x00/rt2x00dump.h @@ -62,11 +62,14 @@ * the tx event which has either succeeded or failed. A frame * with this type should also have been reported with as a * %DUMP_FRAME_TX frame. + * @DUMP_FRAME_BEACON: This beacon frame is queued for transmission to the + * hardware. */ enum rt2x00_dump_type { DUMP_FRAME_RXDONE = 1, DUMP_FRAME_TX = 2, DUMP_FRAME_TXDONE = 3, + DUMP_FRAME_BEACON = 4, }; /** diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 891d5f72716e..c68bf3216166 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -420,6 +420,7 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, { struct data_queue *queue = entry->queue; struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + enum rt2x00_dump_type dump_type; rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry->skb, txdesc); @@ -427,7 +428,9 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, * All processing on the frame has been completed, this means * it is now ready to be dumped to userspace through debugfs. */ - rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, entry->skb); + dump_type = (txdesc->queue == QID_BEACON) ? + DUMP_FRAME_BEACON : DUMP_FRAME_TX; + rt2x00debug_dump_frame(rt2x00dev, dump_type, entry->skb); } static void rt2x00queue_kick_tx_queue(struct queue_entry *entry, -- cgit v1.2.3 From fd76f148ebc67d662f71f00128c8ddb0538168c0 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Tue, 11 May 2010 23:51:43 +0200 Subject: rt2x00: In debugfs frame dumping allow the TX descriptor to be part of the skb. Preparation for futher cleanups in the area of properly maintaining the skb data without fiddling with the skb->data pointer. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00debug.c | 14 ++++++++++---- drivers/net/wireless/rt2x00/rt2x00queue.h | 3 +++ 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 9e2eed51e167..1e81eef9ca1a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -159,6 +159,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, struct sk_buff *skbcopy; struct rt2x00dump_hdr *dump_hdr; struct timeval timestamp; + u32 data_len; do_gettimeofday(×tamp); @@ -170,7 +171,11 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, return; } - skbcopy = alloc_skb(sizeof(*dump_hdr) + skbdesc->desc_len + skb->len, + data_len = skb->len; + if (skbdesc->flags & SKBDESC_DESC_IN_SKB) + data_len -= skbdesc->desc_len; + + skbcopy = alloc_skb(sizeof(*dump_hdr) + skbdesc->desc_len + data_len, GFP_ATOMIC); if (!skbcopy) { DEBUG(rt2x00dev, "Failed to copy skb for dump.\n"); @@ -181,7 +186,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION); dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr)); dump_hdr->desc_length = cpu_to_le32(skbdesc->desc_len); - dump_hdr->data_length = cpu_to_le32(skb->len); + dump_hdr->data_length = cpu_to_le32(data_len); dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt); dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf); dump_hdr->chip_rev = cpu_to_le16(rt2x00dev->chip.rev); @@ -191,8 +196,9 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec); dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec); - memcpy(skb_put(skbcopy, skbdesc->desc_len), skbdesc->desc, - skbdesc->desc_len); + if (!(skbdesc->flags & SKBDESC_DESC_IN_SKB)) + memcpy(skb_put(skbcopy, skbdesc->desc_len), skbdesc->desc, + skbdesc->desc_len); memcpy(skb_put(skbcopy, skb->len), skb->data, skb->len); skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 36a957adc1f9..f79170849add 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -94,12 +94,15 @@ enum data_queue_qid { * mac80211 but was stripped for processing by the driver. * @SKBDESC_NOT_MAC80211: Frame didn't originate from mac80211, * don't try to pass it back. + * @SKBDESC_DESC_IN_SKB: The descriptor is at the start of the + * skb, instead of in the desc field. */ enum skb_frame_desc_flags { SKBDESC_DMA_MAPPED_RX = 1 << 0, SKBDESC_DMA_MAPPED_TX = 1 << 1, SKBDESC_IV_STRIPPED = 1 << 2, SKBDESC_NOT_MAC80211 = 1 << 3, + SKBDESC_DESC_IN_SKB = 1 << 4, }; /** -- cgit v1.2.3 From a4b770972b8f819e408d7cc3ae9637e15bff62f6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 14 May 2010 00:19:28 -0700 Subject: drivers/net: Remove unnecessary returns from void function()s This patch removes from drivers/net/ all the unnecessary return; statements that precede the last closing brace of void functions. It does not remove the returns that are immediately preceded by a label as gcc doesn't like that. It also does not remove null void functions with return. Done via: $ grep -rP --include=*.[ch] -l "return;\n}" net/ | \ xargs perl -i -e 'local $/ ; while (<>) { s/\n[ \t\n]+return;\n}/\n}/g; print; }' with some cleanups by hand. Compile tested x86 allmodconfig only. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/wireless/at76c50x-usb.c | 1 - drivers/net/wireless/ath/ath5k/phy.c | 2 -- drivers/net/wireless/ath/ath5k/reset.c | 3 --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 1 - drivers/net/wireless/ath/ath9k/calib.c | 1 - drivers/net/wireless/ath/ath9k/eeprom.c | 2 -- drivers/net/wireless/ath/ath9k/eeprom_def.c | 3 --- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 1 - drivers/net/wireless/ath/regd.c | 1 - drivers/net/wireless/ipw2x00/ipw2100.c | 1 - drivers/net/wireless/ipw2x00/ipw2200.c | 2 -- drivers/net/wireless/ipw2x00/libipw_rx.c | 1 - drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 -- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 -- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl-calib.c | 2 -- drivers/net/wireless/iwlwifi/iwl-core.c | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 - drivers/net/wireless/iwmc3200wifi/sdio.c | 2 -- drivers/net/wireless/libertas/debugfs.c | 3 --- drivers/net/wireless/libertas/if_usb.c | 4 ---- drivers/net/wireless/libertas/rx.c | 1 - drivers/net/wireless/libertas_tf/if_usb.c | 1 - drivers/net/wireless/libertas_tf/main.c | 1 - drivers/net/wireless/orinoco/main.c | 2 -- drivers/net/wireless/p54/p54usb.c | 1 - drivers/net/wireless/prism54/isl_ioctl.c | 2 -- drivers/net/wireless/ray_cs.c | 5 ----- drivers/net/wireless/rt2x00/rt2x00debug.c | 2 -- drivers/net/wireless/wl12xx/wl1251_rx.c | 2 -- drivers/net/wireless/wl3501_cs.c | 2 -- drivers/net/wireless/zd1201.c | 3 --- 32 files changed, 59 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 7a626d4e100f..8a2d4afc74f8 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -1223,7 +1223,6 @@ static void at76_rx_callback(struct urb *urb) priv->rx_tasklet.data = (unsigned long)urb; tasklet_schedule(&priv->rx_tasklet); - return; } static int at76_submit_rx_urb(struct at76_priv *priv) diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 3ce9afba1d88..1b81c4778800 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -2145,8 +2145,6 @@ ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah, done: *pcinfo_l = &pcinfo[idx_l]; *pcinfo_r = &pcinfo[idx_r]; - - return; } /* diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 44bbbf2a6edd..307f80e83f94 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -627,7 +627,6 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); } - return; } /* TODO: Half/Quarter rate */ @@ -883,8 +882,6 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, /* Heavy clipping -disable for now */ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1) ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE); - - return; } /* diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 5fcafb460877..56a9e5fa6d66 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -726,7 +726,6 @@ static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) TX_IQ_CAL_FAILED: ath_print(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); - return; } static bool ar9003_hw_init_cal(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 6982577043b8..07b8fa6fb62f 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -86,7 +86,6 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); } } - return; } static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index bd9dff3293dc..ca8704a9d7ac 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -36,8 +36,6 @@ void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask, if (ah->config.analog_shiftreg) udelay(100); - - return; } int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight, diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index e591ad6016e5..7e1ed78d0e64 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -50,7 +50,6 @@ static void ath9k_get_txgain_index(struct ath_hw *ah, i++; *pcdacIdx = i; - return; } static void ath9k_olc_get_pdadcs(struct ath_hw *ah, @@ -751,8 +750,6 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, pPDADCValues[k] = pPDADCValues[k - 1]; k++; } - - return; } static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 28abc7d5e909..2571b443ac82 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -663,7 +663,6 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, return; err: dev_kfree_skb_any(skb); - return; } /* FIXME: Locking for cleanup/init */ diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 24d59883d944..3f4244f56ce5 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -333,7 +333,6 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy, ath_reg_apply_active_scan_flags(wiphy, initiator); break; } - return; } int ath_reg_notifier_apply(struct wiphy *wiphy, diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 2088ac029b35..a59ceb26cd83 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -3239,7 +3239,6 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv) IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX, txq->next); } - return; } static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 82de71a3aea7..3aa3bb18f615 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -2607,8 +2607,6 @@ static inline void eeprom_write_reg(struct ipw_priv *p, u32 data) /* the eeprom requires some time to complete the operation */ udelay(p->eeprom_delay); - - return; } /* perform a chip select operation */ diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index 39a34da52d52..0de1b1893220 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c @@ -918,7 +918,6 @@ void libipw_rx_any(struct libipw_device *ieee, drop_free: dev_kfree_skb_irq(skb); ieee->dev->stats.rx_dropped++; - return; } #define MGMT_FRAME_FIXED_PART_LENGTH 0x24 diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 32eb4709acac..8e84a08ff951 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -545,8 +545,6 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband spin_unlock_irqrestore(&rs_sta->lock, flags); IWL_DEBUG_RATE(priv, "leave\n"); - - return; } static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index bfcac5608d87..cf4a95bae4ff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2337,8 +2337,6 @@ out: tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); i = index; lq_sta->last_txrate_idx = i; - - return; } /** diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a672d3379cfd..cc15e929a987 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2494,7 +2494,6 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) } mutex_unlock(&priv->mutex); - return; } static void iwl_bg_restart(struct work_struct *data) diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index f1fd00b1a65d..7e8227773213 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -638,8 +638,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time); iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis); iwl_sensitivity_write(priv); - - return; } EXPORT_SYMBOL(iwl_sensitivity_calibration); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 4cdf4d3a9ddb..87eb89f000f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -769,7 +769,6 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) "extension channel offset 0x%x\n", le32_to_cpu(rxon->flags), ht_conf->ht_protection, ht_conf->extension_chan_offset); - return; } EXPORT_SYMBOL(iwl_set_rxon_ht); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c7e1d7d09e02..1beb81c0be68 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -848,7 +848,6 @@ static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv, #endif IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status); - return; } static void iwl3945_bg_beacon_update(struct work_struct *work) diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c index 1acea37f39f8..edcb52330cf5 100644 --- a/drivers/net/wireless/iwmc3200wifi/sdio.c +++ b/drivers/net/wireless/iwmc3200wifi/sdio.c @@ -479,8 +479,6 @@ static void iwm_sdio_remove(struct sdio_func *func) sdio_set_drvdata(func, NULL); dev_info(dev, "IWM SDIO remove\n"); - - return; } static const struct sdio_device_id iwm_sdio_ids[] = { diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 6f5b843c1f44..de2caac11dd6 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -757,15 +757,12 @@ void lbs_debugfs_init(void) { if (!lbs_dir) lbs_dir = debugfs_create_dir("lbs_wireless", NULL); - - return; } void lbs_debugfs_remove(void) { if (lbs_dir) debugfs_remove(lbs_dir); - return; } void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev) diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index fcea5741ba62..f41594c7ac16 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -133,8 +133,6 @@ static void if_usb_write_bulk_callback(struct urb *urb) /* print the failure status number for debug */ lbs_pr_info("URB in failure status: %d\n", urb->status); } - - return; } /** @@ -651,8 +649,6 @@ static void if_usb_receive_fwload(struct urb *urb) if_usb_submit_rx_urb_fwload(cardp); kfree(syncfwheader); - - return; } #define MRVDRV_MIN_PKT_LEN 30 diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index e2b8d886b091..a115bfa9513a 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -90,7 +90,6 @@ static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd) priv->nextSNRNF++; if (priv->nextSNRNF >= DEFAULT_DATA_AVG_FACTOR) priv->nextSNRNF = 0; - return; } /** diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index 4412c279ca94..c445500ffc61 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c @@ -576,7 +576,6 @@ static void if_usb_receive_fwload(struct urb *urb) kfree(syncfwheader); lbtf_deb_leave(LBTF_DEB_USB); - return; } #define MRVDRV_MIN_PKT_LEN 30 diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 60787de56f3a..6a04c2157f73 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -360,7 +360,6 @@ static void lbtf_op_stop(struct ieee80211_hw *hw) lbtf_set_radio_control(priv); lbtf_deb_leave(LBTF_DEB_MACOPS); - return; } static int lbtf_op_add_interface(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 97e954ee17f8..ca71f08709bc 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -1618,8 +1618,6 @@ void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) /* We don't actually do anything about it */ break; } - - return; } EXPORT_SYMBOL(__orinoco_ev_info); diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 743a6c68b29d..d5b197b4d5bb 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -875,7 +875,6 @@ static void p54u_stop(struct ieee80211_hw *dev) the hardware is still usable next time we want to start it. until then, we just stop listening to the hardware.. */ p54u_free_urbs(dev); - return; } static int __devinit p54u_probe(struct usb_interface *intf, diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index a45818ebfdfb..8d1190c0f062 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -210,8 +210,6 @@ prism54_update_stats(struct work_struct *work) priv->local_iwstatistics.discard.retries = r.u; mutex_unlock(&priv->stats_lock); - - return; } struct iw_statistics * diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 73972ee76540..3886b21becd9 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -735,8 +735,6 @@ static void verify_dl_startup(u_long data) start_net((u_long) local); else join_net((u_long) local); - - return; } /* end verify_dl_startup */ /*===========================================================================*/ @@ -764,7 +762,6 @@ static void start_net(u_long data) return; } local->card_status = CARD_DOING_ACQ; - return; } /* end start_net */ /*===========================================================================*/ @@ -795,7 +792,6 @@ static void join_net(u_long data) return; } local->card_status = CARD_DOING_ACQ; - return; } /*============================================================================ @@ -1626,7 +1622,6 @@ static int ray_dev_close(struct net_device *dev) static void ray_reset(struct net_device *dev) { pr_debug("ray_reset entered\n"); - return; } /*===========================================================================*/ diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 9569fb4e5bc5..e2497f820d75 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -700,8 +700,6 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) exit: rt2x00debug_deregister(rt2x00dev); ERROR(rt2x00dev, "Failed to register debug handler.\n"); - - return; } void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c index af5c67b4da95..851515836a7f 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ b/drivers/net/wireless/wl12xx/wl1251_rx.c @@ -183,6 +183,4 @@ void wl1251_rx(struct wl1251 *wl) /* Finally, we need to ACK the RX */ wl1251_rx_ack(wl); - - return; } diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 1e61e6cace90..6449fe3d128f 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1452,8 +1452,6 @@ static void wl3501_detach(struct pcmcia_device *link) if (link->priv) free_netdev(link->priv); - - return; } static int wl3501_get_name(struct net_device *dev, struct iw_request_info *info, diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index ece86a5d3355..390d77f762c4 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -134,7 +134,6 @@ static void zd1201_usbfree(struct urb *urb) kfree(urb->transfer_buffer); usb_free_urb(urb); - return; } /* cmdreq message: @@ -185,7 +184,6 @@ static void zd1201_usbtx(struct urb *urb) { struct zd1201 *zd = urb->context; netif_wake_queue(zd->dev); - return; } /* Incoming data */ @@ -407,7 +405,6 @@ exit: wake_up(&zd->rxdataq); kfree(urb->transfer_buffer); } - return; } static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata, -- cgit v1.2.3 From ee289b6440c3b0ccb9459495783e8c299bec6604 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 17 May 2010 22:47:34 -0700 Subject: drivers/net: remove useless semicolons switch and while statements don't need semicolons at end of statement [ Fixup minor conflicts with recent wimax merge... -DaveM ] Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/wireless/ath/ath9k/init.c | 2 +- drivers/net/wireless/hostap/hostap_ap.c | 2 +- drivers/net/wireless/hostap/hostap_download.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/prism54/islpci_dev.c | 2 +- drivers/net/wireless/rt2x00/rt2x00firmware.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 8c795488ebc3..d457cb3bd772 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -308,7 +308,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, dd->dd_desc_len += dma_len; ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); - }; + } } /* allocate descriptors */ diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 7e72ac1de49b..231dbd77f5f5 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -349,7 +349,7 @@ static int ap_control_proc_read(char *page, char **start, off_t off, default: policy_txt = "unknown"; break; - }; + } p += sprintf(p, "MAC policy: %s\n", policy_txt); p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries); p += sprintf(p, "MAC list:\n"); diff --git a/drivers/net/wireless/hostap/hostap_download.c b/drivers/net/wireless/hostap/hostap_download.c index 89d3849abfe0..e73bf739fd9b 100644 --- a/drivers/net/wireless/hostap/hostap_download.c +++ b/drivers/net/wireless/hostap/hostap_download.c @@ -744,7 +744,7 @@ static int prism2_download(local_info_t *local, local->dev->name, param->dl_cmd); ret = -EINVAL; break; - }; + } out: if (ret == 0 && dl && diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 637d7b62fb56..1004cfc403b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -932,7 +932,7 @@ static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) else decrypt_out |= RX_RES_STATUS_DECRYPT_OK; break; - }; + } IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", decrypt_in, decrypt_out); diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 10d91afefa33..2c8cc954d1b6 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -946,7 +946,7 @@ islpci_set_state(islpci_private *priv, islpci_state_t new_state) if (!priv->state_off) priv->state = new_state; break; - }; + } #if 0 printk(KERN_DEBUG "%s: state transition %d -> %d (off#%d)\n", priv->ndev->name, old_state, new_state, priv->state_off); diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index 34beb00c4347..b818a43c4672 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -79,7 +79,7 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) ERROR(rt2x00dev, "Current firmware does not support detected chipset.\n"); goto exit; - }; + } rt2x00dev->fw = fw; -- cgit v1.2.3