From 46026e8f487c075f9ec4d671348e351eb5e46d3e Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 10 Jun 2009 22:22:20 -0400 Subject: ath5k: cleanup ath5k_hw struct ah_gpios array isn't used, and ah_current_channel can be a pointer instead of an embedded struct. Removing these and some other write-only variables, and moving some things around for better packing and cache utilization saves 116 bytes. text data bss dec hex filename 121762 472 64 122298 1ddba ath5k_before.ko 121646 472 64 122182 1dd46 ath5k.ko Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 21 +++++++-------------- drivers/net/wireless/ath/ath5k/phy.c | 7 +++---- drivers/net/wireless/ath/ath5k/reset.c | 1 - 3 files changed, 10 insertions(+), 19 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 6358233bac99..91375113916b 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -713,8 +713,8 @@ struct ath5k_gain { * Used internaly for reset_tx_queue). * Also see struct struct ieee80211_channel. */ -#define IS_CHAN_XR(_c) ((_c.hw_value & CHANNEL_XR) != 0) -#define IS_CHAN_B(_c) ((_c.hw_value & CHANNEL_B) != 0) +#define IS_CHAN_XR(_c) ((_c->hw_value & CHANNEL_XR) != 0) +#define IS_CHAN_B(_c) ((_c->hw_value & CHANNEL_B) != 0) /* * The following structure is used to map 2GHz channels to @@ -1029,14 +1029,15 @@ struct ath5k_hw { enum ath5k_int ah_imr; enum nl80211_iftype ah_op_mode; - enum ath5k_power_mode ah_power_mode; - struct ieee80211_channel ah_current_channel; + struct ieee80211_channel *ah_current_channel; bool ah_turbo; bool ah_calibration; - bool ah_running; bool ah_single_chip; bool ah_combined_mic; + enum ath5k_version ah_version; + enum ath5k_radio ah_radio; + u32 ah_phy; u32 ah_mac_srev; u16 ah_mac_version; u16 ah_mac_revision; @@ -1044,13 +1045,6 @@ struct ath5k_hw { u16 ah_radio_5ghz_revision; u16 ah_radio_2ghz_revision; - enum ath5k_version ah_version; - enum ath5k_radio ah_radio; - u32 ah_phy; - - bool ah_5ghz; - bool ah_2ghz; - #define ah_modes ah_capabilities.cap_mode #define ah_ee_version ah_capabilities.cap_eeprom.ee_version @@ -1058,7 +1052,6 @@ struct ath5k_hw { u32 ah_aifs; u32 ah_cw_min; u32 ah_cw_max; - bool ah_software_retry; u32 ah_limit_tx_retries; /* Antenna Control */ @@ -1066,6 +1059,7 @@ struct ath5k_hw { u8 ah_ant_mode; u8 ah_tx_ant; u8 ah_def_ant; + bool ah_software_retry; u8 ah_sta_id[ETH_ALEN]; @@ -1075,7 +1069,6 @@ struct ath5k_hw { u8 ah_bssid[ETH_ALEN]; u8 ah_bssid_mask[ETH_ALEN]; - u32 ah_gpio[AR5K_MAX_GPIO]; int ah_gpio_npins; struct ath_regulatory ah_regulatory; diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index a876ca8d69ef..2075ba993966 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1085,8 +1085,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) AR5K_PHY_CCKTXCTL_WORLD); } - ah->ah_current_channel.center_freq = channel->center_freq; - ah->ah_current_channel.hw_value = channel->hw_value; + ah->ah_current_channel = channel; ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; return 0; @@ -1731,7 +1730,7 @@ ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable) void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) { - struct ieee80211_channel *channel = &ah->ah_current_channel; + struct ieee80211_channel *channel = ah->ah_current_channel; bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div; bool use_def_for_sg; u8 def_ant, tx_ant, ee_mode; @@ -3011,7 +3010,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) { /*Just a try M.F.*/ - struct ieee80211_channel *channel = &ah->ah_current_channel; + struct ieee80211_channel *channel = ah->ah_current_channel; u8 ee_mode; ATH5K_TRACE(ah->ah_sc); diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index bd0a97a38d34..86733fdb4774 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -290,7 +290,6 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, } commit: - ah->ah_power_mode = mode; ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1); return 0; -- cgit v1.2.3 From f0f3d388baabdbc613548d6ad8e5da7616b1cbd1 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 10 Jun 2009 22:22:21 -0400 Subject: ath5k: enable hardware LEDs Cardbus and some PCI cards use hardware LEDs rather than software GPIOs. Program them with the proper blink patterns when idle, scanning or associated. Fixes http://bugzilla.kernel.org/show_bug.cgi?id=13288. Tested-by: Frans Pop Tested-by: Mark Hindley Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/attach.c | 3 +++ drivers/net/wireless/ath/ath5k/base.c | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index c41ef58393e7..9a84d9410b27 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -319,6 +319,9 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ath5k_hw_rfgain_opt_init(ah); + /* turn on HW LEDs */ + ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); + return ah; err_free: kfree(ah); diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index ea045151f953..f26a68960622 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -248,6 +248,8 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes); +static void ath5k_sw_scan_start(struct ieee80211_hw *hw); +static void ath5k_sw_scan_complete(struct ieee80211_hw *hw); static const struct ieee80211_ops ath5k_hw_ops = { .tx = ath5k_tx, @@ -265,6 +267,8 @@ static const struct ieee80211_ops ath5k_hw_ops = { .set_tsf = ath5k_set_tsf, .reset_tsf = ath5k_reset_tsf, .bss_info_changed = ath5k_bss_info_changed, + .sw_scan_start = ath5k_sw_scan_start, + .sw_scan_complete = ath5k_sw_scan_complete, }; /* @@ -3167,6 +3171,8 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, sc->assoc = bss_conf->assoc; if (sc->opmode == NL80211_IFTYPE_STATION) set_beacon_filter(hw, sc->assoc); + ath5k_hw_set_ledstate(sc->ah, sc->assoc ? + AR5K_LED_ASSOC : AR5K_LED_INIT); } if (changes & BSS_CHANGED_BEACON && @@ -3179,3 +3185,17 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, unlock: mutex_unlock(&sc->lock); } + +static void ath5k_sw_scan_start(struct ieee80211_hw *hw) +{ + struct ath5k_softc *sc = hw->priv; + if (!sc->assoc) + ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN); +} + +static void ath5k_sw_scan_complete(struct ieee80211_hw *hw) +{ + struct ath5k_softc *sc = hw->priv; + ath5k_hw_set_ledstate(sc->ah, sc->assoc ? + AR5K_LED_ASSOC : AR5K_LED_INIT); +} -- cgit v1.2.3 From f1d58c2521eb160178b2151d6326d8dc5d7c8560 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 17 Jun 2009 13:13:00 +0200 Subject: mac80211: push rx status into skb->cb Within mac80211, we often need to copy the rx status into skb->cb. This is wasteful, as drivers could be building it in there to start with. This patch changes the API so that drivers are expected to pass the RX status in skb->cb, now accessible as IEEE80211_SKB_RXCB(skb). It also updates all drivers to pass the rx status in there, but only by making them memcpy() it into place before the call to the receive function (ieee80211_rx(_irqsafe)). Each driver can now be optimised on its own schedule. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index f26a68960622..c6e70919435c 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1905,7 +1905,8 @@ accept: if (sc->opmode == NL80211_IFTYPE_ADHOC) ath5k_check_ibss_tsf(sc, skb, &rxs); - __ieee80211_rx(sc->hw, skb, &rxs); + memcpy(IEEE80211_SKB_RXCB(skb), &rxs, sizeof(rxs)); + ieee80211_rx(sc->hw, skb); bf->skb = next_skb; bf->skbaddr = next_skb_addr; -- cgit v1.2.3 From 31670070ffe18f8e8743109b19297a0efac0a72c Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sun, 28 Jun 2009 23:25:27 +0200 Subject: ath5k: remove permissions from debugfs files Don't allow users to open debugfs files, because it can cause oopses. When a user opens some file, driver unlinks it and frees the corresponding structure, we will dereference freed memory. Signed-off-by: Jiri Slaby Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/debug.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 4904a07e4b59..747508c15d34 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -380,13 +380,15 @@ ath5k_debug_init_device(struct ath5k_softc *sc) sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy), ath5k_global_debugfs); - sc->debug.debugfs_debug = debugfs_create_file("debug", S_IWUSR | S_IRUGO, + sc->debug.debugfs_debug = debugfs_create_file("debug", + S_IWUSR | S_IRUSR, sc->debug.debugfs_phydir, sc, &fops_debug); - sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO, + sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR, sc->debug.debugfs_phydir, sc, &fops_registers); - sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO, + sc->debug.debugfs_beacon = debugfs_create_file("beacon", + S_IWUSR | S_IRUSR, sc->debug.debugfs_phydir, sc, &fops_beacon); sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, -- cgit v1.2.3 From cec8db23011d2a0a5ec101a0263d79678adf21ba Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 4 Jul 2009 12:59:51 -0400 Subject: ath5k: send buffered frames after the beacon Enable the "Content" After Beacon queue and utilize it to send any buffered frames for power-saving clients. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 35 ++++++++++++++++++++++++++++++----- drivers/net/wireless/ath/ath5k/base.h | 9 ++++----- drivers/net/wireless/ath/ath5k/qcu.c | 1 - 3 files changed, 34 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index c6e70919435c..87ebc461d74a 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -218,6 +218,8 @@ static struct pci_driver ath5k_pci_driver = { * Prototypes - MAC 802.11 stack related functions */ static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb); +static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, + struct ath5k_txq *txq); static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); static int ath5k_reset_wake(struct ath5k_softc *sc); static int ath5k_start(struct ieee80211_hw *hw); @@ -301,7 +303,8 @@ static void ath5k_desc_free(struct ath5k_softc *sc, 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_buf *bf, + struct ath5k_txq *txq); static inline void ath5k_txbuf_free(struct ath5k_softc *sc, struct ath5k_buf *bf) { @@ -516,6 +519,7 @@ ath5k_pci_probe(struct pci_dev *pdev, /* Initialize driver private data */ SET_IEEE80211_DEV(hw, &pdev->dev); hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; @@ -789,12 +793,18 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) goto err_desc; } sc->bhalq = ret; + sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0); + if (IS_ERR(sc->cabq)) { + ATH5K_ERR(sc, "can't setup cab queue\n"); + ret = PTR_ERR(sc->cabq); + goto err_bhal; + } sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); if (IS_ERR(sc->txq)) { ATH5K_ERR(sc, "can't setup xmit queue\n"); ret = PTR_ERR(sc->txq); - goto err_bhal; + goto err_queues; } tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); @@ -1232,10 +1242,10 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) } static int -ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) +ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, + struct ath5k_txq *txq) { struct ath5k_hw *ah = sc->ah; - struct ath5k_txq *txq = sc->txq; struct ath5k_desc *ds = bf->desc; struct sk_buff *skb = bf->skb; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -2103,6 +2113,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) { struct ath5k_buf *bf = sc->bbuf; struct ath5k_hw *ah = sc->ah; + struct sk_buff *skb; ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); @@ -2156,6 +2167,12 @@ ath5k_beacon_send(struct ath5k_softc *sc) ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", sc->bhalq, (unsigned long long)bf->daddr, bf->desc); + skb = ieee80211_get_buffered_bc(sc->hw, sc->vif); + while (skb) { + ath5k_tx_queue(sc->hw, skb, sc->cabq); + skb = ieee80211_get_buffered_bc(sc->hw, sc->vif); + } + sc->bsent++; } @@ -2601,6 +2618,14 @@ ath5k_calibrate(unsigned long data) static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ath5k_softc *sc = hw->priv; + + return ath5k_tx_queue(hw, skb, sc->txq); +} + +static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, + struct ath5k_txq *txq) { struct ath5k_softc *sc = hw->priv; struct ath5k_buf *bf; @@ -2646,7 +2671,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) bf->skb = skb; - if (ath5k_txbuf_setup(sc, bf)) { + if (ath5k_txbuf_setup(sc, bf, txq)) { bf->skb = NULL; spin_lock_irqsave(&sc->txbuflock, flags); list_add_tail(&bf->list, &sc->txbuf); diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index f9b7f2f819b7..65e75fb54482 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -114,8 +114,7 @@ struct ath5k_softc { struct pci_dev *pdev; /* for dma mapping */ void __iomem *iobase; /* address of the device */ struct mutex lock; /* dev-level lock */ - /* FIXME: how many does it really need? */ - struct ieee80211_tx_queue_stats tx_stats[16]; + struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES]; struct ieee80211_low_level_stats ll_stats; struct ieee80211_hw *hw; /* IEEE 802.11 common */ struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; @@ -171,9 +170,8 @@ struct ath5k_softc { struct list_head txbuf; /* transmit buffer */ spinlock_t txbuflock; unsigned int txbuf_len; /* buf count in txbuf list */ - struct ath5k_txq txqs[2]; /* beacon and tx */ - - struct ath5k_txq *txq; /* beacon and tx*/ + struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */ + struct ath5k_txq *txq; /* main tx queue */ struct tasklet_struct txtq; /* tx intr tasklet */ struct ath5k_led tx_led; /* tx led */ @@ -187,6 +185,7 @@ struct ath5k_softc { bintval, /* beacon interval in TU */ bsent; unsigned int nexttbtt; /* next beacon time in TU */ + struct ath5k_txq *cabq; /* content after beacon */ struct timer_list calib_tim; /* calibration timer */ int power_level; /* Requested tx power in dbm */ diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 73407b3f53ef..6d5aaf00d8bb 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -411,7 +411,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), AR5K_QCU_MISC_FRSHED_BCN_SENT_GT | AR5K_QCU_MISC_CBREXP_DIS | - AR5K_QCU_MISC_RDY_VEOL_POLICY | AR5K_QCU_MISC_CBREXP_BCN_DIS); ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - -- cgit v1.2.3 From 21800491cc5c48e9f1084a6f524a0da7c2525cc6 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 4 Jul 2009 12:59:52 -0400 Subject: ath5k: rework beacon configuration Using the enable_beacon flag allows some simplifications and fixes some corner cases in beacon handling. This change adds a state variable for beaconing in ath5k_beacon_config and handles both enabling and disabling, thus eliminating the need for ath5k_beacon_disable. We also now configure the beacon when any of the beacon parameters change, so ath5k_beacon_reconfig is no longer needed (its mmiowb gets moved to ath5k_beacon_config). Finally, by locking around the whole config function, we don't need to worry about clearing the interrupt mask register before installing the new mask. The upshot is this correctly disables beaconing when the interfaces are taken down, it fixes a potential restarting of beaconing when ath5k_reset() is called, and ensures that updates to the beacon interval take effect immediately. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 59 +++++++++++------------------------ drivers/net/wireless/ath/ath5k/base.h | 1 + 2 files changed, 20 insertions(+), 40 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 87ebc461d74a..482932979c9b 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2093,13 +2093,6 @@ err_unmap: return ret; } -static void ath5k_beacon_disable(struct ath5k_softc *sc) -{ - sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); - ath5k_hw_set_imr(sc->ah, sc->imask); - ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq); -} - /* * Transmit a beacon frame at SWBA. Dynamic updates to the * frame contents are done as needed and the slot time is @@ -2293,13 +2286,11 @@ ath5k_beacon_config(struct ath5k_softc *sc) struct ath5k_hw *ah = sc->ah; unsigned long flags; - ath5k_hw_set_imr(ah, 0); + spin_lock_irqsave(&sc->block, flags); sc->bmisscount = 0; sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); - if (sc->opmode == NL80211_IFTYPE_ADHOC || - sc->opmode == NL80211_IFTYPE_MESH_POINT || - sc->opmode == NL80211_IFTYPE_AP) { + if (sc->enable_beacon) { /* * In IBSS mode we use a self-linked tx descriptor and let the * hardware send the beacons automatically. We have to load it @@ -2312,16 +2303,17 @@ ath5k_beacon_config(struct ath5k_softc *sc) sc->imask |= AR5K_INT_SWBA; if (sc->opmode == NL80211_IFTYPE_ADHOC) { - if (ath5k_hw_hasveol(ah)) { - spin_lock_irqsave(&sc->block, flags); + if (ath5k_hw_hasveol(ah)) ath5k_beacon_send(sc); - spin_unlock_irqrestore(&sc->block, flags); - } } else ath5k_beacon_update_timers(sc, -1); + } else { + ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq); } ath5k_hw_set_imr(ah, sc->imask); + mmiowb(); + spin_unlock_irqrestore(&sc->block, flags); } static void ath5k_tasklet_beacon(unsigned long data) @@ -2806,7 +2798,6 @@ ath5k_remove_interface(struct ieee80211_hw *hw, goto end; ath5k_hw_set_lladdr(sc->ah, mac); - ath5k_beacon_disable(sc); sc->vif = NULL; end: mutex_unlock(&sc->lock); @@ -3135,25 +3126,6 @@ out: return ret; } -/* - * Update the beacon and reconfigure the beacon queues. - */ -static void -ath5k_beacon_reconfig(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - int ret; - unsigned long flags; - struct ath5k_softc *sc = hw->priv; - - spin_lock_irqsave(&sc->block, flags); - ret = ath5k_beacon_update(hw, vif); - spin_unlock_irqrestore(&sc->block, flags); - if (ret == 0) { - ath5k_beacon_config(sc); - mmiowb(); - } -} - static void set_beacon_filter(struct ieee80211_hw *hw, bool enable) { @@ -3176,6 +3148,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, { struct ath5k_softc *sc = hw->priv; struct ath5k_hw *ah = sc->ah; + unsigned long flags; mutex_lock(&sc->lock); if (WARN_ON(sc->vif != vif)) @@ -3201,13 +3174,19 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, AR5K_LED_ASSOC : AR5K_LED_INIT); } - if (changes & BSS_CHANGED_BEACON && - (vif->type == NL80211_IFTYPE_ADHOC || - vif->type == NL80211_IFTYPE_MESH_POINT || - vif->type == NL80211_IFTYPE_AP)) { - ath5k_beacon_reconfig(hw, vif); + if (changes & BSS_CHANGED_BEACON) { + spin_lock_irqsave(&sc->block, flags); + ath5k_beacon_update(hw, vif); + spin_unlock_irqrestore(&sc->block, flags); } + if (changes & BSS_CHANGED_BEACON_ENABLED) + sc->enable_beacon = bss_conf->enable_beacon; + + if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED | + BSS_CHANGED_BEACON_INT)) + ath5k_beacon_config(sc); + unlock: mutex_unlock(&sc->lock); } diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 65e75fb54482..778e422946ab 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -190,6 +190,7 @@ struct ath5k_softc { struct timer_list calib_tim; /* calibration timer */ int power_level; /* Requested tx power in dbm */ bool assoc; /* assocate state */ + bool enable_beacon; /* true if beacons are on */ }; #define ath5k_hw_hasbssidmask(_ah) \ -- cgit v1.2.3 From 0d0cd72fa1e6bfd419c99478ec70b4877ed0ef86 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 4 Jul 2009 12:59:54 -0400 Subject: ath5k: do not release irq across suspend/resume Paraphrasing Rafael J. Wysocki: "drivers should not release PCI IRQs in suspend." Doing so causes a warning during suspend/resume on some platforms. Cc: Rafael J. Wysocki Reported-by: Alan Jenkins Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 482932979c9b..3f55e90c43fc 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -674,7 +674,6 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) ath5k_led_off(sc); - free_irq(pdev->irq, sc); pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); @@ -702,18 +701,8 @@ ath5k_pci_resume(struct pci_dev *pdev) */ pci_write_config_byte(pdev, 0x41, 0); - err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); - if (err) { - ATH5K_ERR(sc, "request_irq failed\n"); - goto err_no_irq; - } - ath5k_led_enable(sc); return 0; - -err_no_irq: - pci_disable_device(pdev); - return err; } #endif /* CONFIG_PM */ -- cgit v1.2.3 From 3355443ad7601991affa5992b0d53870335af765 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 4 Jul 2009 21:03:13 -0400 Subject: ath5k: write PCU registers on initial reset "Ath5k: unify resets" introduced a regression into 2.6.28 where the PCU registers are never initialized, due to ath5k_reset() always passing true for change_channel. We subsequently program a lot of these registers but several may start in an unknown state. Cc: stable@kernel.org Reported-by: Forrest Zhang Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 3f55e90c43fc..20ba6fa5f1f1 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2687,7 +2687,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) sc->curchan = chan; sc->curband = &sc->sbands[chan->band]; } - ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true); + ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL); if (ret) { ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); goto err; -- cgit v1.2.3 From f974cfdd8112a081fb1a402bf77835f28f37fcad Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Mon, 20 Jul 2009 08:00:30 -0400 Subject: ath5k: fix values for bus error bits in ISR2 The new values are taken from the recently open sourced Atheros HAL. Correctness is also confirmed by the users with access to Atheros documentation. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/reg.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 6809b54a2ad7..debad07d9900 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -339,9 +339,9 @@ #define AR5K_SISR2 0x008c /* Register Address [5211+] */ #define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ #define AR5K_SISR2_QCU_TXURN_S 0 -#define AR5K_SISR2_MCABT 0x00100000 /* Master Cycle Abort */ -#define AR5K_SISR2_SSERR 0x00200000 /* Signaled System Error */ -#define AR5K_SISR2_DPERR 0x00400000 /* Bus parity error */ +#define AR5K_SISR2_MCABT 0x00010000 /* Master Cycle Abort */ +#define AR5K_SISR2_SSERR 0x00020000 /* Signaled System Error */ +#define AR5K_SISR2_DPERR 0x00040000 /* Bus parity error */ #define AR5K_SISR2_TIM 0x01000000 /* [5212+] */ #define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */ #define AR5K_SISR2_DTIM_SYNC 0x04000000 /* DTIM sync lost [5212+] */ @@ -430,9 +430,9 @@ #define AR5K_SIMR2 0x00ac /* Register Address [5211+] */ #define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ #define AR5K_SIMR2_QCU_TXURN_S 0 -#define AR5K_SIMR2_MCABT 0x00100000 /* Master Cycle Abort */ -#define AR5K_SIMR2_SSERR 0x00200000 /* Signaled System Error */ -#define AR5K_SIMR2_DPERR 0x00400000 /* Bus parity error */ +#define AR5K_SIMR2_MCABT 0x00010000 /* Master Cycle Abort */ +#define AR5K_SIMR2_SSERR 0x00020000 /* Signaled System Error */ +#define AR5K_SIMR2_DPERR 0x00040000 /* Bus parity error */ #define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */ #define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */ #define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* DTIM Sync lost [5212+] */ -- cgit v1.2.3 From b820b3bcb02a97091b969faf2b5f19f1218953f9 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 27 Jul 2009 16:52:07 -0700 Subject: ath: simplify kconfig dependency and add documentation Make atheros wireless drivers visible when you select "Atheros wirless drivers". Adds links to ath.ko page, and Atheros drivers page on the wiki. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig index daf0c83527d8..9b07eef7c610 100644 --- a/drivers/net/wireless/ath/ath5k/Kconfig +++ b/drivers/net/wireless/ath/ath5k/Kconfig @@ -1,7 +1,6 @@ config ATH5K tristate "Atheros 5xxx wireless cards support" depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL - select ATH_COMMON select MAC80211_LEDS select LEDS_CLASS select NEW_LEDS -- cgit v1.2.3 From 75323fa3dec54abb0bcba8ce6b4994020af210ca Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 27 Jul 2009 16:52:09 -0700 Subject: ath5k: remove EXPERIMENTAL marker Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig index 9b07eef7c610..06d006675d7d 100644 --- a/drivers/net/wireless/ath/ath5k/Kconfig +++ b/drivers/net/wireless/ath/ath5k/Kconfig @@ -1,6 +1,6 @@ config ATH5K tristate "Atheros 5xxx wireless cards support" - depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL + depends on PCI && MAC80211 && WLAN_80211 select MAC80211_LEDS select LEDS_CLASS select NEW_LEDS -- cgit v1.2.3 From ae6f53f25f9803212d1985b5eb5a03111f439c24 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 29 Jul 2009 10:29:03 -0400 Subject: ath5k: update PCU opmode whenever a new interface is added Previously, we would store the operating mode at interface up time, but only update the PCU registers when the next reset happened. The result is that if beacon configuration (ops->bss_info_changed) happens before ops->config, we will program the wrong things into the timer registers. Consequently, beacons won't work in AP mode until after a reset (channel change, scan etc.). This is fragile anyway so just program the opmode as soon as mac80211 gives it to us. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 7db32ce3dbd8..55ee976ab6d7 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1117,6 +1117,8 @@ 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); @@ -2768,6 +2770,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, } ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); + ath5k_mode_setup(sc); ret = 0; end: -- cgit v1.2.3 From 8784d2ee92fc835bf18dd5096f00ec9a48dc0590 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 29 Jul 2009 17:32:28 -0400 Subject: ath5k: fix CAB queue operation We need to process tx descriptors for all queues (currently main tx queue and cabq) which may have triggered the TX completion interrupt. Otherwise, the queues can get stuck after sending a few frames. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 55ee976ab6d7..3a1c156d275f 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2000,9 +2000,12 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) static void ath5k_tasklet_tx(unsigned long data) { + int i; struct ath5k_softc *sc = (void *)data; - ath5k_tx_processq(sc, sc->txq); + for (i=0; i < AR5K_NUM_TX_QUEUES; i++) + if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i))) + ath5k_tx_processq(sc, &sc->txqs[i]); } -- cgit v1.2.3 From e30eb4ab45211c2f27b6bb9b29124ac431e01ce9 Mon Sep 17 00:00:00 2001 From: Joerg Albert Date: Wed, 5 Aug 2009 01:52:07 +0200 Subject: ath5k: fix missing output in monitor mode after ifconfig up Let ath5k_chan_set() always call ath5k_reset(). This fixes the bug that we don't get any packets in monitor mode after: ifconfig wlan0 down iwconfig wlan0 mode monitor channel 1 ifconfig wlan0 up but they arrive after iwconfig wlan0 channel 2 Signed-off-by: Joerg Albert Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 3a1c156d275f..5d5028538ac2 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1071,10 +1071,9 @@ ath5k_setup_bands(struct ieee80211_hw *hw) } /* - * Set/change channels. If the channel is really being changed, - * it's done by reseting the chip. To accomplish this we must - * first cleanup any pending DMA, then restart stuff after a la - * ath5k_init. + * Set/change channels. We always reset the chip. + * To accomplish this we must first cleanup any pending DMA, + * then restart stuff after a la ath5k_init. * * Called with sc->lock. */ @@ -1084,19 +1083,13 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n", sc->curchan->center_freq, chan->center_freq); - if (chan->center_freq != sc->curchan->center_freq || - chan->hw_value != sc->curchan->hw_value) { - - /* - * To switch channels clear any pending DMA operations; - * wait long enough for the RX fifo to drain, reset the - * hardware at the new frequency, and then re-enable - * the relevant bits of the h/w. - */ - return ath5k_reset(sc, chan); - } - - return 0; + /* + * To switch channels clear any pending DMA operations; + * wait long enough for the RX fifo to drain, reset the + * hardware at the new frequency, and then re-enable + * the relevant bits of the h/w. + */ + return ath5k_reset(sc, chan); } static void @@ -2811,9 +2804,11 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&sc->lock); - ret = ath5k_chan_set(sc, conf->channel); - if (ret < 0) - goto unlock; + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + ret = ath5k_chan_set(sc, conf->channel); + if (ret < 0) + goto unlock; + } if ((changed & IEEE80211_CONF_CHANGE_POWER) && (sc->power_level != conf->power_level)) { -- cgit v1.2.3 From 4d30d309a3be84dfb01743ceb4652405204a80a0 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 8 Aug 2009 15:22:26 +0200 Subject: drivers/net/wireless/ath/ath5k: Change constant name Elsewhere, the tqi_type field is compared to constants having a name beginning with AR5K_TX_QUEUE, rather than AR5K_TX_QUEUE_ID. I have thus converted AR5K_TX_QUEUE_ID_CAB to AR5K_TX_QUEUE_CAB. This does, however, change the value, so perhaps something else was wanted. Signed-off-by: Julia Lawall Acked-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/qcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 6d5aaf00d8bb..eeebb9aef206 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -362,7 +362,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) } if (tq->tqi_ready_time && - (tq->tqi_type != AR5K_TX_QUEUE_ID_CAB)) + (tq->tqi_type != AR5K_TX_QUEUE_CAB)) ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, AR5K_QCU_RDYTIMECFG_INTVAL) | AR5K_QCU_RDYTIMECFG_ENABLE, -- cgit v1.2.3 From c38e7a9348f725be0ea2493454db9e6d44fb7e0c Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Mon, 10 Aug 2009 03:26:55 +0300 Subject: ath5k: Check EEPROM before tweaking SERDES * Read PCI-E infos offset from EEPROM and if it points to serdes section (0x40), enable serdes programming (further tweaking of serdes values during attach). This follows Legacy and Sam's HAL sources. Signed-off-by: Nick Kossifidis Acked-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/attach.c | 56 ++++++++++++++++++++------------- drivers/net/wireless/ath/ath5k/eeprom.c | 10 ++++++ drivers/net/wireless/ath/ath5k/eeprom.h | 4 +++ 3 files changed, 48 insertions(+), 22 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 9a84d9410b27..626306592cf8 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -252,28 +252,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) goto err_free; } - /* - * Write PCI-E power save settings - */ - if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { - ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); - ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); - /* Shut off RX when elecidle is asserted */ - ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES); - ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES); - /* TODO: EEPROM work */ - ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES); - /* Shut off PLL and CLKREQ active in L1 */ - ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES); - /* Preserce other settings */ - ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES); - ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES); - ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES); - /* Reset SERDES to load new settings */ - ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET); - mdelay(1); - } - /* * POST */ @@ -295,6 +273,40 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) goto err_free; } + /* + * Write PCI-E power save settings + */ + if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + + ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); + ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); + + /* Shut off RX when elecidle is asserted */ + ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES); + ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES); + + /* If serdes programing is enabled, increase PCI-E + * tx power for systems with long trace from host + * to minicard connector. */ + if (ee->ee_serdes) + ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES); + else + ath5k_hw_reg_write(ah, 0xf6800579, AR5K_PCIE_SERDES); + + /* Shut off PLL and CLKREQ active in L1 */ + ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES); + + /* Preserve other settings */ + ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES); + ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES); + ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES); + + /* Reset SERDES to load new settings */ + ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET); + mdelay(1); + } + /* Get misc capabilities */ ret = ath5k_hw_set_capabilities(ah); if (ret) { diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index c56b494d417a..8af477dd6fc7 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -167,6 +167,16 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) ee->ee_rfkill_pin = (u8) AR5K_REG_MS(val, AR5K_EEPROM_RFKILL_GPIO_SEL); ee->ee_rfkill_pol = val & AR5K_EEPROM_RFKILL_POLARITY ? true : false; + /* Check if PCIE_OFFSET points to PCIE_SERDES_SECTION + * and enable serdes programming if needed. + * + * XXX: Serdes values seem to be fixed so + * no need to read them here, we write them + * during ath5k_hw_attach */ + AR5K_EEPROM_READ(AR5K_EEPROM_PCIE_OFFSET, val); + ee->ee_serdes = (val == AR5K_EEPROM_PCIE_SERDES_SECTION) ? + true : false; + return 0; } diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 64be73a5edae..0123f3521a0b 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -19,6 +19,9 @@ /* * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE) */ +#define AR5K_EEPROM_PCIE_OFFSET 0x02 /* Contains offset to PCI-E infos */ +#define AR5K_EEPROM_PCIE_SERDES_SECTION 0x40 /* PCIE_OFFSET points here when + * 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 */ @@ -391,6 +394,7 @@ struct ath5k_eeprom_info { u8 ee_rfkill_pin; bool ee_rfkill_pol; bool ee_is_hb63; + bool ee_serdes; u16 ee_misc0; u16 ee_misc1; u16 ee_misc2; -- cgit v1.2.3 From d1cb0bdac180a4afdd3c001acb2618d2a62d9abe Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Mon, 10 Aug 2009 03:27:59 +0300 Subject: ath5k: Linear PCDAC code fixes * Set correct xpd curve indices for high/low gain curves during rfbuffer setup on RF5112B with both calibration curves available. * Don't return zero min power when we have the same pcdac value twice because it breaks interpolation. Instead return the right x barrier as we do when we have equal power levels for 2 different pcdac values. Signed-off-by: Nick Kossifidis Acked-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/phy.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 2075ba993966..6afba98f6adb 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -740,13 +740,22 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, AR5K_RF_XPD_GAIN, true); } else { - /* TODO: Set high and low gain bits */ - ath5k_hw_rfb_op(ah, rf_regs, - ee->ee_x_gain[ee_mode], + u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode]; + if (ee->ee_pd_gains[ee_mode] > 1) { + ath5k_hw_rfb_op(ah, rf_regs, + pdg_curve_to_idx[0], AR5K_RF_PD_GAIN_LO, true); - ath5k_hw_rfb_op(ah, rf_regs, - ee->ee_x_gain[ee_mode], + ath5k_hw_rfb_op(ah, rf_regs, + pdg_curve_to_idx[1], AR5K_RF_PD_GAIN_HI, true); + } else { + ath5k_hw_rfb_op(ah, rf_regs, + pdg_curve_to_idx[0], + AR5K_RF_PD_GAIN_LO, true); + ath5k_hw_rfb_op(ah, rf_regs, + pdg_curve_to_idx[0], + AR5K_RF_PD_GAIN_HI, true); + } /* Lower synth voltage on Rev 2 */ ath5k_hw_rfb_op(ah, rf_regs, 2, @@ -1896,8 +1905,9 @@ ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR, s16 min_pwrL, min_pwrR; s16 pwr_i; - if (WARN_ON(stepL[0] == stepL[1] || stepR[0] == stepR[1])) - return 0; + /* Some vendors write the same pcdac value twice !!! */ + if (stepL[0] == stepL[1] || stepR[0] == stepR[1]) + return max(pwrL[0], pwrR[0]); if (pwrL[0] == pwrL[1]) min_pwrL = pwrL[0]; -- cgit v1.2.3 From edd7fc7003f31da48d06e215a93ea966a22c2a03 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Mon, 10 Aug 2009 03:29:02 +0300 Subject: ath5k: Wakeup fixes * Don't put chip to full sleep because there are problems during wakeup. Instead hold MAC/Baseband on warm reset state via a new function ath5k_hw_on_hold. * Minor cleanups Signed-off-by: Nick Kossifidis Tested-by: Ben Greear Tested-by: Johannes Stezenbach Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 1 + drivers/net/wireless/ath/ath5k/attach.c | 2 +- drivers/net/wireless/ath/ath5k/base.c | 44 ++++----- drivers/net/wireless/ath/ath5k/reset.c | 155 +++++++++++++++++++++++--------- 4 files changed, 140 insertions(+), 62 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 91375113916b..1047a6cb1d92 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1157,6 +1157,7 @@ extern 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); /* Power management functions */ extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration); diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 626306592cf8..238eeb7e166e 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -145,7 +145,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) goto err_free; /* Bring device out of sleep and reset it's units */ - ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, true); + ret = ath5k_hw_nic_wakeup(ah, 0, true); if (ret) goto err_free; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 5d5028538ac2..0370cba8356c 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2446,27 +2446,29 @@ ath5k_stop_hw(struct ath5k_softc *sc) ret = ath5k_stop_locked(sc); if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) { /* - * Set the chip in full sleep mode. Note that we are - * careful to do this only when bringing the interface - * completely to a stop. When the chip is in this state - * it must be carefully woken up or references to - * registers in the PCI clock domain may freeze the bus - * (and system). This varies by chip and is mostly an - * issue with newer parts that go to sleep more quickly. - */ - if (sc->ah->ah_mac_srev >= 0x78) { - /* - * XXX - * don't put newer MAC revisions > 7.8 to sleep because - * of the above mentioned problems - */ - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mac version > 7.8, " - "not putting device to sleep\n"); - } else { - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, - "putting device to full sleep\n"); - ath5k_hw_set_power(sc->ah, AR5K_PM_FULL_SLEEP, true, 0); - } + * Don't set the card in full sleep mode! + * + * a) When the device is in this state it must be carefully + * woken up or references to registers in the PCI clock + * domain may freeze the bus (and system). This varies + * by chip and is mostly an issue with newer parts + * (madwifi sources mentioned srev >= 0x78) that go to + * sleep more quickly. + * + * b) On older chips full sleep results a weird behaviour + * during wakeup. I tested various cards with srev < 0x78 + * and they don't wake up after module reload, a second + * module reload is needed to bring the card up again. + * + * Until we figure out what's going on don't enable + * full chip reset on any chip (this is what Legacy HAL + * and Sam's HAL do anyway). Instead Perform a full reset + * on the device (same as initial state after attach) and + * leave it idle (keep MAC/BB on warm reset) */ + ret = ath5k_hw_on_hold(sc->ah); + + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, + "putting device to sleep\n"); } ath5k_txbuf_free(sc, sc->bbuf); diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 86733fdb4774..34e13c700849 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -258,29 +258,35 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, if (!set_chip) goto commit; - /* Preserve sleep duration */ data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL); + + /* If card is down we 'll get 0xffff... so we + * need to clean this up before we write the register + */ if (data & 0xffc00000) data = 0; else - data = data & 0xfffcffff; + /* Preserve sleep duration etc */ + data = data & ~AR5K_SLEEP_CTL_SLE; - ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); + ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE, + AR5K_SLEEP_CTL); udelay(15); - for (i = 50; i > 0; i--) { + for (i = 200; i > 0; i--) { /* Check if the chip did wake up */ if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_SPWR_DN) == 0) break; /* Wait a bit and retry */ - udelay(200); - ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); + udelay(50); + ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE, + AR5K_SLEEP_CTL); } /* Fail if the chip didn't wake up */ - if (i <= 0) + if (i == 0) return -EIO; break; @@ -295,6 +301,64 @@ commit: return 0; } +/* + * Put device on hold + * + * Put MAC and Baseband on warm reset and + * keep that state (don't clean sleep control + * register). After this MAC and Baseband are + * disabled and a full reset is needed to come + * back. This way we save as much power as possible + * without puting the card on full sleep. + */ +int ath5k_hw_on_hold(struct ath5k_hw *ah) +{ + struct pci_dev *pdev = ah->ah_sc->pdev; + u32 bus_flags; + int ret; + + /* Make sure device is awake */ + ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); + if (ret) { + ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); + return ret; + } + + /* + * Put chipset on warm reset... + * + * Note: puting PCI core on warm reset on PCI-E cards + * results card to hang and always return 0xffff... so + * we ingore that flag for PCI-E cards. On PCI cards + * this flag gets cleared after 64 PCI clocks. + */ + bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; + + if (ah->ah_version == AR5K_AR5210) { + ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | + AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | + AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); + mdelay(2); + } else { + ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | + AR5K_RESET_CTL_BASEBAND | bus_flags); + } + + if (ret) { + ATH5K_ERR(ah->ah_sc, "failed to put device on warm reset\n"); + return -EIO; + } + + /* ...wakeup again!*/ + ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); + if (ret) { + ATH5K_ERR(ah->ah_sc, "failed to put device on hold\n"); + return ret; + } + + return ret; +} + /* * Bring up MAC + PHY Chips and program PLL * TODO: Half/Quarter rate support @@ -318,6 +382,50 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) return ret; } + /* + * Put chipset on warm reset... + * + * Note: puting PCI core on warm reset on PCI-E cards + * results card to hang and always return 0xffff... so + * we ingore that flag for PCI-E cards. On PCI cards + * this flag gets cleared after 64 PCI clocks. + */ + bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; + + if (ah->ah_version == AR5K_AR5210) { + ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | + AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | + AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); + mdelay(2); + } else { + ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | + AR5K_RESET_CTL_BASEBAND | bus_flags); + } + + if (ret) { + ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); + return -EIO; + } + + /* ...wakeup again!...*/ + ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); + if (ret) { + ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n"); + return ret; + } + + /* ...clear reset control register and pull device out of + * warm reset */ + if (ath5k_hw_nic_reset(ah, 0)) { + ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); + return -EIO; + } + + /* On initialization skip PLL programming since we don't have + * a channel / mode set yet */ + if (initial) + return 0; + if (ah->ah_version != AR5K_AR5210) { /* * Get channel mode flags @@ -383,39 +491,6 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) AR5K_PHY_TURBO); } - /* reseting PCI on PCI-E cards results card to hang - * and always return 0xffff... so we ingore that flag - * for PCI-E cards */ - bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; - - /* Reset chipset */ - if (ah->ah_version == AR5K_AR5210) { - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | - AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); - mdelay(2); - } else { - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_BASEBAND | bus_flags); - } - if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); - return -EIO; - } - - /* ...wakeup again!*/ - ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); - if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n"); - return ret; - } - - /* ...final warm reset */ - if (ath5k_hw_nic_reset(ah, 0)) { - ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); - return -EIO; - } - if (ah->ah_version != AR5K_AR5210) { /* ...update PLL if needed */ -- cgit v1.2.3 From b55a5de114dcdc03f2f18c3bd98bbabb13ee53ef Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Mon, 10 Aug 2009 03:30:32 +0300 Subject: ath5k: Preserve pcicfg bits during attach * During attach preserve pcicfg bits when enabling pci core sw retry fix. Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/attach.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 238eeb7e166e..65d438b59f64 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -261,7 +261,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) /* Enable pci core retry fix on Hainan (5213A) and later chips */ if (srev >= AR5K_SREV_AR5213A) - ath5k_hw_reg_write(ah, AR5K_PCICFG_RETRY_FIX, AR5K_PCICFG); + AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_RETRY_FIX); /* * Get card capabilities, calibration values etc -- cgit v1.2.3 From 6e220662bf9a2ba284e88a8c8867340c9f6da27e Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Mon, 10 Aug 2009 03:31:31 +0300 Subject: ath5k: Use SWI to trigger calibration * Get rid of calibration timer, instead use a software interrupt to schedule the calibration tasklet. a) We don't need a timer for this, there is no need for accuracy even with round_jiffies i think this is a waste of resources. Also we don't need to run calibration if we are idle (no interrupts). b) When we add ANI support we 'll just extend the poll function and calibration tasklet and handle all periodic phy calibration on one place (much cleaner). c) Having calibration on a tasklet is better since during calibration we can't transmit or receive (antennas are detached to measure noise floor), previously calibration could run in parallel with tx/rx and interfere (packet loss). v2: kill tasklet on stop_hw, stop/wake queues v3: use time_is_before_eq_jiffies to compare timestamp with current time Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 16 +++++++++++++++ drivers/net/wireless/ath/ath5k/base.c | 36 ++++++++++++++++++++++++---------- drivers/net/wireless/ath/ath5k/base.h | 3 ++- drivers/net/wireless/ath/ath5k/phy.c | 23 ++++++++++++++++++++++ 4 files changed, 67 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 1047a6cb1d92..c09402eea7f3 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -919,6 +919,12 @@ enum ath5k_int { AR5K_INT_NOCARD = 0xffffffff }; +/* Software interrupts used for calibration */ +enum ath5k_software_interrupt { + AR5K_SWI_FULL_CALIBRATION = 0x01, + AR5K_SWI_SHORT_CALIBRATION = 0x02, +}; + /* * Power management */ @@ -1123,6 +1129,15 @@ struct ath5k_hw { /* noise floor from last periodic calibration */ s32 ah_noise_floor; + /* Calibration timestamp */ + unsigned long ah_cal_tstamp; + + /* Calibration interval (secs) */ + u8 ah_cal_intval; + + /* Software interrupt mask */ + u8 ah_swi_mask; + /* * Function pointers */ @@ -1276,6 +1291,7 @@ extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *chann /* PHY calibration */ 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 void ath5k_hw_calibration_poll(struct ath5k_hw *ah); /* Spur mitigation */ bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, struct ieee80211_channel *channel); diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 0370cba8356c..acbcfc2a9f71 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -59,7 +59,7 @@ #include "reg.h" #include "debug.h" -static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ +static u8 ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -376,7 +376,7 @@ static int ath5k_stop_hw(struct ath5k_softc *sc); static irqreturn_t ath5k_intr(int irq, void *dev_id); static void ath5k_tasklet_reset(unsigned long data); -static void ath5k_calibrate(unsigned long data); +static void ath5k_tasklet_calibrate(unsigned long data); /* * Module init/exit functions @@ -799,8 +799,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); + tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); - setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc); ret = ath5k_eeprom_read_mac(ah, mac); if (ret) { @@ -2364,7 +2364,7 @@ ath5k_init(struct ath5k_softc *sc) sc->curband = &sc->sbands[sc->curchan->band]; sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | - AR5K_INT_FATAL | AR5K_INT_GLOBAL; + AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_SWI; ret = ath5k_reset(sc, NULL); if (ret) goto done; @@ -2381,8 +2381,8 @@ ath5k_init(struct ath5k_softc *sc) /* Set ack to be sent at low bit-rates */ ath5k_hw_set_ack_bitrate_high(ah, false); - mod_timer(&sc->calib_tim, round_jiffies(jiffies + - msecs_to_jiffies(ath5k_calinterval * 1000))); + /* Set PHY calibration inteval */ + ah->ah_cal_intval = ath5k_calinterval; ret = 0; done: @@ -2475,10 +2475,10 @@ ath5k_stop_hw(struct ath5k_softc *sc) mmiowb(); mutex_unlock(&sc->lock); - del_timer_sync(&sc->calib_tim); tasklet_kill(&sc->rxtq); tasklet_kill(&sc->txtq); tasklet_kill(&sc->restq); + tasklet_kill(&sc->calib); tasklet_kill(&sc->beacontq); ath5k_rfkill_hw_stop(sc->ah); @@ -2534,6 +2534,9 @@ ath5k_intr(int irq, void *dev_id) if (status & AR5K_INT_BMISS) { /* TODO */ } + if (status & AR5K_INT_SWI) { + tasklet_schedule(&sc->calib); + } if (status & AR5K_INT_MIB) { /* * These stats are also used for ANI i think @@ -2550,6 +2553,8 @@ ath5k_intr(int irq, void *dev_id) if (unlikely(!counter)) ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); + ath5k_hw_calibration_poll(ah); + return IRQ_HANDLED; } @@ -2566,11 +2571,19 @@ ath5k_tasklet_reset(unsigned long data) * for temperature/environment changes. */ static void -ath5k_calibrate(unsigned long data) +ath5k_tasklet_calibrate(unsigned long data) { struct ath5k_softc *sc = (void *)data; struct ath5k_hw *ah = sc->ah; + /* Only full calibration for now */ + if (ah->ah_swi_mask != AR5K_SWI_FULL_CALIBRATION) + return; + + /* Stop queues so that calibration + * doesn't interfere with tx */ + ieee80211_stop_queues(sc->hw); + ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", ieee80211_frequency_to_channel(sc->curchan->center_freq), sc->curchan->hw_value); @@ -2588,8 +2601,11 @@ ath5k_calibrate(unsigned long data) ieee80211_frequency_to_channel( sc->curchan->center_freq)); - mod_timer(&sc->calib_tim, round_jiffies(jiffies + - msecs_to_jiffies(ath5k_calinterval * 1000))); + ah->ah_swi_mask = 0; + + /* Wake queues */ + ieee80211_wake_queues(sc->hw); + } diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 778e422946ab..667bd9dc1900 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -177,6 +177,8 @@ struct ath5k_softc { struct ath5k_rfkill rf_kill; + struct tasklet_struct calib; /* calibration tasklet */ + spinlock_t block; /* protects beacon */ struct tasklet_struct beacontq; /* beacon intr tasklet */ struct ath5k_buf *bbuf; /* beacon buffer */ @@ -187,7 +189,6 @@ struct ath5k_softc { unsigned int nexttbtt; /* next beacon time in TU */ struct ath5k_txq *cabq; /* content after beacon */ - struct timer_list calib_tim; /* calibration timer */ int power_level; /* Requested tx power in dbm */ bool assoc; /* assocate state */ bool enable_beacon; /* true if beacons are on */ diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 6afba98f6adb..298fcf015227 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1104,6 +1104,29 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) PHY calibration \*****************/ +void +ath5k_hw_calibration_poll(struct ath5k_hw *ah) +{ + /* Calibration interval in jiffies */ + unsigned long cal_intval; + + cal_intval = msecs_to_jiffies(ah->ah_cal_intval * 1000); + + /* Initialize timestamp if needed */ + if (!ah->ah_cal_tstamp) + ah->ah_cal_tstamp = jiffies; + + /* For now we always do full calibration + * Mark software interrupt mask and fire software + * interrupt (bit gets auto-cleared) */ + if (time_is_before_eq_jiffies(ah->ah_cal_tstamp + cal_intval)) { + ah->ah_cal_tstamp = jiffies; + ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION; + AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); + } + +} + /** * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration * -- cgit v1.2.3 From aeb63cfd4ccc813c204a0d81ad6c5a90c33d8f61 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 12 Aug 2009 09:57:00 -0700 Subject: ath5k: use common ath.ko ath_rxbuf_alloc() Now that its shared we can remove ath5k's own implementation. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 21 +++++++-------------- drivers/net/wireless/ath/ath5k/base.h | 3 ++- 2 files changed, 9 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index acbcfc2a9f71..63c2b5714d2f 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -544,7 +544,7 @@ ath5k_pci_probe(struct pci_dev *pdev, __set_bit(ATH_STAT_INVALID, sc->status); sc->iobase = mem; /* So we can unmap it on detach */ - sc->cachelsz = csz * sizeof(u32); /* convert to bytes */ + sc->common.cachelsz = csz * sizeof(u32); /* convert to bytes */ sc->opmode = NL80211_IFTYPE_STATION; sc->bintval = 1000; mutex_init(&sc->lock); @@ -1151,27 +1151,20 @@ static struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) { struct sk_buff *skb; - unsigned int off; /* * Allocate buffer with headroom_needed space for the * fake physical layer header at the start. */ - skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1); + skb = ath_rxbuf_alloc(&sc->common, + sc->rxbufsize + sc->common.cachelsz - 1, + GFP_ATOMIC); if (!skb) { ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", - sc->rxbufsize + sc->cachelsz - 1); + sc->rxbufsize + sc->common.cachelsz - 1); return NULL; } - /* - * Cache-line-align. This is important (for the - * 5210 at least) as not doing so causes bogus data - * in rx'd frames. - */ - off = ((unsigned long)skb->data) % sc->cachelsz; - if (off != 0) - skb_reserve(skb, sc->cachelsz - off); *skb_addr = pci_map_single(sc->pdev, skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); @@ -1613,10 +1606,10 @@ ath5k_rx_start(struct ath5k_softc *sc) struct ath5k_buf *bf; int ret; - sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->cachelsz); + sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->common.cachelsz); ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", - sc->cachelsz, sc->rxbufsize); + sc->common.cachelsz, sc->rxbufsize); spin_lock_bh(&sc->rxbuflock); sc->rxlink = NULL; diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 667bd9dc1900..25a72a85aaa5 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -50,6 +50,7 @@ #include "ath5k.h" #include "debug.h" +#include "../ath.h" #define ATH_RXBUF 40 /* number of RX buffers */ #define ATH_TXBUF 200 /* number of TX buffers */ @@ -112,6 +113,7 @@ struct ath5k_rfkill { * associated with an instance of a device */ struct ath5k_softc { struct pci_dev *pdev; /* for dma mapping */ + struct ath_common common; void __iomem *iobase; /* address of the device */ struct mutex lock; /* dev-level lock */ struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES]; @@ -134,7 +136,6 @@ struct ath5k_softc { struct ath5k_desc *desc; /* TX/RX descriptors */ dma_addr_t desc_daddr; /* DMA (physical) address */ size_t desc_len; /* size of TX/RX descriptors */ - u16 cachelsz; /* cache line size */ DECLARE_BITMAP(status, 5); #define ATH_STAT_INVALID 0 /* disable hardware accesses */ -- cgit v1.2.3 From 13311b00117ed1bf903cf8870432504631a7ce77 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 12 Aug 2009 09:57:01 -0700 Subject: ath5k: use bit shift operators for cache line size This matches ath9k, providing consistency when reading both drivers. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 63c2b5714d2f..2b3cf39dd4b1 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -471,7 +471,7 @@ ath5k_pci_probe(struct pci_dev *pdev, * DMA to work so force a reasonable value here if it * comes up zero. */ - csz = L1_CACHE_BYTES / sizeof(u32); + csz = L1_CACHE_BYTES >> 2; pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); } /* @@ -544,7 +544,7 @@ ath5k_pci_probe(struct pci_dev *pdev, __set_bit(ATH_STAT_INVALID, sc->status); sc->iobase = mem; /* So we can unmap it on detach */ - sc->common.cachelsz = csz * sizeof(u32); /* convert to bytes */ + sc->common.cachelsz = csz << 2; /* convert to bytes */ sc->opmode = NL80211_IFTYPE_STATION; sc->bintval = 1000; mutex_init(&sc->lock); -- cgit v1.2.3 From 3ac64beecd27400d12cc7afb4108eef26c499f6a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 17 Aug 2009 16:16:53 +0200 Subject: mac80211: allow configure_filter callback to sleep Over time, a whole bunch of drivers have come up with their own scheme to delay the configure_filter operation to a workqueue. To be able to simplify things, allow configure_filter to sleep, and add a new prepare_multicast callback that drivers that need the multicast address list implement. This new callback must be atomic, but most drivers either don't care or just calculate a hash which can be done atomically and then uploaded to the hardware non-atomically. A cursory look suggests that at76c50x-usb, ar9170, mwl8k (which is actually very broken now), rt2x00, wl1251, wl1271 and zd1211 should make use of this new capability. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 64 +++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 25 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 2b3cf39dd4b1..3951b5b13424 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -229,10 +229,12 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, static void ath5k_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); static int ath5k_config(struct ieee80211_hw *hw, u32 changed); +static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, + int mc_count, struct dev_addr_list *mc_list); static void ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *new_flags, - int mc_count, struct dev_mc_list *mclist); + u64 multicast); static int ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -260,6 +262,7 @@ static const struct ieee80211_ops ath5k_hw_ops = { .add_interface = ath5k_add_interface, .remove_interface = ath5k_remove_interface, .config = ath5k_config, + .prepare_multicast = ath5k_prepare_multicast, .configure_filter = ath5k_configure_filter, .set_key = ath5k_set_key, .get_stats = ath5k_get_stats, @@ -2853,6 +2856,37 @@ unlock: return ret; } +static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, + int mc_count, struct dev_addr_list *mclist) +{ + u32 mfilt[2], val; + int i; + u8 pos; + + mfilt[0] = 0; + mfilt[1] = 1; + + for (i = 0; i < mc_count; i++) { + if (!mclist) + break; + /* calculate XOR of eight 6-bit values */ + val = get_unaligned_le32(mclist->dmi_addr + 0); + pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; + val = get_unaligned_le32(mclist->dmi_addr + 3); + pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; + pos &= 0x3f; + mfilt[pos / 32] |= (1 << (pos % 32)); + /* XXX: we might be able to just do this instead, + * but not sure, needs testing, if we do use this we'd + * neet to inform below to not reset the mcast */ + /* ath5k_hw_set_mcast_filterindex(ah, + * mclist->dmi_addr[5]); */ + mclist = mclist->next; + } + + return ((u64)(mfilt[1]) << 32) | mfilt[0]; +} + #define SUPPORTED_FIF_FLAGS \ FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ @@ -2878,16 +2912,14 @@ unlock: static void ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *new_flags, - int mc_count, struct dev_mc_list *mclist) + u64 multicast) { struct ath5k_softc *sc = hw->priv; struct ath5k_hw *ah = sc->ah; - u32 mfilt[2], val, rfilt; - u8 pos; - int i; + u32 mfilt[2], rfilt; - mfilt[0] = 0; - mfilt[1] = 0; + mfilt[0] = multicast; + mfilt[1] = multicast >> 32; /* Only deal with supported flags */ changed_flags &= SUPPORTED_FIF_FLAGS; @@ -2913,24 +2945,6 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, if (*new_flags & FIF_ALLMULTI) { mfilt[0] = ~0; mfilt[1] = ~0; - } else { - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - /* calculate XOR of eight 6-bit values */ - val = get_unaligned_le32(mclist->dmi_addr + 0); - pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; - val = get_unaligned_le32(mclist->dmi_addr + 3); - pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; - pos &= 0x3f; - mfilt[pos / 32] |= (1 << (pos % 32)); - /* XXX: we might be able to just do this instead, - * but not sure, needs testing, if we do use this we'd - * neet to inform below to not reset the mcast */ - /* ath5k_hw_set_mcast_filterindex(ah, - * mclist->dmi_addr[5]); */ - mclist = mclist->next; - } } /* This is the best we can do */ -- cgit v1.2.3 From 608b88cb34b0e70a538ee1fc334cc833ef691836 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 17 Aug 2009 18:07:23 -0700 Subject: ath: move regulatory info into shared common structure This moves the shared regulatory structure into the common structure. We will use this ongoing for common data. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 3 --- drivers/net/wireless/ath/ath5k/base.c | 14 +++++++------- drivers/net/wireless/ath/ath5k/base.h | 13 +++++++++++++ drivers/net/wireless/ath/ath5k/phy.c | 3 ++- 4 files changed, 22 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index c09402eea7f3..862762cea54c 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -27,8 +27,6 @@ #include #include -#include "../regd.h" - /* RX/TX descriptor hw structs * TODO: Driver part should only see sw structs */ #include "desc.h" @@ -1077,7 +1075,6 @@ struct ath5k_hw { int ah_gpio_npins; - struct ath_regulatory ah_regulatory; struct ath5k_capabilities ah_capabilities; struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 3951b5b13424..5056410d788a 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -718,9 +718,9 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct ath5k_softc *sc = hw->priv; - struct ath_regulatory *reg = &sc->ah->ah_regulatory; + struct ath_regulatory *regulatory = &sc->common.regulatory; - return ath_reg_notifier_apply(wiphy, request, reg); + return ath_reg_notifier_apply(wiphy, request, regulatory); } static int @@ -728,6 +728,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) { struct ath5k_softc *sc = hw->priv; struct ath5k_hw *ah = sc->ah; + struct ath_regulatory *regulatory = &sc->common.regulatory; u8 mac[ETH_ALEN] = {}; int ret; @@ -817,9 +818,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) memset(sc->bssidmask, 0xff, ETH_ALEN); ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); - ah->ah_regulatory.current_rd = - ah->ah_capabilities.cap_eeprom.ee_regdomain; - ret = ath_regd_init(&ah->ah_regulatory, hw->wiphy, ath5k_reg_notifier); + regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; + ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier); if (ret) { ATH5K_ERR(sc, "can't initialize regulatory system\n"); goto err_queues; @@ -831,8 +831,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) goto err_queues; } - if (!ath_is_world_regd(&sc->ah->ah_regulatory)) - regulatory_hint(hw->wiphy, sc->ah->ah_regulatory.alpha2); + if (!ath_is_world_regd(regulatory)) + regulatory_hint(hw->wiphy, regulatory->alpha2); ath5k_init_leds(sc); diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 25a72a85aaa5..a28c42f32c9d 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -50,6 +50,8 @@ #include "ath5k.h" #include "debug.h" + +#include "../regd.h" #include "../ath.h" #define ATH_RXBUF 40 /* number of RX buffers */ @@ -200,4 +202,15 @@ struct ath5k_softc { #define ath5k_hw_hasveol(_ah) \ (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) +static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah) +{ + return &ah->ah_sc->common; +} + +static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah) +{ + return &(ath5k_hw_common(ah)->regulatory); + +} + #endif diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 298fcf015227..1a039f2bd732 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -2198,6 +2198,7 @@ static void ath5k_get_max_ctl_power(struct ath5k_hw *ah, struct ieee80211_channel *channel) { + struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; struct ath5k_edge_power *rep = ee->ee_ctl_pwr; u8 *ctl_val = ee->ee_ctl; @@ -2208,7 +2209,7 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah, u8 ctl_idx = 0xFF; u32 target = channel->center_freq; - ctl_mode = ath_regd_get_band_ctl(&ah->ah_regulatory, channel->band); + ctl_mode = ath_regd_get_band_ctl(regulatory, channel->band); switch (channel->hw_value & CHANNEL_MODES) { case CHANNEL_A: -- cgit v1.2.3 From 56d1de0a21db28e41741cfa0a66e18bc8d920554 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 24 Aug 2009 23:00:30 -0400 Subject: ath5k: clean up filter flags setting The maze of if() statements in configure_filter is confusing. Reorganizing it as a switch statement makes it more apparent what is going on and reveals several suspicious settings. This has no functional changes, though it does remove some redundant flags that are set earlier. Also now that we can sleep, protect sc->filter_flags with the sc lock. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 39 +++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 5056410d788a..c4adf9846410 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2918,6 +2918,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, struct ath5k_hw *ah = sc->ah; u32 mfilt[2], rfilt; + mutex_lock(&sc->lock); + mfilt[0] = multicast; mfilt[1] = multicast >> 32; @@ -2968,22 +2970,25 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */ - if (sc->opmode == NL80211_IFTYPE_MONITOR) - rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON | - AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM; - if (sc->opmode != NL80211_IFTYPE_STATION) - rfilt |= AR5K_RX_FILTER_PROBEREQ; - if (sc->opmode != NL80211_IFTYPE_AP && - sc->opmode != NL80211_IFTYPE_MESH_POINT && - test_bit(ATH_STAT_PROMISC, sc->status)) - rfilt |= AR5K_RX_FILTER_PROM; - if ((sc->opmode == NL80211_IFTYPE_STATION && sc->assoc) || - sc->opmode == NL80211_IFTYPE_ADHOC || - sc->opmode == NL80211_IFTYPE_AP) - rfilt |= AR5K_RX_FILTER_BEACON; - if (sc->opmode == NL80211_IFTYPE_MESH_POINT) - rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON | - AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM; + switch (sc->opmode) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_MONITOR: + rfilt |= AR5K_RX_FILTER_CONTROL | + AR5K_RX_FILTER_BEACON | + AR5K_RX_FILTER_PROBEREQ | + AR5K_RX_FILTER_PROM; + break; + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_ADHOC: + rfilt |= AR5K_RX_FILTER_PROBEREQ | + AR5K_RX_FILTER_BEACON; + break; + case NL80211_IFTYPE_STATION: + if (sc->assoc) + rfilt |= AR5K_RX_FILTER_BEACON; + default: + break; + } /* Set filters */ ath5k_hw_set_rx_filter(ah, rfilt); @@ -2993,6 +2998,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, /* Set the cached hw filter flags, this will alter actually * be set in HW */ sc->filter_flags = rfilt; + + mutex_unlock(&sc->lock); } static int -- cgit v1.2.3 From 09c9bae26b0d3c9472cb6ae45010460a2cee8b8d Mon Sep 17 00:00:00 2001 From: Marcos Chaparro Date: Mon, 24 Aug 2009 23:00:31 -0400 Subject: ath5k: add led pin configuration for compaq c700 laptop With this patch, a compaq c700 can turn on the wifi led. The array of compatible devices now includes the hardware present in this computer, as well as the led pin and polarity. Signed-off-by: Marcos Chaparro Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/led.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index 876725f08b6c..b767c3b67b24 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -69,6 +69,8 @@ static const struct pci_device_id ath5k_led_devices[] = { { ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) }, /* IBM ThinkPad AR5BXB6 (legovini@spiro.fisica.unipd.it) */ { ATH_SDEVICE(PCI_VENDOR_ID_IBM, 0x058a), ATH_LED(1, 0) }, + /* HP Compaq C700 (nitrousnrg@gmail.com) */ + { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) }, /* IBM-specific AR5212 (all others) */ { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, { } -- cgit v1.2.3 From 1c5256bb168faca5ce32a9c9511c8389f9fed31c Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 24 Aug 2009 23:00:32 -0400 Subject: ath5k: use the skb->cb directly for RX status Save a memcpy by just storing updates directly in the skb control block. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 41 ++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index c4adf9846410..10bf01547068 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1741,7 +1741,7 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, static void ath5k_tasklet_rx(unsigned long data) { - struct ieee80211_rx_status rxs = {}; + struct ieee80211_rx_status *rxs; struct ath5k_rx_status rs = {}; struct sk_buff *skb, *next_skb; dma_addr_t next_skb_addr; @@ -1751,6 +1751,7 @@ ath5k_tasklet_rx(unsigned long data) int ret; int hdrlen; int padsize; + int rx_flag; spin_lock(&sc->rxbuflock); if (list_empty(&sc->rxbuf)) { @@ -1758,7 +1759,7 @@ ath5k_tasklet_rx(unsigned long data) goto unlock; } do { - rxs.flag = 0; + rx_flag = 0; bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); BUG_ON(bf->skb == NULL); @@ -1802,7 +1803,7 @@ ath5k_tasklet_rx(unsigned long data) goto accept; } if (rs.rs_status & AR5K_RXERR_MIC) { - rxs.flag |= RX_FLAG_MMIC_ERROR; + rx_flag |= RX_FLAG_MMIC_ERROR; goto accept; } @@ -1840,6 +1841,7 @@ accept: memmove(skb->data + padsize, skb->data, hdrlen); skb_pull(skb, padsize); } + rxs = IEEE80211_SKB_RXCB(skb); /* * always extend the mac timestamp, since this information is @@ -1861,41 +1863,40 @@ accept: * impossible to comply to that. This affects IBSS merge only * right now, so it's not too bad... */ - rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp); - rxs.flag |= RX_FLAG_TSFT; + rxs->mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp); + rxs->flag = rx_flag | RX_FLAG_TSFT; - rxs.freq = sc->curchan->center_freq; - rxs.band = sc->curband->band; + rxs->freq = sc->curchan->center_freq; + rxs->band = sc->curband->band; - rxs.noise = sc->ah->ah_noise_floor; - rxs.signal = rxs.noise + rs.rs_rssi; + rxs->noise = sc->ah->ah_noise_floor; + rxs->signal = rxs->noise + rs.rs_rssi; /* An rssi of 35 indicates you should be able use * 54 Mbps reliably. A more elaborate scheme can be used * here but it requires a map of SNR/throughput for each * possible mode used */ - rxs.qual = rs.rs_rssi * 100 / 35; + rxs->qual = rs.rs_rssi * 100 / 35; /* rssi can be more than 35 though, anything above that * should be considered at 100% */ - if (rxs.qual > 100) - rxs.qual = 100; + if (rxs->qual > 100) + rxs->qual = 100; - rxs.antenna = rs.rs_antenna; - rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); - rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); + rxs->antenna = rs.rs_antenna; + rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); + rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); - if (rxs.rate_idx >= 0 && rs.rs_rate == - sc->curband->bitrates[rxs.rate_idx].hw_value_short) - rxs.flag |= RX_FLAG_SHORTPRE; + if (rxs->rate_idx >= 0 && rs.rs_rate == + sc->curband->bitrates[rxs->rate_idx].hw_value_short) + rxs->flag |= RX_FLAG_SHORTPRE; ath5k_debug_dump_skb(sc, skb, "RX ", 0); /* check beacons in IBSS mode */ if (sc->opmode == NL80211_IFTYPE_ADHOC) - ath5k_check_ibss_tsf(sc, skb, &rxs); + ath5k_check_ibss_tsf(sc, skb, rxs); - memcpy(IEEE80211_SKB_RXCB(skb), &rxs, sizeof(rxs)); ieee80211_rx(sc->hw, skb); bf->skb = next_skb; -- cgit v1.2.3 From 1c81874078dc96b8158ce7b0dab54afe43c8d03e Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 24 Aug 2009 23:00:33 -0400 Subject: ath5k: add hardware CCMP encyption support Recent ath5k hardware is capable of doing CCMP acceleration. Enable it for the cards that support it. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 1 + drivers/net/wireless/ath/ath5k/attach.c | 10 ++++++++++ drivers/net/wireless/ath/ath5k/base.c | 3 +++ 3 files changed, 14 insertions(+) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 862762cea54c..cdc79cd134c2 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1037,6 +1037,7 @@ struct ath5k_hw { bool ah_turbo; bool ah_calibration; bool ah_single_chip; + bool ah_aes_support; bool ah_combined_mic; enum ath5k_version ah_version; diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 65d438b59f64..109ab7ba3041 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -106,6 +106,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) { struct ath5k_hw *ah; struct pci_dev *pdev = sc->pdev; + struct ath5k_eeprom_info *ee; int ret; u32 srev; @@ -315,6 +316,15 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) goto err_free; } + /* Crypto settings */ + ee = &ah->ah_capabilities.cap_eeprom; + ah->ah_aes_support = + (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && + !AR5K_EEPROM_AES_DIS(ee->ee_misc5) && + (ah->ah_mac_version > (AR5K_SREV_AR5212 >> 4) || + (ah->ah_mac_version == (AR5K_SREV_AR5212 >> 4) && + ah->ah_mac_revision >= (AR5K_SREV_AR5211 >> 4)))); + if (srev >= AR5K_SREV_AR2414) { ah->ah_combined_mic = true; AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE, diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 10bf01547068..94d46fd94ff6 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -3022,6 +3022,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, case ALG_TKIP: break; case ALG_CCMP: + if (sc->ah->ah_aes_support) + break; + return -EOPNOTSUPP; default: WARN_ON(1); -- cgit v1.2.3 From ca5efbe243dde7d269b6bbae7feaa5e4740db36e Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Thu, 27 Aug 2009 15:17:15 -0400 Subject: ath5k: clarify srev comparison for CCMP check As Pavel Roskin noted, the check for mac version as copied from legacy_hal made no sense. This replaces it with the equivalent and makes up a suitable #define for the mac version legacy_hal checked. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 1 + drivers/net/wireless/ath/ath5k/attach.c | 7 ++----- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index cdc79cd134c2..1275ba0990b3 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -306,6 +306,7 @@ struct ath5k_srev_name { #define AR5K_SREV_AR5311B 0x30 /* Spirit */ #define AR5K_SREV_AR5211 0x40 /* Oahu */ #define AR5K_SREV_AR5212 0x50 /* Venice */ +#define AR5K_SREV_AR5212_V4 0x54 /* ??? */ #define AR5K_SREV_AR5213 0x55 /* ??? */ #define AR5K_SREV_AR5213A 0x59 /* Hainan */ #define AR5K_SREV_AR2413 0x78 /* Griffin lite */ diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 109ab7ba3041..4819f39da704 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -318,12 +318,9 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) /* Crypto settings */ ee = &ah->ah_capabilities.cap_eeprom; - ah->ah_aes_support = + ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 && (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && - !AR5K_EEPROM_AES_DIS(ee->ee_misc5) && - (ah->ah_mac_version > (AR5K_SREV_AR5212 >> 4) || - (ah->ah_mac_version == (AR5K_SREV_AR5212 >> 4) && - ah->ah_mac_revision >= (AR5K_SREV_AR5211 >> 4)))); + !AR5K_EEPROM_AES_DIS(ee->ee_misc5)); if (srev >= AR5K_SREV_AR2414) { ah->ah_combined_mic = true; -- cgit v1.2.3 From 3b3ee43da43aca1cbf4c3651379b2b1492e49dd6 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Wed, 26 Aug 2009 22:30:00 -0400 Subject: ath5k: fix uninitialized value use in ath5k_eeprom_read_turbo_modes() The `val' variable in ath5k_eeprom_read_turbo_modes() is used uninitialized. gcc 4.4.1 with -fno-inline-functions-called-once reports it: eeprom.c: In function 'ath5k_eeprom_read_turbo_modes': eeprom.c:441: warning: 'val' may be used uninitialized in this function Comparing the code to the Atheros HAL, it's clear that the split between ath5k_eeprom_read_modes() and ath5k_eeprom_read_turbo_modes() was incorrect. The Atheros HAL reads both turbo and non-turbo data from EEPROM in one function. Some turbo mode parameters are derived from the same EEPROM values as non-turbo parameters, just from different bits. Merge ath5k_eeprom_read_turbo_modes() into ath5k_eeprom_read_modes() to fix the warning. The actual values and offsets have been cross-checked against Atheros HAL. Signed-off-by: Pavel Roskin Acked-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/eeprom.c | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 8af477dd6fc7..644962adda97 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -414,27 +414,11 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, break; } -done: - /* return new offset */ - *offset = o; - - return 0; -} - -/* - * Read turbo mode information on newer EEPROM versions - */ -static int -ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah, - u32 *offset, unsigned int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 o = *offset; - u16 val; - int ret; - + /* + * Read turbo mode information on newer EEPROM versions + */ if (ee->ee_version < AR5K_EEPROM_VERSION_5_0) - return 0; + goto done; switch (mode){ case AR5K_EEPROM_MODE_11A: @@ -468,6 +452,7 @@ ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah, break; } +done: /* return new offset */ *offset = o; @@ -504,10 +489,6 @@ ath5k_eeprom_init_modes(struct ath5k_hw *ah) ret = ath5k_eeprom_read_modes(ah, &offset, mode); if (ret) return ret; - - ret = ath5k_eeprom_read_turbo_modes(ah, &offset, mode); - if (ret) - return ret; } /* override for older eeprom versions for better performance */ -- cgit v1.2.3 From 97a81f5c5033cb02ae56dd80ff9c38866c777bd8 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Wed, 26 Aug 2009 22:30:09 -0400 Subject: ath5k: don't use PCI ID to find the chip revision AR5K_SREV is available even if the chip has been put to sleep. Relying on the chip register allows binding non-standard PCI IDs by echo VENDOR_ID PRODUCT_ID >/sys/bus/pci/drivers/ath5k/new_id without having to specify the driver data as well. Signed-off-by: Pavel Roskin Acked-by: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 2 +- drivers/net/wireless/ath/ath5k/attach.c | 14 +++++++----- drivers/net/wireless/ath/ath5k/base.c | 38 ++++++++++++++++----------------- 3 files changed, 29 insertions(+), 25 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 1275ba0990b3..6cd5efcec417 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1160,7 +1160,7 @@ struct ath5k_hw { */ /* Attach/Detach Functions */ -extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version); +extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc); extern void ath5k_hw_detach(struct ath5k_hw *ah); /* LED functions */ diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 4819f39da704..71a1bd254517 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -95,14 +95,13 @@ static int ath5k_hw_post(struct ath5k_hw *ah) * ath5k_hw_attach - Check if hw is supported and init the needed structs * * @sc: The &struct ath5k_softc we got from the driver's attach function - * @mac_version: The mac version id (check out ath5k.h) based on pci id * * Check if the device is supported, perform a POST and initialize the needed * structs. Returns -ENOMEM if we don't have memory for the needed structs, * -ENODEV if the device is not supported or prints an error msg if something * else went wrong. */ -struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) +struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) { struct ath5k_hw *ah; struct pci_dev *pdev = sc->pdev; @@ -136,9 +135,15 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ah->ah_software_retry = false; /* - * Set the mac version based on the pci id + * Find the mac version */ - ah->ah_version = mac_version; + srev = ath5k_hw_reg_read(ah, AR5K_SREV); + if (srev < AR5K_SREV_AR5311) + ah->ah_version = AR5K_AR5210; + else if (srev < AR5K_SREV_AR5212) + ah->ah_version = AR5K_AR5211; + else + ah->ah_version = AR5K_AR5212; /*Fill the ath5k_hw struct with the needed functions*/ ret = ath5k_hw_init_desc_functions(ah); @@ -151,7 +156,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) goto err_free; /* Get MAC, PHY and RADIO revisions */ - srev = ath5k_hw_reg_read(ah, AR5K_SREV); 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); diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 94d46fd94ff6..9c6ab5378f6e 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -84,24 +84,24 @@ MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); /* Known PCI ids */ static const struct pci_device_id ath5k_pci_id_table[] = { - { PCI_VDEVICE(ATHEROS, 0x0207), .driver_data = AR5K_AR5210 }, /* 5210 early */ - { PCI_VDEVICE(ATHEROS, 0x0007), .driver_data = AR5K_AR5210 }, /* 5210 */ - { PCI_VDEVICE(ATHEROS, 0x0011), .driver_data = AR5K_AR5211 }, /* 5311 - this is on AHB bus !*/ - { PCI_VDEVICE(ATHEROS, 0x0012), .driver_data = AR5K_AR5211 }, /* 5211 */ - { PCI_VDEVICE(ATHEROS, 0x0013), .driver_data = AR5K_AR5212 }, /* 5212 */ - { PCI_VDEVICE(3COM_2, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 5212 */ - { PCI_VDEVICE(3COM, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 3CRDAG675 5212 */ - { PCI_VDEVICE(ATHEROS, 0x1014), .driver_data = AR5K_AR5212 }, /* IBM minipci 5212 */ - { PCI_VDEVICE(ATHEROS, 0x0014), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0015), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0016), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0017), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0018), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0019), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */ - { PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */ - { PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* PCI-E cards */ - { PCI_VDEVICE(ATHEROS, 0x001d), .driver_data = AR5K_AR5212 }, /* 2417 Nala */ + { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ + { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ + { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ + { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */ + { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */ + { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */ + { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */ + { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */ + { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */ + { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ + { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ + { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ { 0 } }; MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); @@ -566,7 +566,7 @@ ath5k_pci_probe(struct pci_dev *pdev, } /* Initialize device */ - sc->ah = ath5k_hw_attach(sc, id->driver_data); + sc->ah = ath5k_hw_attach(sc); if (IS_ERR(sc->ah)) { ret = PTR_ERR(sc->ah); goto err_irq; -- cgit v1.2.3