From 62bb2ac5cb6c2f813e151617525ec518e2d1c649 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 17 Feb 2010 21:27:26 +0100 Subject: mac80211: deprecate RX status noise The noise value as is won't be used, isn't filled by most drivers and doesn't really make a whole lot of sense on a per packet basis -- proper cfg80211 survey support in mac80211 will need to be different. Mark the struct member as deprecated so it will be removed from drivers. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 4 ++-- net/mac80211/debugfs_sta.c | 2 -- net/mac80211/rx.c | 9 --------- net/mac80211/sta_info.h | 2 -- 4 files changed, 2 insertions(+), 15 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 45d7d44d7cb..936bc410d06 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -543,7 +543,7 @@ enum mac80211_rx_flags { * @signal: signal strength when receiving this frame, either in dBm, in dB or * unspecified depending on the hardware capabilities flags * @IEEE80211_HW_SIGNAL_* - * @noise: noise when receiving this frame, in dBm. + * @noise: noise when receiving this frame, in dBm (DEPRECATED). * @antenna: antenna used * @rate_idx: index of data rate into band's supported rates or MCS index if * HT rates are use (RX_FLAG_HT) @@ -554,7 +554,7 @@ struct ieee80211_rx_status { enum ieee80211_band band; int freq; int signal; - int noise; + int noise __deprecated; int antenna; int rate_idx; int flag; diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index d92800bb2d2..23e72003457 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -57,7 +57,6 @@ STA_FILE(tx_filtered, tx_filtered_count, LU); STA_FILE(tx_retry_failed, tx_retry_failed, LU); STA_FILE(tx_retry_count, tx_retry_count, LU); STA_FILE(last_signal, last_signal, D); -STA_FILE(last_noise, last_noise, D); STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU); static ssize_t sta_flags_read(struct file *file, char __user *userbuf, @@ -289,7 +288,6 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) DEBUGFS_ADD(tx_retry_failed); DEBUGFS_ADD(tx_retry_count); DEBUGFS_ADD(last_signal); - DEBUGFS_ADD(last_noise); DEBUGFS_ADD(wep_weak_iv_count); DEBUGFS_ADD(ht_capa); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b5c48de81d8..1da57c8e849 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -178,14 +178,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, pos++; } - /* IEEE80211_RADIOTAP_DBM_ANTNOISE */ - if (local->hw.flags & IEEE80211_HW_NOISE_DBM) { - *pos = status->noise; - rthdr->it_present |= - cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE); - pos++; - } - /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */ /* IEEE80211_RADIOTAP_ANTENNA */ @@ -1077,7 +1069,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) sta->rx_fragments++; sta->rx_bytes += rx->skb->len; sta->last_signal = status->signal; - sta->last_noise = status->noise; /* * Change STA power saving mode only at the end of a frame diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 822d8452293..2b635909de5 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -200,7 +200,6 @@ struct sta_ampdu_mlme { * @rx_fragments: number of received MPDUs * @rx_dropped: number of dropped MPDUs from this STA * @last_signal: signal of last received frame from this STA - * @last_noise: noise of last received frame from this STA * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) * @tx_filtered_count: number of frames the hardware filtered for this STA * @tx_retry_failed: number of frames that failed retry @@ -267,7 +266,6 @@ struct sta_info { unsigned long rx_fragments; unsigned long rx_dropped; int last_signal; - int last_noise; __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; /* Updated from TX status path only, no locking requirements */ -- cgit v1.2.3 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(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index ac67f02e26d..9e4ea19e720 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 8dce0077b02..c889d4992a6 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 aefe84f9c04..be69ebb2744 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 72474c0ccaf..ac2a57aba6a 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 9122a8556f4..d9cab7c3cff 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 a35a7db0fc4..8decf212691 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(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 9e4ea19e720..f4e50ef8406 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(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index f4e50ef8406..4de7fe03b9f 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 ac2a57aba6a..10ad877c2cd 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 8decf212691..8bd62c130b2 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(+) diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 4f752a21495..36f4c820ad0 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index fa9a0b35788..38fce4caf4a 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 2a864b24291..66319aabf26 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 67a82934f36..c26726a0623 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 2be76ee42bb..7d6d2e6c467 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 5cd94d5666c..b825cfa30ec 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 38fce4caf4a..c8b09718e18 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 66319aabf26..18347c3a5e1 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 c26726a0623..b422c9fdcd2 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 a803596dad4..86ff161ef24 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 97ea5096bc8..10135c94e20 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 b825cfa30ec..d00f7ed7f21 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 c8b09718e18..f2b6325ba2a 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 18347c3a5e1..6b3fd0005ce 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 b422c9fdcd2..a0f416972be 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c index d00f7ed7f21..c0826585a49 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 f2b6325ba2a..8501898950d 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 a0f416972be..f89e1b3ac1b 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 diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 60f10dce480..f41f886741f 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 7d6d2e6c467..f88d52e87e8 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 36a64e06f29..6759aa11c13 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 7468ef10194..5533519a141 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 c0826585a49..c8759acef13 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 8501898950d..95d2168f8af 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 6b3fd0005ce..54bc1e961cb 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 e2b1ebf096e..5a04482b935 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 6730f5b96e7..b7a7c0621ec 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 f89e1b3ac1b..51171d7d5da 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 86ff161ef24..00000000000 --- 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 3919102e942..2401e6035d5 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 811e739d05b..2b7dd9b76fe 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(-) diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 785e0244e30..9c6fdccf00f 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 f47ec94c16d..473a1e28799 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 54bc1e961cb..ea49cede4cb 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 diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 9c6fdccf00f..2f6733526f7 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 473a1e28799..27ddd2be0a9 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 00000000000..be5c14935bc --- /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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index ea49cede4cb..310f58c6623 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index be5c14935bc..7d7c8504185 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(+) diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index b7a7c0621ec..2df7852db9a 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 10135c94e20..cc974eae009 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 310f58c6623..5cc778f658b 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 2b7dd9b76fe..2e057b0e325 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 17e405a09ca..ca92bd81129 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 6759aa11c13..e029bf03809 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 2dc06c73532..4297205b8d6 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 5cc778f658b..81fb02e8292 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index cc974eae009..7f03f899b2b 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 81fb02e8292..184264a53b2 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 2e057b0e325..7926471cd09 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 184264a53b2..4d091ebd340 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index 2df7852db9a..b824c6cc2cc 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 4d091ebd340..a46d323f8a6 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 7f03f899b2b..457ce725027 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 a46d323f8a6..9f741686405 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 7d7c8504185..1f204db30c2 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 51171d7d5da..ed285fec2a0 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 457ce725027..41de47caa20 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 9f741686405..4c4d22acaee 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 7926471cd09..a32d3014781 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index a32d3014781..d3ed63e92cf 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 ca92bd81129..8b9f6b4f565 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 41de47caa20..0deb4fdf916 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 e029bf03809..d59b3830a6a 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 4c4d22acaee..f10ba847689 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 d3ed63e92cf..1b11e2caabd 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index f10ba847689..0a4ff7b02f5 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 1b11e2caabd..6d109df9a0a 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index f41f886741f..60e20876e6d 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 b4d59a9317e41faec3d0b6a03f0454d1e8abb710 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Tue, 23 Feb 2010 18:51:13 +0900 Subject: mac80211: fix rates setup on IBSS merge when an IBSS merge happened, the supported rates for the newly added station were left empty, causing the rate control module to be initialized with only the basic rates. also the section of the ibss code which deals with updating supported rates for an already existing station fails to inform the rate control module about the new rates. as i don't know how to fix this (minstrel does not have an update function), i have just added a comment for now. Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index f3e94248674..b840d9072de 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -276,6 +276,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, (unsigned long long) sta->sta.supp_rates[band]); #endif rcu_read_unlock(); + + /* FIXME: update rate control */ } else { rcu_read_unlock(); ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, @@ -370,6 +372,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, sdata->name, mgmt->bssid); #endif ieee80211_sta_join_ibss(sdata, bss); + supp_rates = ieee80211_sta_get_rates(local, elems, band); ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates, GFP_KERNEL); } -- 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(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2e767cf22f1..1fb14edfcb2 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 dbbf7ca5f97..20d90268ce3 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 efc420cd42b..589490b69dd 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 df13cce53a7b28a81460e6bfc4857e9df4956141 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Wed, 24 Feb 2010 14:19:21 +0100 Subject: mac80211: Improve software scan timing The current software scan implemenation in mac80211 returns to the operating channel after each scanned channel. However, in some situations (e.g. no traffic) it would be nicer to scan a few channels in a row to speed up the scan itself. Hence, after scanning a channel, check if we have queued up any tx frames and return to the operating channel in that case. Unfortunately we don't know if the AP has buffered any frames for us. Hence, scan only as many channels in a row as the pm_qos latency and the negotiated listen interval allows us to. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 1 + net/mac80211/scan.c | 71 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 241533e1bc0..b84126491ab 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -745,6 +745,7 @@ struct ieee80211_local { int scan_channel_idx; int scan_ies_len; + unsigned long leave_oper_channel_time; enum mac80211_scan_state next_scan_state; struct delayed_work scan_work; struct ieee80211_sub_if_data *scan_sdata; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index b822dce9786..75a85978c3b 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -14,6 +14,8 @@ #include #include +#include +#include #include #include "ieee80211_i.h" @@ -321,6 +323,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) ieee80211_offchannel_stop_beaconing(local); + local->leave_oper_channel_time = 0; local->next_scan_state = SCAN_DECISION; local->scan_channel_idx = 0; @@ -425,11 +428,28 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, return rc; } +static unsigned long +ieee80211_scan_get_channel_time(struct ieee80211_channel *chan) +{ + /* + * TODO: channel switching also consumes quite some time, + * add that delay as well to get a better estimation + */ + if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) + return IEEE80211_PASSIVE_CHANNEL_TIME; + return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; +} + static int ieee80211_scan_state_decision(struct ieee80211_local *local, unsigned long *next_delay) { bool associated = false; + bool tx_empty = true; + bool bad_latency; + bool listen_int_exceeded; + unsigned long min_beacon_int = 0; struct ieee80211_sub_if_data *sdata; + struct ieee80211_channel *next_chan; /* if no more bands/channels left, complete scan and advance to the idle state */ if (local->scan_channel_idx >= local->scan_req->n_channels) { @@ -437,7 +457,11 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, return 1; } - /* check if at least one STA interface is associated */ + /* + * check if at least one STA interface is associated, + * check if at least one STA interface has pending tx frames + * and grab the lowest used beacon interval + */ mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { if (!ieee80211_sdata_running(sdata)) @@ -446,7 +470,16 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.mgd.associated) { associated = true; - break; + + if (sdata->vif.bss_conf.beacon_int < + min_beacon_int || min_beacon_int == 0) + min_beacon_int = + sdata->vif.bss_conf.beacon_int; + + if (!qdisc_all_tx_empty(sdata->dev)) { + tx_empty = false; + break; + } } } } @@ -455,11 +488,34 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, if (local->scan_channel) { /* * we're currently scanning a different channel, let's - * switch back to the operating channel now if at least - * one interface is associated. Otherwise just scan the - * next channel + * see if we can scan another channel without interfering + * with the current traffic situation. + * + * Since we don't know if the AP has pending frames for us + * we can only check for our tx queues and use the current + * pm_qos requirements for rx. Hence, if no tx traffic occurs + * at all we will scan as many channels in a row as the pm_qos + * latency allows us to. Additionally we also check for the + * currently negotiated listen interval to prevent losing + * frames unnecessarily. + * + * Otherwise switch back to the operating channel. */ - if (associated) + next_chan = local->scan_req->channels[local->scan_channel_idx]; + + bad_latency = time_after(jiffies + + ieee80211_scan_get_channel_time(next_chan), + local->leave_oper_channel_time + + usecs_to_jiffies(pm_qos_requirement(PM_QOS_NETWORK_LATENCY))); + + listen_int_exceeded = time_after(jiffies + + ieee80211_scan_get_channel_time(next_chan), + local->leave_oper_channel_time + + usecs_to_jiffies(min_beacon_int * 1024) * + local->hw.conf.listen_interval); + + if (associated && ( !tx_empty || bad_latency || + listen_int_exceeded)) local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; else local->next_scan_state = SCAN_SET_CHANNEL; @@ -491,6 +547,9 @@ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *loca else *next_delay = HZ / 10; + /* remember when we left the operating channel */ + local->leave_oper_channel_time = jiffies; + /* advance to the next channel to be scanned */ local->next_scan_state = SCAN_SET_CHANNEL; } -- cgit v1.2.3 From fa9029f8c34576e121a4b6ddbbd645081fe50c74 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 25 Feb 2010 15:13:11 +0100 Subject: mac80211: use different MAC addresses for virtual interfaces Drivers can now advertise to cfg80211 that they have multiple MAC addresses reserved for a device, but we don't currently make use of that in mac80211. Change that and assign different addresses to new virtual interfaces (if addresses are available) in order to make it easier for users to use multiple virtual interfaces; they no longer need to always assign a new MAC address manually. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/iface.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 2 deletions(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 0793d7a8d74..d5571b9420c 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -815,6 +815,118 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, return 0; } +static void ieee80211_assign_perm_addr(struct ieee80211_local *local, + struct net_device *dev, + enum nl80211_iftype type) +{ + struct ieee80211_sub_if_data *sdata; + u64 mask, start, addr, val, inc; + u8 *m; + u8 tmp_addr[ETH_ALEN]; + int i; + + /* default ... something at least */ + memcpy(dev->perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN); + + if (is_zero_ether_addr(local->hw.wiphy->addr_mask) && + local->hw.wiphy->n_addresses <= 1) + return; + + + mutex_lock(&local->iflist_mtx); + + switch (type) { + case NL80211_IFTYPE_MONITOR: + /* doesn't matter */ + break; + case NL80211_IFTYPE_WDS: + case NL80211_IFTYPE_AP_VLAN: + /* match up with an AP interface */ + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type != NL80211_IFTYPE_AP) + continue; + memcpy(dev->perm_addr, sdata->vif.addr, ETH_ALEN); + break; + } + /* keep default if no AP interface present */ + break; + default: + /* assign a new address if possible -- try n_addresses first */ + for (i = 0; i < local->hw.wiphy->n_addresses; i++) { + bool used = false; + + list_for_each_entry(sdata, &local->interfaces, list) { + if (memcmp(local->hw.wiphy->addresses[i].addr, + sdata->vif.addr, ETH_ALEN) == 0) { + used = true; + break; + } + } + + if (!used) { + memcpy(dev->perm_addr, + local->hw.wiphy->addresses[i].addr, + ETH_ALEN); + break; + } + } + + /* try mask if available */ + if (is_zero_ether_addr(local->hw.wiphy->addr_mask)) + break; + + m = local->hw.wiphy->addr_mask; + mask = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | + ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | + ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); + + if (__ffs64(mask) + hweight64(mask) != fls64(mask)) { + /* not a contiguous mask ... not handled now! */ + printk(KERN_DEBUG "not contiguous\n"); + break; + } + + m = local->hw.wiphy->perm_addr; + start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | + ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | + ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); + + inc = 1ULL<<__ffs64(mask); + val = (start & mask); + addr = (start & ~mask) | (val & mask); + do { + bool used = false; + + tmp_addr[5] = addr >> 0*8; + tmp_addr[4] = addr >> 1*8; + tmp_addr[3] = addr >> 2*8; + tmp_addr[2] = addr >> 3*8; + tmp_addr[1] = addr >> 4*8; + tmp_addr[0] = addr >> 5*8; + + val += inc; + + list_for_each_entry(sdata, &local->interfaces, list) { + if (memcmp(tmp_addr, sdata->vif.addr, + ETH_ALEN) == 0) { + used = true; + break; + } + } + + if (!used) { + memcpy(dev->perm_addr, tmp_addr, ETH_ALEN); + break; + } + addr = (start & ~mask) | (val & mask); + } while (addr != start); + + break; + } + + mutex_unlock(&local->iflist_mtx); +} + int ieee80211_if_add(struct ieee80211_local *local, const char *name, struct net_device **new_dev, enum nl80211_iftype type, struct vif_params *params) @@ -844,8 +956,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, if (ret < 0) goto fail; - memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); - memcpy(ndev->perm_addr, ndev->dev_addr, ETH_ALEN); + ieee80211_assign_perm_addr(local, ndev, type); + memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ -- cgit v1.2.3 From 9734485c8d2064f39ff77acf615e87da0766ce76 Mon Sep 17 00:00:00 2001 From: RafaÅ‚ MiÅ‚ecki 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(+) diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index b8807fb12c9..3a003e6803a 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 403aad3f894..47d20dcafbf 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 9c1c6ecd367..b23036f7dc1 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: RafaÅ‚ MiÅ‚ecki 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(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 795bb1e3345..2d8eda145cb 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: RafaÅ‚ MiÅ‚ecki 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(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 2d8eda145cb..dd81e8aec91 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: RafaÅ‚ MiÅ‚ecki 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(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index dd81e8aec91..2c592d2dba9 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: RafaÅ‚ MiÅ‚ecki 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(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 2c592d2dba9..67748976ae7 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: RafaÅ‚ MiÅ‚ecki 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(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 67748976ae7..1952acc3c38 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 47d20dcafbf..e7acae278be 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: RafaÅ‚ MiÅ‚ecki 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(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 1952acc3c38..30f8bf24ac6 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: RafaÅ‚ MiÅ‚ecki 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(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 30f8bf24ac6..ffe26227066 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: RafaÅ‚ MiÅ‚ecki 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(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index ffe26227066..862223fdde4 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: RafaÅ‚ MiÅ‚ecki 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(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 862223fdde4..6fd140ac7f9 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 e7acae278be..8b6d570dd0a 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 diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 4e378faee65..e31a5ccebea 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 3bf2e6e9b2d..59b092eaa82 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 e476acb53aa..f59628c1c1c 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 c4844adff92..4b7bc008220 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 00000000000..d6b028b1b6e --- /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 47b02147796..d7b8e44985b 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 00000000000..26eeb586ee0 --- /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 112149e9b31..b994eee771a 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 4ef7739f9e8..f493248d472 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 51a67fb2e18..3ff6b9d25a1 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 3a876a8ece3..074f42a7dca 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 47909f94271..effdd3670da 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 303cc8193ad..867bd69270f 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 6054c5fba0c..e6cae388487 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 54daa38ecba..1b3a1ba4ed9 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c index d6b028b1b6e..4c5395eae95 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 d7b8e44985b..d0fab876df0 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 e6cae388487..f9210b78ffc 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index effdd3670da..b588cb69536 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 867bd69270f..9a5a7b100e6 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 8bf7c20b9d3..696e668b801 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 f9210b78ffc..c277e4e8cf8 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 df257bc15f4..8116aa0d767 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 1b3a1ba4ed9..a825092fff9 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b994eee771a..166087d6f72 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 166087d6f72..1cfcc9fe9dc 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 1ed5206721e..08b33fcc079 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 a825092fff9..2b2c96bf5a5 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d0fab876df0..e7e4bf71568 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 c277e4e8cf8..4d6558fbebe 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 2b2c96bf5a5..b2b050592bc 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 696e668b801..84271cc62af 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 e71923961e6..e182f5a0f73 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 e7e4bf71568..fbbe9985966 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 1cfcc9fe9dc..8e8f5282c01 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 4d6558fbebe..ba404b99f4f 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 b2b050592bc..9cc15f96d20 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8e8f5282c01..4365e853f4b 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 4365e853f4b..5fa1da1f59c 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index f59628c1c1c..4c0ef013acb 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 9a5a7b100e6..ed59e2744ca 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 ba404b99f4f..90d2b6e0df7 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index fbbe9985966..b07c013e273 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 9cc15f96d20..bdd5fc74bce 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b07c013e273..6c816d9b524 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 5fa1da1f59c..a962fb3cb35 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 f493248d472..bec00c79059 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 7bf44f14679..fc084dd2d14 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 bdd5fc74bce..2fd1b3d4949 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6c816d9b524..bc84fd4a8d2 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 fc084dd2d14..50d0ee96629 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 50d0ee96629..d9255b53be1 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index bc84fd4a8d2..d6e1a059b9b 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 90d2b6e0df7..bac8e7cc46c 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 4a6686fa6b3..b1aad306efa 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 2fd1b3d4949..dd33251d691 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index a962fb3cb35..ec435e5491d 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 bec00c79059..aced12f1611 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 dd9ff2ed645..ccad04c0a76 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index d9255b53be1..5f5820249a2 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index ccad04c0a76..1544d751a42 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index dd33251d691..252df12eeb3 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 1bd2cd83602..644aacfbd7d 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 4c0ef013acb..37e1e77f513 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 bac8e7cc46c..2e4d47c7139 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 d2d2a917490..5944de7a98a 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 08b33fcc079..045e4a67344 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(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 252df12eeb3..2579bbcaab3 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 69c86373c6ea1149aa559e6088362d58d8ec8835 Mon Sep 17 00:00:00 2001 From: "florian@mickler.org" Date: Wed, 24 Feb 2010 12:05:16 +0100 Subject: Document the rfkill sysfs ABI This moves sysfs ABI info from Documentation/rfkill.txt to the ABI subfolder and reformats it. This also schedules the deprecated sysfs parts to be removed in 2012 (claim file) and 2014 (state file). Signed-off-by: Florian Mickler Signed-off-by: John W. Linville --- Documentation/ABI/obsolete/sysfs-class-rfkill | 29 ++++++++++++++++++ Documentation/ABI/stable/sysfs-class-rfkill | 42 +++++++++++++++++++++++++ Documentation/feature-removal-schedule.txt | 18 +++++++++++ Documentation/rfkill.txt | 44 ++++++++------------------- 4 files changed, 102 insertions(+), 31 deletions(-) create mode 100644 Documentation/ABI/obsolete/sysfs-class-rfkill create mode 100644 Documentation/ABI/stable/sysfs-class-rfkill diff --git a/Documentation/ABI/obsolete/sysfs-class-rfkill b/Documentation/ABI/obsolete/sysfs-class-rfkill new file mode 100644 index 00000000000..4201d5b0551 --- /dev/null +++ b/Documentation/ABI/obsolete/sysfs-class-rfkill @@ -0,0 +1,29 @@ +rfkill - radio frequency (RF) connector kill switch support + +For details to this subsystem look at Documentation/rfkill.txt. + +What: /sys/class/rfkill/rfkill[0-9]+/state +Date: 09-Jul-2007 +KernelVersion v2.6.22 +Contact: linux-wireless@vger.kernel.org +Description: Current state of the transmitter. + This file is deprecated and sheduled to be removed in 2014, + because its not possible to express the 'soft and hard block' + state of the rfkill driver. +Values: A numeric value. + 0: RFKILL_STATE_SOFT_BLOCKED + transmitter is turned off by software + 1: RFKILL_STATE_UNBLOCKED + transmitter is (potentially) active + 2: RFKILL_STATE_HARD_BLOCKED + transmitter is forced off by something outside of + the driver's control. + +What: /sys/class/rfkill/rfkill[0-9]+/claim +Date: 09-Jul-2007 +KernelVersion v2.6.22 +Contact: linux-wireless@vger.kernel.org +Description: This file is deprecated because there no longer is a way to + claim just control over a single rfkill instance. + This file is scheduled to be removed in 2012. +Values: 0: Kernel handles events diff --git a/Documentation/ABI/stable/sysfs-class-rfkill b/Documentation/ABI/stable/sysfs-class-rfkill new file mode 100644 index 00000000000..97d5064f4f8 --- /dev/null +++ b/Documentation/ABI/stable/sysfs-class-rfkill @@ -0,0 +1,42 @@ +rfkill - radio frequency (RF) connector kill switch support + +For details to this subsystem look at Documentation/rfkill.txt. + +For the deprecated /sys/class/rfkill/*/state and +/sys/class/rfkill/*/claim knobs of this interface look in +Documentation/ABI/obsolte/sysfs-class-rfkill. + +What: /sys/class/rfkill +Date: 09-Jul-2007 +KernelVersion: v2.6.22 +Contact: linux-wireless@vger.kernel.org, +Description: The rfkill class subsystem folder. + Each registered rfkill driver is represented by an rfkillX + subfolder (X being an integer > 0). + + +What: /sys/class/rfkill/rfkill[0-9]+/name +Date: 09-Jul-2007 +KernelVersion v2.6.22 +Contact: linux-wireless@vger.kernel.org +Description: Name assigned by driver to this key (interface or driver name). +Values: arbitrary string. + + +What: /sys/class/rfkill/rfkill[0-9]+/type +Date: 09-Jul-2007 +KernelVersion v2.6.22 +Contact: linux-wireless@vger.kernel.org +Description: Driver type string ("wlan", "bluetooth", etc). +Values: See include/linux/rfkill.h. + + +What: /sys/class/rfkill/rfkill[0-9]+/persistent +Date: 09-Jul-2007 +KernelVersion v2.6.22 +Contact: linux-wireless@vger.kernel.org +Description: Whether the soft blocked state is initialised from non-volatile + storage at startup. +Values: A numeric value. + 0: false + 1: true diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index a0a4fd43e62..a841e79dfac 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -520,6 +520,24 @@ Who: Hans de Goede ---------------------------- +What: sysfs-class-rfkill state file +When: Feb 2014 +Files: net/rfkill/core.c +Why: Documented as obsolete since Feb 2010. This file is limited to 3 + states while the rfkill drivers can have 4 states. +Who: anybody or Florian Mickler + +---------------------------- + +What: sysfs-class-rfkill claim file +When: Feb 2012 +Files: net/rfkill/core.c +Why: It is not possible to claim an rfkill driver since 2007. This is + Documented as obsolete since Feb 2010. +Who: anybody or Florian Mickler + +---------------------------- + What: capifs When: February 2011 Files: drivers/isdn/capi/capifs.* diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt index b4860509c31..83668e5dd17 100644 --- a/Documentation/rfkill.txt +++ b/Documentation/rfkill.txt @@ -99,37 +99,15 @@ system. Also, it is possible to switch all rfkill drivers (or all drivers of a specified type) into a state which also updates the default state for hotplugged devices. -After an application opens /dev/rfkill, it can read the current state of -all devices, and afterwards can poll the descriptor for hotplug or state -change events. - -Applications must ignore operations (the "op" field) they do not handle, -this allows the API to be extended in the future. - -Additionally, each rfkill device is registered in sysfs and there has the -following attributes: - - name: Name assigned by driver to this key (interface or driver name). - type: Driver type string ("wlan", "bluetooth", etc). - persistent: Whether the soft blocked state is initialised from - non-volatile storage at startup. - state: Current state of the transmitter - 0: RFKILL_STATE_SOFT_BLOCKED - transmitter is turned off by software - 1: RFKILL_STATE_UNBLOCKED - transmitter is (potentially) active - 2: RFKILL_STATE_HARD_BLOCKED - transmitter is forced off by something outside of - the driver's control. - This file is deprecated because it can only properly show - three of the four possible states, soft-and-hard-blocked is - missing. - claim: 0: Kernel handles events - This file is deprecated because there no longer is a way to - claim just control over a single rfkill instance. - -rfkill devices also issue uevents (with an action of "change"), with the -following environment variables set: +After an application opens /dev/rfkill, it can read the current state of all +devices. Changes can be either obtained by either polling the descriptor for +hotplug or state change events or by listening for uevents emitted by the +rfkill core framework. + +Additionally, each rfkill device is registered in sysfs and emits uevents. + +rfkill devices issue uevents (with an action of "change"), with the following +environment variables set: RFKILL_NAME RFKILL_STATE @@ -137,3 +115,7 @@ RFKILL_TYPE The contents of these variables corresponds to the "name", "state" and "type" sysfs files explained above. + + +For further details consult Documentation/ABI/stable/dev-rfkill and +Documentation/ABI/stable/sysfs-class-rfkill. -- cgit v1.2.3 From 6c26361e4be3cf0dad7083e38ca52001a987e3e6 Mon Sep 17 00:00:00 2001 From: "florian@mickler.org" Date: Fri, 26 Feb 2010 12:01:34 +0100 Subject: enhance sysfs rfkill interface This commit introduces two new sysfs knobs. /sys/class/rfkill/rfkill[0-9]+/blocked_hw: (ro) hardblock kill state /sys/class/rfkill/rfkill[0-9]+/blocked_sw: (rw) softblock kill state Signed-off-by: Florian Mickler Signed-off-by: John W. Linville --- Documentation/ABI/stable/sysfs-class-rfkill | 25 +++++++++++++ net/rfkill/core.c | 58 +++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/Documentation/ABI/stable/sysfs-class-rfkill b/Documentation/ABI/stable/sysfs-class-rfkill index 97d5064f4f8..b91c3f37453 100644 --- a/Documentation/ABI/stable/sysfs-class-rfkill +++ b/Documentation/ABI/stable/sysfs-class-rfkill @@ -40,3 +40,28 @@ Description: Whether the soft blocked state is initialised from non-volatile Values: A numeric value. 0: false 1: true + + +What: /sys/class/rfkill/rfkill[0-9]+/blocked_hw +Date: 23-Feb-2010 +KernelVersion v2.6.34 +Contact: linux-wireless@vger.kernel.org +Description: Current hardblock state. This file is read only. +Values: A numeric value. + 0: inactive + The transmitter is (potentially) active. + 1: active + The transmitter is forced off by something outside of + the driver's control. + + +What: /sys/class/rfkill/rfkill[0-9]+/blocked_sw +Date: 23-Feb-2010 +KernelVersion v2.6.34 +Contact: linux-wireless@vger.kernel.org +Description: Current softblock state. This file is read and write. +Values: A numeric value. + 0: inactive + The transmitter is (potentially) active. + 1: active + The transmitter is turned off by software. diff --git a/net/rfkill/core.c b/net/rfkill/core.c index c218e07e5ca..5f33151d70a 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -628,6 +628,61 @@ static ssize_t rfkill_persistent_show(struct device *dev, return sprintf(buf, "%d\n", rfkill->persistent); } +static ssize_t rfkill_blocked_hw_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct rfkill *rfkill = to_rfkill(dev); + unsigned long flags; + u32 state; + + spin_lock_irqsave(&rfkill->lock, flags); + state = rfkill->state; + spin_unlock_irqrestore(&rfkill->lock, flags); + + return sprintf(buf, "%d\n", (state & RFKILL_BLOCK_HW) ? 1 : 0 ); +} + +static ssize_t rfkill_blocked_sw_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct rfkill *rfkill = to_rfkill(dev); + unsigned long flags; + u32 state; + + spin_lock_irqsave(&rfkill->lock, flags); + state = rfkill->state; + spin_unlock_irqrestore(&rfkill->lock, flags); + + return sprintf(buf, "%d\n", (state & RFKILL_BLOCK_SW) ? 1 : 0 ); +} + +static ssize_t rfkill_blocked_sw_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct rfkill *rfkill = to_rfkill(dev); + unsigned long state; + int err; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + err = strict_strtoul(buf, 0, &state); + if (err) + return err; + + if (state > 1 ) + return -EINVAL; + + mutex_lock(&rfkill_global_mutex); + rfkill_set_block(rfkill, state); + mutex_unlock(&rfkill_global_mutex); + + return err ?: count; +} + static u8 user_state_from_blocked(unsigned long state) { if (state & RFKILL_BLOCK_HW) @@ -700,6 +755,9 @@ static struct device_attribute rfkill_dev_attrs[] = { __ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL), __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), + __ATTR(sw, S_IRUGO|S_IWUSR, rfkill_blocked_sw_show, + rfkill_blocked_sw_store), + __ATTR(hw, S_IRUGO, rfkill_blocked_hw_show, NULL), __ATTR_NULL }; -- 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(-) diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 1e41ad0fcad..9ef4fd04504 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 3dfd9f0e900..7e16bcf5997 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 ad8f7eabb5a..36b1580329c 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(-) diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 7c4f44a9c3e..6778e5838fe 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 be992ca41cf..6ac5c8dbe05 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 d13c8853ee8..96caab4bbe5 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 7f34d6dd3c4..90519600a94 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 36b1580329c..cbaf8ae3aa3 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 diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig index b9d34a76696..03f998d098c 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 d34291b652d..aeed5cd8081 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 96caab4bbe5..373b5b5001d 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 0adfdc85765..e7bc41670b2 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 79ffa3b98d7..9ad5b3c22eb 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 cbaf8ae3aa3..38d950b0f24 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 00000000000..904d36f2231 --- /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 00000000000..320e54fbb38 --- /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 55905f02309..406615c2c58 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(-) diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c index 6ac5c8dbe05..48930c1a0f7 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 9ad5b3c22eb..13266c3842f 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 90519600a94..3a3510a6223 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 38d950b0f24..c8a31be1688 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(-) diff --git a/drivers/net/wireless/iwmc3200wifi/hal.h b/drivers/net/wireless/iwmc3200wifi/hal.h index e7bc41670b2..c20936d9b6b 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(-) diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 6778e5838fe..fc239a32cb6 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(-) diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 9ef4fd04504..b5cbd2bfd52 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 c8a31be1688..5090a8a6188 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 406615c2c58..a20b936ae21 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 7f54a145ca6..0cbba3ecc81 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 c2ef355bf3ef0b8006b96128726684fba47ac928 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Thu, 25 Feb 2010 19:18:47 -0500 Subject: mac80211: give warning if building w/out rate ctrl algorithm I discovered that if EMBEDDED=y, one can accidentally build a mac80211 stack and drivers w/ no rate control algorithm. For drivers like RTL8187 that don't supply their own RC algorithms, this will cause ieee80211_register_hw to fail (making the driver unusable). This will tell kconfig to provide a warning if no rate control algorithms have been selected. That'll at least warn the user; users that know that their drivers supply a rate control algorithm can safely ignore the warning, and those who don't know (or who expect to be using multiple drivers) can select a default RC algorithm. Signed-off-by: Andres Salomon Cc: stable@kernel.org Signed-off-by: John W. Linville --- net/mac80211/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index a952b7f8c64..334c359da5e 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -15,8 +15,12 @@ comment "CFG80211 needs to be enabled for MAC80211" if MAC80211 != n +config MAC80211_HAS_RC + def_bool n + config MAC80211_RC_PID bool "PID controller based rate control algorithm" if EMBEDDED + select MAC80211_HAS_RC ---help--- This option enables a TX rate control algorithm for mac80211 that uses a PID controller to select the TX @@ -24,12 +28,14 @@ config MAC80211_RC_PID config MAC80211_RC_MINSTREL bool "Minstrel" if EMBEDDED + select MAC80211_HAS_RC default y ---help--- This option enables the 'minstrel' TX rate control algorithm choice prompt "Default rate control algorithm" + depends on MAC80211_HAS_RC default MAC80211_RC_DEFAULT_MINSTREL ---help--- This option selects the default rate control algorithm @@ -62,6 +68,9 @@ config MAC80211_RC_DEFAULT endif +comment "Some wireless drivers require a rate control algorithm" + depends on MAC80211_HAS_RC=n + config MAC80211_MESH bool "Enable mac80211 mesh networking (pre-802.11s) support" depends on MAC80211 && EXPERIMENTAL -- 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(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 4de7fe03b9f..22f9f59397c 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 c889d4992a6..7c08434ebd1 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 dc30a2b70a6..d26126bfacd 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 44ac91ea8450b0e7a27b4a1fd64aefd35a144728 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 1 Mar 2010 22:17:38 +0100 Subject: minstrel: simplify and fix debugfs code This patch cleans up the debugfs read function for the statistics by using simple_read_from_buffer instead of its own semi-broken hack. Also removes a useless member of the minstrel debugfs info struct. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/rc80211_minstrel.h | 5 +++++ net/mac80211/rc80211_minstrel_debugfs.c | 35 ++++++--------------------------- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 38bf4168fc3..9372656f3f5 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -80,6 +80,11 @@ struct minstrel_priv { unsigned int lookaround_rate_mrr; }; +struct minstrel_debugfs_info { + size_t len; + char buf[]; +}; + void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index a715d9454f6..3e83402ece1 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c @@ -52,21 +52,15 @@ #include #include "rc80211_minstrel.h" -struct minstrel_stats_info { - struct minstrel_sta_info *mi; - char buf[4096]; - size_t len; -}; - static int minstrel_stats_open(struct inode *inode, struct file *file) { struct minstrel_sta_info *mi = inode->i_private; - struct minstrel_stats_info *ms; + struct minstrel_debugfs_info *ms; unsigned int i, tp, prob, eprob; char *p; - ms = kmalloc(sizeof(*ms), GFP_KERNEL); + ms = kmalloc(sizeof(*ms) + 4096, GFP_KERNEL); if (!ms) return -ENOMEM; @@ -107,35 +101,18 @@ minstrel_stats_open(struct inode *inode, struct file *file) } static ssize_t -minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *o) +minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) { - struct minstrel_stats_info *ms; - char *src; + struct minstrel_debugfs_info *ms; ms = file->private_data; - src = ms->buf; - - len = min(len, ms->len); - if (len <= *o) - return 0; - - src += *o; - len -= *o; - *o += len; - - if (copy_to_user(buf, src, len)) - return -EFAULT; - - return len; + return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len); } static int minstrel_stats_release(struct inode *inode, struct file *file) { - struct minstrel_stats_info *ms = file->private_data; - - kfree(ms); - + kfree(file->private_data); return 0; } -- cgit v1.2.3 From eae44756d60c4e938259358090dba5df675dced0 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 1 Mar 2010 22:21:40 +0100 Subject: minstrel: make the rate control ops reusable from another rc implementation This patch makes it possible to reuse the minstrel rate control ops from another rate control module. This is useful in preparing for the new 802.11n implementation of minstrel, which will reuse the old code for legacy stations. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/rc80211_minstrel.c | 2 +- net/mac80211/rc80211_minstrel.h | 6 ++++++ net/mac80211/rc80211_minstrel_debugfs.c | 6 +++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 6e5d68b4e42..4926d929fd9 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -541,7 +541,7 @@ minstrel_free(void *priv) kfree(priv); } -static struct rate_control_ops mac80211_minstrel = { +struct rate_control_ops mac80211_minstrel = { .name = "minstrel", .tx_status = minstrel_tx_status, .get_rate = minstrel_get_rate, diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 9372656f3f5..0f5a83370aa 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -85,7 +85,13 @@ struct minstrel_debugfs_info { char buf[]; }; +extern struct rate_control_ops mac80211_minstrel; void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); +/* debugfs */ +int minstrel_stats_open(struct inode *inode, struct file *file); +ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos); +int minstrel_stats_release(struct inode *inode, struct file *file); + #endif diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index 3e83402ece1..56d0f24957d 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c @@ -52,7 +52,7 @@ #include #include "rc80211_minstrel.h" -static int +int minstrel_stats_open(struct inode *inode, struct file *file) { struct minstrel_sta_info *mi = inode->i_private; @@ -100,7 +100,7 @@ minstrel_stats_open(struct inode *inode, struct file *file) return 0; } -static ssize_t +ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) { struct minstrel_debugfs_info *ms; @@ -109,7 +109,7 @@ minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppo return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len); } -static int +int minstrel_stats_release(struct inode *inode, struct file *file) { kfree(file->private_data); -- 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(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 9f6d6bf06b8..a4f70de99cd 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(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index a4f70de99cd..15bae0a6805 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(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 15bae0a6805..3433461995a 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(+) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 3433461995a..267afd714c7 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(+) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 7c08434ebd1..e7a989c707a 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 7e1a88a5abd..ca525842d82 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 747508c15d3..236f20f9cd4 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 66f69f04e55..01861271104 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(-) diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 42284445b75..c8bb102a4db 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 e7a989c707a..fdf3190e461 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 10ad877c2cd..5aee85f27c0 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(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 22f9f59397c..e5ace22b951 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 c8bb102a4db..66758cb66d5 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 fdf3190e461..79922cfd96b 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 be69ebb2744..c813046b354 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 8bd62c130b2..4120068792e 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(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index e5ace22b951..2c3b4a65752 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 d26126bfacd..aebb31f2834 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 473a483bb9c..1a65683e8c1 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(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 2c3b4a65752..1c2a8e87d76 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 66758cb66d5..dd4099a2ff1 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(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 1c2a8e87d76..5898e2e50a7 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 367a6c7d3cc..e618e71b1ce 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(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 79922cfd96b..b142a78ed1e 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 ca525842d82..33f1d8b87ee 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 236f20f9cd4..bccd4a78027 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 01861271104..da24ff52e27 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(-) diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 5aee85f27c0..20d562b07c9 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(-) diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 6a3f4da7fb4..86654b9e109 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 1a65683e8c1..c4a6d5f26af 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 4cb9c5df9f4..f325e664065 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(-) diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 2f6733526f7..337fc7bec5a 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(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 0e79e58cf4c..3c4b5d2d9e1 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 4f6d6fd442f..f4818e4fa4b 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 b2c8207f7bc..8359362fc51 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(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 5898e2e50a7..365eccd777a 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 aebb31f2834..9d920fb14d5 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 85373ee817f95e4b9ad50822ec0c1d8a6f1f7a7f Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 10 Mar 2010 10:41:32 -0600 Subject: ssb: Export ssb_chipco_gpio_control - needed by N PHY code The latest changes in the N PHY core require the symbol ssb_chipco_gpio_control to be exported. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/ssb/driver_chipcommon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 9681536163c..59c3c0fdbec 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c @@ -370,6 +370,7 @@ u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value) { return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value); } +EXPORT_SYMBOL(ssb_chipco_gpio_control); u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value) { -- 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(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index dc5018a6d9e..2859a355ef9 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(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 2859a355ef9..a441aad922c 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(-) diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index c813046b354..9247123c9b6 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 20d562b07c9..e291bfbd6e6 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 d9cab7c3cff..f5831da33f7 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(-) diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index e291bfbd6e6..384347b0c9f 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(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 365eccd777a..1d7491c8546 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 9247123c9b6..1b9fcb84216 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(-) diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 2daf8ffdb7e..7a867e31ca5 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 eaf55530c94cb7adcd320c28ed6c7d463c9a3727 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 11 Mar 2010 16:28:24 +0100 Subject: mac80211: optimize tx status processing When a cooked monitor interface is active, ieee80211_tx_status() generates a radiotap header for every single frame, even if it wasn't injected and thus won't be sent to a monitor interface. This patch reduces cpu utilization by moving the cooked monitor check a bit earlier, before it generates the rtap header. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/status.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 56d5b9a6ec5..11805a3a626 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -171,7 +171,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) struct net_device *prev_dev = NULL; struct sta_info *sta, *tmp; int retry_count = -1, i; - bool injected; + bool send_to_cooked; for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { /* the HW cannot have attempted that rate */ @@ -296,11 +296,15 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) /* this was a transmitted frame, but now we want to reuse it */ skb_orphan(skb); + /* Need to make a copy before skb->cb gets cleared */ + send_to_cooked = !!(info->flags & IEEE80211_TX_CTL_INJECTED) || + (type != IEEE80211_FTYPE_DATA); + /* * This is a bit racy but we can avoid a lot of work * with this test... */ - if (!local->monitors && !local->cooked_mntrs) { + if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) { dev_kfree_skb(skb); return; } @@ -345,9 +349,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) /* for now report the total retry_count */ rthdr->data_retries = retry_count; - /* Need to make a copy before skb->cb gets cleared */ - injected = !!(info->flags & IEEE80211_TX_CTL_INJECTED); - /* XXX: is this sufficient for BPF? */ skb_set_mac_header(skb, 0); skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -362,8 +363,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) continue; if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && - !injected && - (type == IEEE80211_FTYPE_DATA)) + !send_to_cooked) continue; if (prev_dev) { -- 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c index 9423f22bdce..cfca232dc8c 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index 37c61c19cae..4f5f02a26e6 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 b89d2ac62ef..c545e9d5f51 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 24ae6a360ac..0155653b710 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 851dfb65e47..b55cb2bd459 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 cfca232dc8c..2051ef06e9e 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(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 28a80867408..acb334184d7 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(-) diff --git a/drivers/net/wireless/orinoco/Kconfig b/drivers/net/wireless/orinoco/Kconfig index e2a2c18920a..6116b546861 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 e6369242e49..883b8f86862 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 1d4ada188ed..fdc96137917 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(-) diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 9b72c45a774..fe63bf21c67 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 63c2a7ade5f..d6edc244012 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 bf45391172f..9ac136b98bb 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 1ae0b2b02c3..5b8841159b7 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(+) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 91cce2d0f6d..549a60ab3b6 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(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 549a60ab3b6..2f42e01eb99 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(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 2f42e01eb99..b1f5643f83f 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 819386dfc67e770b4a0b59983f7948f8ddaa357e Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 16 Mar 2010 15:02:35 -0400 Subject: Revert "mac80211: fix rates setup on IBSS merge" I accidentally merged an incomplete version of the patch... This reverts commit b4d59a9317e41faec3d0b6a03f0454d1e8abb710. Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index b840d9072de..f3e94248674 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -276,8 +276,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, (unsigned long long) sta->sta.supp_rates[band]); #endif rcu_read_unlock(); - - /* FIXME: update rate control */ } else { rcu_read_unlock(); ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, @@ -372,7 +370,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, sdata->name, mgmt->bssid); #endif ieee80211_sta_join_ibss(sdata, bss); - supp_rates = ieee80211_sta_get_rates(local, elems, band); ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates, GFP_KERNEL); } -- cgit v1.2.3 From 09a08cff3d13315c948e6aee5cf912f8f1db54e7 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Wed, 3 Mar 2010 18:45:42 +0900 Subject: mac80211: (really) fix rates setup on IBSS merge when an IBSS merge happened, the supported rates for the newly added station were left empty, causing the rate control module to be initialized with only the basic rates. the section of the ibss code which deals with updating supported rates for an already existing station failed to inform the rate control module about the new rates. as both minstrel and pid don't have an update function i just use the init function. also remove unnecessary (unsigned long long) casts and edit debug message. Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index f3e94248674..01974c2510a 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -264,17 +264,16 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, sta->sta.supp_rates[band] = supp_rates | ieee80211_mandatory_rates(local, band); + if (sta->sta.supp_rates[band] != prev_rates) { #ifdef CONFIG_MAC80211_IBSS_DEBUG - if (sta->sta.supp_rates[band] != prev_rates) printk(KERN_DEBUG "%s: updated supp_rates set " - "for %pM based on beacon info (0x%llx | " - "0x%llx -> 0x%llx)\n", - sdata->name, - sta->sta.addr, - (unsigned long long) prev_rates, - (unsigned long long) supp_rates, - (unsigned long long) sta->sta.supp_rates[band]); + "for %pM based on beacon/probe_response " + "(0x%x -> 0x%x)\n", + sdata->name, sta->sta.addr, + prev_rates, sta->sta.supp_rates[band]); #endif + rate_control_rate_init(sta); + } rcu_read_unlock(); } else { rcu_read_unlock(); @@ -370,6 +369,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, sdata->name, mgmt->bssid); #endif ieee80211_sta_join_ibss(sdata, bss); + supp_rates = ieee80211_sta_get_rates(local, elems, band); ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates, GFP_KERNEL); } -- cgit v1.2.3 From 819bfecc4fc6b6e5a793f719a45b7146ce423b79 Mon Sep 17 00:00:00 2001 From: "florian@mickler.org" Date: Sat, 13 Mar 2010 13:31:05 +0100 Subject: rename new rfkill sysfs knobs This patch renames the (never officially released) sysfs-knobs "blocked_hw" and "blocked_sw" to "hard" and "soft", as the hardware vs software conotation is misleading. It also gets rid of not needed locks around u32-read-access. Signed-off-by: Florian Mickler Signed-off-by: John W. Linville --- Documentation/ABI/stable/sysfs-class-rfkill | 10 ++++----- net/rfkill/core.c | 35 +++++++---------------------- 2 files changed, 13 insertions(+), 32 deletions(-) diff --git a/Documentation/ABI/stable/sysfs-class-rfkill b/Documentation/ABI/stable/sysfs-class-rfkill index b91c3f37453..097f522c33b 100644 --- a/Documentation/ABI/stable/sysfs-class-rfkill +++ b/Documentation/ABI/stable/sysfs-class-rfkill @@ -4,7 +4,7 @@ For details to this subsystem look at Documentation/rfkill.txt. For the deprecated /sys/class/rfkill/*/state and /sys/class/rfkill/*/claim knobs of this interface look in -Documentation/ABI/obsolte/sysfs-class-rfkill. +Documentation/ABI/obsolete/sysfs-class-rfkill. What: /sys/class/rfkill Date: 09-Jul-2007 @@ -42,8 +42,8 @@ Values: A numeric value. 1: true -What: /sys/class/rfkill/rfkill[0-9]+/blocked_hw -Date: 23-Feb-2010 +What: /sys/class/rfkill/rfkill[0-9]+/hard +Date: 12-March-2010 KernelVersion v2.6.34 Contact: linux-wireless@vger.kernel.org Description: Current hardblock state. This file is read only. @@ -55,8 +55,8 @@ Values: A numeric value. the driver's control. -What: /sys/class/rfkill/rfkill[0-9]+/blocked_sw -Date: 23-Feb-2010 +What: /sys/class/rfkill/rfkill[0-9]+/soft +Date: 12-March-2010 KernelVersion v2.6.34 Contact: linux-wireless@vger.kernel.org Description: Current softblock state. This file is read and write. diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 5f33151d70a..7ae58b5b5a0 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -628,37 +628,25 @@ static ssize_t rfkill_persistent_show(struct device *dev, return sprintf(buf, "%d\n", rfkill->persistent); } -static ssize_t rfkill_blocked_hw_show(struct device *dev, +static ssize_t rfkill_hard_show(struct device *dev, struct device_attribute *attr, char *buf) { struct rfkill *rfkill = to_rfkill(dev); - unsigned long flags; - u32 state; - spin_lock_irqsave(&rfkill->lock, flags); - state = rfkill->state; - spin_unlock_irqrestore(&rfkill->lock, flags); - - return sprintf(buf, "%d\n", (state & RFKILL_BLOCK_HW) ? 1 : 0 ); + return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_HW) ? 1 : 0 ); } -static ssize_t rfkill_blocked_sw_show(struct device *dev, +static ssize_t rfkill_soft_show(struct device *dev, struct device_attribute *attr, char *buf) { struct rfkill *rfkill = to_rfkill(dev); - unsigned long flags; - u32 state; - - spin_lock_irqsave(&rfkill->lock, flags); - state = rfkill->state; - spin_unlock_irqrestore(&rfkill->lock, flags); - return sprintf(buf, "%d\n", (state & RFKILL_BLOCK_SW) ? 1 : 0 ); + return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0 ); } -static ssize_t rfkill_blocked_sw_store(struct device *dev, +static ssize_t rfkill_soft_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -698,14 +686,8 @@ static ssize_t rfkill_state_show(struct device *dev, char *buf) { struct rfkill *rfkill = to_rfkill(dev); - unsigned long flags; - u32 state; - - spin_lock_irqsave(&rfkill->lock, flags); - state = rfkill->state; - spin_unlock_irqrestore(&rfkill->lock, flags); - return sprintf(buf, "%d\n", user_state_from_blocked(state)); + return sprintf(buf, "%d\n", user_state_from_blocked(rfkill->state)); } static ssize_t rfkill_state_store(struct device *dev, @@ -755,9 +737,8 @@ static struct device_attribute rfkill_dev_attrs[] = { __ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL), __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), - __ATTR(sw, S_IRUGO|S_IWUSR, rfkill_blocked_sw_show, - rfkill_blocked_sw_store), - __ATTR(hw, S_IRUGO, rfkill_blocked_hw_show, NULL), + __ATTR(soft, S_IRUGO|S_IWUSR, rfkill_soft_show, rfkill_soft_store), + __ATTR(hard, S_IRUGO, rfkill_hard_show, NULL), __ATTR_NULL }; -- cgit v1.2.3