diff options
-rw-r--r-- | drivers/net/wireless/ath/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/Kconfig | 21 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/Makefile | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/common.c | 421 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/common.h | 17 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hif_usb.c | 993 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hif_usb.h | 105 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc.h | 441 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 260 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_init.c | 713 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 1626 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 604 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_hst.c | 463 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_hst.h | 246 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.h | 26 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/wmi.c | 319 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/wmi.h | 126 | ||||
-rw-r--r-- | drivers/net/wireless/ath/debug.h | 1 |
18 files changed, 1 insertions, 6393 deletions
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 0a75be027afa..4e7a7fd695c8 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig @@ -3,7 +3,7 @@ menuconfig ATH_COMMON depends on CFG80211 ---help--- This will enable the support for the Atheros wireless drivers. - ath5k, ath9k, ath9k_htc and ar9170 drivers share some common code, this option + ath5k, ath9k and ar9170 drivers share some common code, this option enables the common ath.ko module which shares common helpers. For more information and documentation on this module you can visit: diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 35f23bdc442f..5774cea23a3b 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -32,24 +32,3 @@ config ATH9K_DEBUGFS Also required for changing debug message flags at run time. -config ATH9K_HTC - tristate "Atheros HTC based wireless cards support" - depends on USB && MAC80211 - select ATH9K_HW - select MAC80211_LEDS - select LEDS_CLASS - select NEW_LEDS - select ATH9K_COMMON - ---help--- - Support for Atheros HTC based cards. - Chipsets supported: AR9271 - - For more information: http://wireless.kernel.org/en/users/Drivers/ath9k_htc - - The built module will be ath9k_htc. - -config ATH9K_HTC_DEBUGFS - bool "Atheros ath9k_htc debugging" - depends on ATH9K_HTC && DEBUG_FS - ---help--- - Say Y, if you need access to ath9k_htc's statistics. diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 97133beda269..6b50d5eb9ec3 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -28,13 +28,3 @@ obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o ath9k_common-y:= common.o - -ath9k_htc-y += htc_hst.o \ - hif_usb.o \ - wmi.o \ - htc_drv_txrx.o \ - htc_drv_main.o \ - htc_drv_beacon.o \ - htc_drv_init.o - -obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 7902d287f671..4d775ae141db 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -286,427 +286,6 @@ int ath9k_cmn_padpos(__le16 frame_control) } EXPORT_SYMBOL(ath9k_cmn_padpos); -int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - - if (tx_info->control.hw_key) { - if (tx_info->control.hw_key->alg == ALG_WEP) - return ATH9K_KEY_TYPE_WEP; - else if (tx_info->control.hw_key->alg == ALG_TKIP) - return ATH9K_KEY_TYPE_TKIP; - else if (tx_info->control.hw_key->alg == ALG_CCMP) - return ATH9K_KEY_TYPE_AES; - } - - return ATH9K_KEY_TYPE_CLEAR; -} -EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); - -/* - * Calculate the RX filter to be set in the HW. - */ -u32 ath9k_cmn_calcrxfilter(struct ieee80211_hw *hw, struct ath_hw *ah, - unsigned int rxfilter) -{ -#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) - - u32 rfilt; - - rfilt = (ath9k_hw_getrxfilter(ah) & RX_FILTER_PRESERVE) - | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST - | ATH9K_RX_FILTER_MCAST; - - /* If not a STA, enable processing of Probe Requests */ - if (ah->opmode != NL80211_IFTYPE_STATION) - rfilt |= ATH9K_RX_FILTER_PROBEREQ; - - /* - * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station - * mode interface or when in monitor mode. AP mode does not need this - * since it receives all in-BSS frames anyway. - */ - if (((ah->opmode != NL80211_IFTYPE_AP) && - (rxfilter & FIF_PROMISC_IN_BSS)) || - (ah->opmode == NL80211_IFTYPE_MONITOR)) - rfilt |= ATH9K_RX_FILTER_PROM; - - if (rxfilter & FIF_CONTROL) - rfilt |= ATH9K_RX_FILTER_CONTROL; - - if ((ah->opmode == NL80211_IFTYPE_STATION) && - !(rxfilter & FIF_BCN_PRBRESP_PROMISC)) - rfilt |= ATH9K_RX_FILTER_MYBEACON; - else - rfilt |= ATH9K_RX_FILTER_BEACON; - - if ((AR_SREV_9280_10_OR_LATER(ah) || - AR_SREV_9285_10_OR_LATER(ah)) && - (ah->opmode == NL80211_IFTYPE_AP) && - (rxfilter & FIF_PSPOLL)) - rfilt |= ATH9K_RX_FILTER_PSPOLL; - - if (conf_is_ht(&hw->conf)) - rfilt |= ATH9K_RX_FILTER_COMP_BAR; - - return rfilt; - -#undef RX_FILTER_PRESERVE -} -EXPORT_SYMBOL(ath9k_cmn_calcrxfilter); - -/* - * Recv initialization for opmode change. - */ -void ath9k_cmn_opmode_init(struct ieee80211_hw *hw, struct ath_hw *ah, - unsigned int rxfilter) -{ - struct ath_common *common = ath9k_hw_common(ah); - - u32 rfilt, mfilt[2]; - - /* configure rx filter */ - rfilt = ath9k_cmn_calcrxfilter(hw, ah, rxfilter); - ath9k_hw_setrxfilter(ah, rfilt); - - /* configure bssid mask */ - if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) - ath_hw_setbssidmask(common); - - /* configure operational mode */ - ath9k_hw_setopmode(ah); - - /* Handle any link-level address change. */ - ath9k_hw_setmac(ah, common->macaddr); - - /* calculate and install multicast filter */ - mfilt[0] = mfilt[1] = ~0; - ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); -} -EXPORT_SYMBOL(ath9k_cmn_opmode_init); - -static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type) -{ - u32 chanmode = 0; - - switch (chan->band) { - case IEEE80211_BAND_2GHZ: - switch (channel_type) { - case NL80211_CHAN_NO_HT: - case NL80211_CHAN_HT20: - chanmode = CHANNEL_G_HT20; - break; - case NL80211_CHAN_HT40PLUS: - chanmode = CHANNEL_G_HT40PLUS; - break; - case NL80211_CHAN_HT40MINUS: - chanmode = CHANNEL_G_HT40MINUS; - break; - } - break; - case IEEE80211_BAND_5GHZ: - switch (channel_type) { - case NL80211_CHAN_NO_HT: - case NL80211_CHAN_HT20: - chanmode = CHANNEL_A_HT20; - break; - case NL80211_CHAN_HT40PLUS: - chanmode = CHANNEL_A_HT40PLUS; - break; - case NL80211_CHAN_HT40MINUS: - chanmode = CHANNEL_A_HT40MINUS; - break; - } - break; - default: - break; - } - - return chanmode; -} - -/* - * Update internal channel flags. - */ -void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, - struct ath9k_channel *ichan) -{ - struct ieee80211_channel *chan = hw->conf.channel; - struct ieee80211_conf *conf = &hw->conf; - - ichan->channel = chan->center_freq; - ichan->chan = chan; - - if (chan->band == IEEE80211_BAND_2GHZ) { - ichan->chanmode = CHANNEL_G; - ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G; - } else { - ichan->chanmode = CHANNEL_A; - ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; - } - - if (conf_is_ht(conf)) - ichan->chanmode = ath9k_get_extchanmode(chan, - conf->channel_type); -} -EXPORT_SYMBOL(ath9k_cmn_update_ichannel); - -/* - * Get the internal channel reference. - */ -struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, - struct ath_hw *ah) -{ - struct ieee80211_channel *curchan = hw->conf.channel; - struct ath9k_channel *channel; - u8 chan_idx; - - chan_idx = curchan->hw_value; - channel = &ah->channels[chan_idx]; - ath9k_cmn_update_ichannel(hw, channel); - - return channel; -} -EXPORT_SYMBOL(ath9k_cmn_get_curchannel); - -static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key, - struct ath9k_keyval *hk, const u8 *addr, - bool authenticator) -{ - struct ath_hw *ah = common->ah; - const u8 *key_rxmic; - const u8 *key_txmic; - - key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; - key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; - - if (addr == NULL) { - /* - * Group key installation - only two key cache entries are used - * regardless of splitmic capability since group key is only - * used either for TX or RX. - */ - if (authenticator) { - memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); - memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); - } else { - memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); - memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); - } - return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); - } - if (!common->splitmic) { - /* TX and RX keys share the same key cache entry. */ - memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); - memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); - return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); - } - - /* Separate key cache entries for TX and RX */ - - /* TX key goes at first index, RX key at +32. */ - memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); - if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) { - /* TX MIC entry failed. No need to proceed further */ - ath_print(common, ATH_DBG_FATAL, - "Setting TX MIC Key Failed\n"); - return 0; - } - - memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); - /* XXX delete tx key on failure? */ - return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr); -} - -static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) -{ - int i; - - for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { - if (test_bit(i, common->keymap) || - test_bit(i + 64, common->keymap)) - continue; /* At least one part of TKIP key allocated */ - if (common->splitmic && - (test_bit(i + 32, common->keymap) || - test_bit(i + 64 + 32, common->keymap))) - continue; /* At least one part of TKIP key allocated */ - - /* Found a free slot for a TKIP key */ - return i; - } - return -1; -} - -static int ath_reserve_key_cache_slot(struct ath_common *common) -{ - int i; - - /* First, try to find slots that would not be available for TKIP. */ - if (common->splitmic) { - for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { - if (!test_bit(i, common->keymap) && - (test_bit(i + 32, common->keymap) || - test_bit(i + 64, common->keymap) || - test_bit(i + 64 + 32, common->keymap))) - return i; - if (!test_bit(i + 32, common->keymap) && - (test_bit(i, common->keymap) || - test_bit(i + 64, common->keymap) || - test_bit(i + 64 + 32, common->keymap))) - return i + 32; - if (!test_bit(i + 64, common->keymap) && - (test_bit(i , common->keymap) || - test_bit(i + 32, common->keymap) || - test_bit(i + 64 + 32, common->keymap))) - return i + 64; - if (!test_bit(i + 64 + 32, common->keymap) && - (test_bit(i, common->keymap) || - test_bit(i + 32, common->keymap) || - test_bit(i + 64, common->keymap))) - return i + 64 + 32; - } - } else { - for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { - if (!test_bit(i, common->keymap) && - test_bit(i + 64, common->keymap)) - return i; - if (test_bit(i, common->keymap) && - !test_bit(i + 64, common->keymap)) - return i + 64; - } - } - - /* No partially used TKIP slots, pick any available slot */ - for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) { - /* Do not allow slots that could be needed for TKIP group keys - * to be used. This limitation could be removed if we know that - * TKIP will not be used. */ - if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) - continue; - if (common->splitmic) { - if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) - continue; - if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) - continue; - } - - if (!test_bit(i, common->keymap)) - return i; /* Found a free slot for a key */ - } - - /* No free slot found */ - return -1; -} - -/* - * Configure encryption in the HW. - */ -int ath9k_cmn_key_config(struct ath_common *common, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct ath_hw *ah = common->ah; - struct ath9k_keyval hk; - const u8 *mac = NULL; - int ret = 0; - int idx; - - memset(&hk, 0, sizeof(hk)); - - switch (key->alg) { - case ALG_WEP: - hk.kv_type = ATH9K_CIPHER_WEP; - break; - case ALG_TKIP: - hk.kv_type = ATH9K_CIPHER_TKIP; - break; - case ALG_CCMP: - hk.kv_type = ATH9K_CIPHER_AES_CCM; - break; - default: - return -EOPNOTSUPP; - } - - hk.kv_len = key->keylen; - memcpy(hk.kv_val, key->key, key->keylen); - - if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { - /* For now, use the default keys for broadcast keys. This may - * need to change with virtual interfaces. */ - idx = key->keyidx; - } else if (key->keyidx) { - if (WARN_ON(!sta)) - return -EOPNOTSUPP; - mac = sta->addr; - - if (vif->type != NL80211_IFTYPE_AP) { - /* Only keyidx 0 should be used with unicast key, but - * allow this for client mode for now. */ - idx = key->keyidx; - } else - return -EIO; - } else { - if (WARN_ON(!sta)) - return -EOPNOTSUPP; - mac = sta->addr; - - if (key->alg == ALG_TKIP) - idx = ath_reserve_key_cache_slot_tkip(common); - else - idx = ath_reserve_key_cache_slot(common); - if (idx < 0) - return -ENOSPC; /* no free key cache entries */ - } - - if (key->alg == ALG_TKIP) - ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, - vif->type == NL80211_IFTYPE_AP); - else - ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac); - - if (!ret) - return -EIO; - - set_bit(idx, common->keymap); - if (key->alg == ALG_TKIP) { - set_bit(idx + 64, common->keymap); - if (common->splitmic) { - set_bit(idx + 32, common->keymap); - set_bit(idx + 64 + 32, common->keymap); - } - } - - return idx; -} -EXPORT_SYMBOL(ath9k_cmn_key_config); - -/* - * Delete Key. - */ -void ath9k_cmn_key_delete(struct ath_common *common, - struct ieee80211_key_conf *key) -{ - struct ath_hw *ah = common->ah; - - ath9k_hw_keyreset(ah, key->hw_key_idx); - if (key->hw_key_idx < IEEE80211_WEP_NKID) - return; - - clear_bit(key->hw_key_idx, common->keymap); - if (key->alg != ALG_TKIP) - return; - - clear_bit(key->hw_key_idx + 64, common->keymap); - if (common->splitmic) { - ath9k_hw_keyreset(ah, key->hw_key_idx + 32); - clear_bit(key->hw_key_idx + 32, common->keymap); - clear_bit(key->hw_key_idx + 64 + 32, common->keymap); - } -} -EXPORT_SYMBOL(ath9k_cmn_key_delete); - static int __init ath9k_cmn_init(void) { return 0; diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index bbcc57f6eba3..042999c2fe9c 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -23,8 +23,6 @@ /* Common header for Atheros 802.11n base driver cores */ -#define IEEE80211_WEP_NKID 4 - #define WME_NUM_TID 16 #define WME_BA_BMP_SIZE 64 #define WME_MAX_BA WME_BA_BMP_SIZE @@ -127,18 +125,3 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, bool decrypt_error); int ath9k_cmn_padpos(__le16 frame_control); -int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); -u32 ath9k_cmn_calcrxfilter(struct ieee80211_hw *hw, struct ath_hw *ah, - unsigned int rxfilter); -void ath9k_cmn_opmode_init(struct ieee80211_hw *hw, struct ath_hw *ah, - unsigned int rxfilter); -void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, - struct ath9k_channel *ichan); -struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, - struct ath_hw *ah); -int ath9k_cmn_key_config(struct ath_common *common, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key); -void ath9k_cmn_key_delete(struct ath_common *common, - struct ieee80211_key_conf *key); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c deleted file mode 100644 index fc4f6e8c9ef3..000000000000 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ /dev/null @@ -1,993 +0,0 @@ -/* - * Copyright (c) 2010 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "htc.h" - -#define ATH9K_FW_USB_DEV(devid, fw) \ - { USB_DEVICE(0x0cf3, devid), .driver_info = (unsigned long) fw } - -static struct usb_device_id ath9k_hif_usb_ids[] = { - ATH9K_FW_USB_DEV(0x9271, "ar9271.fw"), - { }, -}; - -MODULE_DEVICE_TABLE(usb, ath9k_hif_usb_ids); - -static int __hif_usb_tx(struct hif_device_usb *hif_dev); - -static void hif_usb_regout_cb(struct urb *urb) -{ - struct cmd_buf *cmd = (struct cmd_buf *)urb->context; - struct hif_device_usb *hif_dev = cmd->hif_dev; - - if (!hif_dev) { - usb_free_urb(urb); - if (cmd) { - if (cmd->skb) - dev_kfree_skb_any(cmd->skb); - kfree(cmd); - } - return; - } - - switch (urb->status) { - case 0: - break; - case -ENOENT: - case -ECONNRESET: - break; - case -ENODEV: - case -ESHUTDOWN: - return; - default: - break; - } - - if (cmd) { - ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, - cmd->skb, 1); - kfree(cmd); - usb_free_urb(urb); - } -} - -static int hif_usb_send_regout(struct hif_device_usb *hif_dev, - struct sk_buff *skb) -{ - struct urb *urb; - struct cmd_buf *cmd; - int ret = 0; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (urb == NULL) - return -ENOMEM; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) { - usb_free_urb(urb); - return -ENOMEM; - } - - cmd->skb = skb; - cmd->hif_dev = hif_dev; - - usb_fill_int_urb(urb, hif_dev->udev, - usb_sndintpipe(hif_dev->udev, USB_REG_OUT_PIPE), - skb->data, skb->len, - hif_usb_regout_cb, cmd, 1); - - ret = usb_submit_urb(urb, GFP_KERNEL); - if (ret) { - usb_free_urb(urb); - kfree(cmd); - } - - return ret; -} - -static void hif_usb_tx_cb(struct urb *urb) -{ - struct tx_buf *tx_buf = (struct tx_buf *) urb->context; - struct hif_device_usb *hif_dev = tx_buf->hif_dev; - struct sk_buff *skb; - bool drop, flush; - - if (!hif_dev) - return; - - switch (urb->status) { - case 0: - break; - case -ENOENT: - case -ECONNRESET: - break; - case -ENODEV: - case -ESHUTDOWN: - return; - default: - break; - } - - if (tx_buf) { - spin_lock(&hif_dev->tx.tx_lock); - drop = !!(hif_dev->tx.flags & HIF_USB_TX_STOP); - flush = !!(hif_dev->tx.flags & HIF_USB_TX_FLUSH); - spin_unlock(&hif_dev->tx.tx_lock); - - while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) { - if (!drop && !flush) { - ath9k_htc_txcompletion_cb(hif_dev->htc_handle, - skb, 1); - TX_STAT_INC(skb_completed); - } else { - dev_kfree_skb_any(skb); - } - } - - if (flush) - return; - - tx_buf->len = tx_buf->offset = 0; - __skb_queue_head_init(&tx_buf->skb_queue); - - spin_lock(&hif_dev->tx.tx_lock); - list_del(&tx_buf->list); - list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf); - hif_dev->tx.tx_buf_cnt++; - if (!drop) - __hif_usb_tx(hif_dev); /* Check for pending SKBs */ - TX_STAT_INC(buf_completed); - spin_unlock(&hif_dev->tx.tx_lock); - } -} - -/* TX lock has to be taken */ -static int __hif_usb_tx(struct hif_device_usb *hif_dev) -{ - struct tx_buf *tx_buf = NULL; - struct sk_buff *nskb = NULL; - int ret = 0, i; - u16 *hdr, tx_skb_cnt = 0; - u8 *buf; - - if (hif_dev->tx.tx_skb_cnt == 0) - return 0; - - /* Check if a free TX buffer is available */ - if (list_empty(&hif_dev->tx.tx_buf)) - return 0; - - tx_buf = list_first_entry(&hif_dev->tx.tx_buf, struct tx_buf, list); - list_del(&tx_buf->list); - list_add_tail(&tx_buf->list, &hif_dev->tx.tx_pending); - hif_dev->tx.tx_buf_cnt--; - - tx_skb_cnt = min_t(u16, hif_dev->tx.tx_skb_cnt, MAX_TX_AGGR_NUM); - - for (i = 0; i < tx_skb_cnt; i++) { - nskb = __skb_dequeue(&hif_dev->tx.tx_skb_queue); - - /* Should never be NULL */ - BUG_ON(!nskb); - - hif_dev->tx.tx_skb_cnt--; - - buf = tx_buf->buf; - buf += tx_buf->offset; - hdr = (u16 *)buf; - *hdr++ = nskb->len; - *hdr++ = ATH_USB_TX_STREAM_MODE_TAG; - buf += 4; - memcpy(buf, nskb->data, nskb->len); - tx_buf->len = nskb->len + 4; - - if (i < (tx_skb_cnt - 1)) - tx_buf->offset += (((tx_buf->len - 1) / 4) + 1) * 4; - - if (i == (tx_skb_cnt - 1)) - tx_buf->len += tx_buf->offset; - - __skb_queue_tail(&tx_buf->skb_queue, nskb); - TX_STAT_INC(skb_queued); - } - - usb_fill_bulk_urb(tx_buf->urb, hif_dev->udev, - usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE), - tx_buf->buf, tx_buf->len, - hif_usb_tx_cb, tx_buf); - - ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC); - if (ret) { - tx_buf->len = tx_buf->offset = 0; - __skb_queue_purge(&tx_buf->skb_queue); - __skb_queue_head_init(&tx_buf->skb_queue); - list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); - hif_dev->tx.tx_buf_cnt++; - } - - if (!ret) - TX_STAT_INC(buf_queued); - - return ret; -} - -static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb, - struct ath9k_htc_tx_ctl *tx_ctl) -{ - unsigned long flags; - - spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); - - if (hif_dev->tx.flags & HIF_USB_TX_STOP) { - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); - return -ENODEV; - } - - /* Check if the max queue count has been reached */ - if (hif_dev->tx.tx_skb_cnt > MAX_TX_BUF_NUM) { - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); - return -ENOMEM; - } - - __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); - hif_dev->tx.tx_skb_cnt++; - - /* Send normal frames immediately */ - if (!tx_ctl || (tx_ctl && (tx_ctl->type == ATH9K_HTC_NORMAL))) - __hif_usb_tx(hif_dev); - - /* Check if AMPDUs have to be sent immediately */ - if (tx_ctl && (tx_ctl->type == ATH9K_HTC_AMPDU) && - (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && - (hif_dev->tx.tx_skb_cnt < 2)) { - __hif_usb_tx(hif_dev); - } - - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); - - return 0; -} - -static void hif_usb_start(void *hif_handle, u8 pipe_id) -{ - struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; - unsigned long flags; - - hif_dev->flags |= HIF_USB_START; - - spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); - hif_dev->tx.flags &= ~HIF_USB_TX_STOP; - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); -} - -static void hif_usb_stop(void *hif_handle, u8 pipe_id) -{ - struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; - unsigned long flags; - - spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); - __skb_queue_purge(&hif_dev->tx.tx_skb_queue); - hif_dev->tx.tx_skb_cnt = 0; - hif_dev->tx.flags |= HIF_USB_TX_STOP; - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); -} - -static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb, - struct ath9k_htc_tx_ctl *tx_ctl) -{ - struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; - int ret = 0; - - switch (pipe_id) { - case USB_WLAN_TX_PIPE: - ret = hif_usb_send_tx(hif_dev, skb, tx_ctl); - break; - case USB_REG_OUT_PIPE: - ret = hif_usb_send_regout(hif_dev, skb); - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static struct ath9k_htc_hif hif_usb = { - .transport = ATH9K_HIF_USB, - .name = "ath9k_hif_usb", - - .control_ul_pipe = USB_REG_OUT_PIPE, - .control_dl_pipe = USB_REG_IN_PIPE, - - .start = hif_usb_start, - .stop = hif_usb_stop, - .send = hif_usb_send, -}; - -static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, - struct sk_buff *skb) -{ - struct sk_buff *nskb, *skb_pool[8]; - int index = 0, i = 0, chk_idx, len = skb->len; - int rx_remain_len = 0, rx_pkt_len = 0; - u16 pkt_len, pkt_tag, pool_index = 0; - u8 *ptr; - - rx_remain_len = hif_dev->rx_remain_len; - rx_pkt_len = hif_dev->rx_transfer_len; - - if (rx_remain_len != 0) { - struct sk_buff *remain_skb = hif_dev->remain_skb; - - if (remain_skb) { - ptr = (u8 *) remain_skb->data; - - index = rx_remain_len; - rx_remain_len -= hif_dev->rx_pad_len; - ptr += rx_pkt_len; - - memcpy(ptr, skb->data, rx_remain_len); - - rx_pkt_len += rx_remain_len; - hif_dev->rx_remain_len = 0; - skb_put(remain_skb, rx_pkt_len); - - skb_pool[pool_index++] = remain_skb; - - } else { - index = rx_remain_len; - } - } - - while (index < len) { - ptr = (u8 *) skb->data; - - pkt_len = ptr[index] + (ptr[index+1] << 8); - pkt_tag = ptr[index+2] + (ptr[index+3] << 8); - - if (pkt_tag == ATH_USB_RX_STREAM_MODE_TAG) { - u16 pad_len; - - pad_len = 4 - (pkt_len & 0x3); - if (pad_len == 4) - pad_len = 0; - - chk_idx = index; - index = index + 4 + pkt_len + pad_len; - - if (index > MAX_RX_BUF_SIZE) { - hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; - hif_dev->rx_transfer_len = - MAX_RX_BUF_SIZE - chk_idx - 4; - hif_dev->rx_pad_len = pad_len; - - nskb = __dev_alloc_skb(pkt_len + 32, - GFP_ATOMIC); - if (!nskb) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: RX memory allocation" - " error\n"); - goto err; - } - skb_reserve(nskb, 32); - RX_STAT_INC(skb_allocated); - - memcpy(nskb->data, &(skb->data[chk_idx+4]), - hif_dev->rx_transfer_len); - - /* Record the buffer pointer */ - hif_dev->remain_skb = nskb; - } else { - nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); - if (!nskb) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: RX memory allocation" - " error\n"); - goto err; - } - skb_reserve(nskb, 32); - RX_STAT_INC(skb_allocated); - - memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); - skb_put(nskb, pkt_len); - skb_pool[pool_index++] = nskb; - } - } else { - RX_STAT_INC(skb_dropped); - dev_kfree_skb_any(skb); - return; - } - } - -err: - dev_kfree_skb_any(skb); - - for (i = 0; i < pool_index; i++) { - ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i], - skb_pool[i]->len, USB_WLAN_RX_PIPE); - RX_STAT_INC(skb_completed); - } -} - -static void ath9k_hif_usb_rx_cb(struct urb *urb) -{ - struct sk_buff *skb = (struct sk_buff *) urb->context; - struct sk_buff *nskb; - struct hif_device_usb *hif_dev = (struct hif_device_usb *) - usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); - int ret; - - if (!hif_dev) - goto free; - - switch (urb->status) { - case 0: - break; - case -ENOENT: - case -ECONNRESET: - case -ENODEV: - case -ESHUTDOWN: - goto free; - default: - goto resubmit; - } - - if (likely(urb->actual_length != 0)) { - skb_put(skb, urb->actual_length); - - nskb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_ATOMIC); - if (!nskb) - goto resubmit; - - usb_fill_bulk_urb(urb, hif_dev->udev, - usb_rcvbulkpipe(hif_dev->udev, - USB_WLAN_RX_PIPE), - nskb->data, MAX_RX_BUF_SIZE, - ath9k_hif_usb_rx_cb, nskb); - - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) { - dev_kfree_skb_any(nskb); - goto free; - } - - ath9k_hif_usb_rx_stream(hif_dev, skb); - return; - } - -resubmit: - skb_reset_tail_pointer(skb); - skb_trim(skb, 0); - - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) - goto free; - - return; -free: - dev_kfree_skb_any(skb); -} - -static void ath9k_hif_usb_reg_in_cb(struct urb *urb) -{ - struct sk_buff *skb = (struct sk_buff *) urb->context; - struct sk_buff *nskb; - struct hif_device_usb *hif_dev = (struct hif_device_usb *) - usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); - int ret; - - if (!hif_dev) - goto free; - - switch (urb->status) { - case 0: - break; - case -ENOENT: - case -ECONNRESET: - case -ENODEV: - case -ESHUTDOWN: - goto free; - default: - goto resubmit; - } - - if (likely(urb->actual_length != 0)) { - skb_put(skb, urb->actual_length); - - nskb = __dev_alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); - if (!nskb) - goto resubmit; - - usb_fill_int_urb(urb, hif_dev->udev, - usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), - nskb->data, MAX_REG_IN_BUF_SIZE, - ath9k_hif_usb_reg_in_cb, nskb, 1); - - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) { - dev_kfree_skb_any(nskb); - goto free; - } - - ath9k_htc_rx_msg(hif_dev->htc_handle, skb, - skb->len, USB_REG_IN_PIPE); - - return; - } - -resubmit: - skb_reset_tail_pointer(skb); - skb_trim(skb, 0); - - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) - goto free; - - return; -free: - dev_kfree_skb_any(skb); -} - -static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) -{ - unsigned long flags; - struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; - - list_for_each_entry_safe(tx_buf, tx_buf_tmp, &hif_dev->tx.tx_buf, list) { - list_del(&tx_buf->list); - usb_free_urb(tx_buf->urb); - kfree(tx_buf->buf); - kfree(tx_buf); - } - - spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); - hif_dev->tx.flags |= HIF_USB_TX_FLUSH; - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); - - list_for_each_entry_safe(tx_buf, tx_buf_tmp, - &hif_dev->tx.tx_pending, list) { - usb_kill_urb(tx_buf->urb); - list_del(&tx_buf->list); - usb_free_urb(tx_buf->urb); - kfree(tx_buf->buf); - kfree(tx_buf); - } - - spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); - hif_dev->tx.flags &= ~HIF_USB_TX_FLUSH; - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); -} - -static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) -{ - struct tx_buf *tx_buf; - int i; - - INIT_LIST_HEAD(&hif_dev->tx.tx_buf); - INIT_LIST_HEAD(&hif_dev->tx.tx_pending); - spin_lock_init(&hif_dev->tx.tx_lock); - __skb_queue_head_init(&hif_dev->tx.tx_skb_queue); - - for (i = 0; i < MAX_TX_URB_NUM; i++) { - tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL); - if (!tx_buf) - goto err; - - tx_buf->buf = kzalloc(MAX_TX_BUF_SIZE, GFP_KERNEL); - if (!tx_buf->buf) - goto err; - - tx_buf->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!tx_buf->urb) - goto err; - - tx_buf->hif_dev = hif_dev; - __skb_queue_head_init(&tx_buf->skb_queue); - - list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf); - } - - hif_dev->tx.tx_buf_cnt = MAX_TX_URB_NUM; - - return 0; -err: - ath9k_hif_usb_dealloc_tx_urbs(hif_dev); - return -ENOMEM; -} - -static void ath9k_hif_usb_dealloc_rx_skbs(struct hif_device_usb *hif_dev) -{ - int i; - - for (i = 0; i < MAX_RX_URB_NUM; i++) { - if (hif_dev->wlan_rx_data_urb[i]) { - if (hif_dev->wlan_rx_data_urb[i]->transfer_buffer) - dev_kfree_skb_any((void *) - hif_dev->wlan_rx_data_urb[i]->context); - } - } -} - -static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev) -{ - int i; - - for (i = 0; i < MAX_RX_URB_NUM; i++) { - if (hif_dev->wlan_rx_data_urb[i]) { - usb_kill_urb(hif_dev->wlan_rx_data_urb[i]); - usb_free_urb(hif_dev->wlan_rx_data_urb[i]); - hif_dev->wlan_rx_data_urb[i] = NULL; - } - } -} - -static int ath9k_hif_usb_prep_rx_urb(struct hif_device_usb *hif_dev, - struct urb *urb) -{ - struct sk_buff *skb; - - skb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL); - if (!skb) - return -ENOMEM; - - usb_fill_bulk_urb(urb, hif_dev->udev, - usb_rcvbulkpipe(hif_dev->udev, USB_WLAN_RX_PIPE), - skb->data, MAX_RX_BUF_SIZE, - ath9k_hif_usb_rx_cb, skb); - return 0; -} - -static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) -{ - int i, ret; - - for (i = 0; i < MAX_RX_URB_NUM; i++) { - - /* Allocate URB */ - hif_dev->wlan_rx_data_urb[i] = usb_alloc_urb(0, GFP_KERNEL); - if (hif_dev->wlan_rx_data_urb[i] == NULL) { - ret = -ENOMEM; - goto err_rx_urb; - } - - /* Allocate buffer */ - ret = ath9k_hif_usb_prep_rx_urb(hif_dev, - hif_dev->wlan_rx_data_urb[i]); - if (ret) - goto err_rx_urb; - - /* Submit URB */ - ret = usb_submit_urb(hif_dev->wlan_rx_data_urb[i], GFP_KERNEL); - if (ret) - goto err_rx_urb; - - } - - return 0; - -err_rx_urb: - ath9k_hif_usb_dealloc_rx_skbs(hif_dev); - ath9k_hif_usb_dealloc_rx_urbs(hif_dev); - return ret; -} - -static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev) -{ - if (hif_dev->reg_in_urb) { - usb_kill_urb(hif_dev->reg_in_urb); - usb_free_urb(hif_dev->reg_in_urb); - hif_dev->reg_in_urb = NULL; - } -} - -static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev) -{ - struct sk_buff *skb; - - hif_dev->reg_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (hif_dev->reg_in_urb == NULL) - return -ENOMEM; - - skb = __dev_alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); - if (!skb) - goto err; - - usb_fill_int_urb(hif_dev->reg_in_urb, hif_dev->udev, - usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), - skb->data, MAX_REG_IN_BUF_SIZE, - ath9k_hif_usb_reg_in_cb, skb, 1); - - if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0) - goto err_skb; - - return 0; - -err_skb: - dev_kfree_skb_any(skb); -err: - ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); - return -ENOMEM; -} - -static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) -{ - /* TX */ - if (ath9k_hif_usb_alloc_tx_urbs(hif_dev) < 0) - goto err; - - /* RX */ - if (ath9k_hif_usb_alloc_rx_urbs(hif_dev) < 0) - goto err; - - /* Register Read/Write */ - if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0) - goto err; - - return 0; -err: - return -ENOMEM; -} - -static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) -{ - int transfer, err; - const void *data = hif_dev->firmware->data; - size_t len = hif_dev->firmware->size; - u32 addr = AR9271_FIRMWARE; - u8 *buf = kzalloc(4096, GFP_KERNEL); - - if (!buf) - return -ENOMEM; - - while (len) { - transfer = min_t(int, len, 4096); - memcpy(buf, data, transfer); - - err = usb_control_msg(hif_dev->udev, - usb_sndctrlpipe(hif_dev->udev, 0), - FIRMWARE_DOWNLOAD, 0x40 | USB_DIR_OUT, - addr >> 8, 0, buf, transfer, HZ); - if (err < 0) { - kfree(buf); - return err; - } - - len -= transfer; - data += transfer; - addr += transfer; - } - kfree(buf); - - /* - * Issue FW download complete command to firmware. - */ - err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0), - FIRMWARE_DOWNLOAD_COMP, - 0x40 | USB_DIR_OUT, - AR9271_FIRMWARE_TEXT >> 8, 0, NULL, 0, HZ); - if (err) - return -EIO; - - dev_info(&hif_dev->udev->dev, "ath9k_htc: Transferred FW: %s, size: %ld\n", - "ar9271.fw", (unsigned long) hif_dev->firmware->size); - - return 0; -} - -static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, - const char *fw_name) -{ - int ret; - - /* Request firmware */ - ret = request_firmware(&hif_dev->firmware, fw_name, &hif_dev->udev->dev); - if (ret) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: Firmware - %s not found\n", fw_name); - goto err_fw_req; - } - - /* Download firmware */ - ret = ath9k_hif_usb_download_fw(hif_dev); - if (ret) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: Firmware - %s download failed\n", fw_name); - goto err_fw_download; - } - - /* Alloc URBs */ - ret = ath9k_hif_usb_alloc_urbs(hif_dev); - if (ret) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: Unable to allocate URBs\n"); - goto err_urb; - } - - return 0; - -err_urb: - /* Nothing */ -err_fw_download: - release_firmware(hif_dev->firmware); -err_fw_req: - hif_dev->firmware = NULL; - return ret; -} - -static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) -{ - ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); - ath9k_hif_usb_dealloc_tx_urbs(hif_dev); - ath9k_hif_usb_dealloc_rx_urbs(hif_dev); -} - -static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev) -{ - ath9k_hif_usb_dealloc_urbs(hif_dev); - if (hif_dev->firmware) - release_firmware(hif_dev->firmware); -} - -static int ath9k_hif_usb_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct hif_device_usb *hif_dev; - const char *fw_name = (const char *) id->driver_info; - int ret = 0; - - hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL); - if (!hif_dev) { - ret = -ENOMEM; - goto err_alloc; - } - - usb_get_dev(udev); - hif_dev->udev = udev; - hif_dev->interface = interface; - hif_dev->device_id = id->idProduct; -#ifdef CONFIG_PM - udev->reset_resume = 1; -#endif - usb_set_intfdata(interface, hif_dev); - - ret = ath9k_hif_usb_dev_init(hif_dev, fw_name); - if (ret) { - ret = -EINVAL; - goto err_hif_init_usb; - } - - hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev); - if (hif_dev->htc_handle == NULL) { - ret = -ENOMEM; - goto err_htc_hw_alloc; - } - - ret = ath9k_htc_hw_init(&hif_usb, hif_dev->htc_handle, hif_dev, - &hif_dev->udev->dev, hif_dev->device_id, - ATH9K_HIF_USB); - if (ret) { - ret = -EINVAL; - goto err_htc_hw_init; - } - - dev_info(&hif_dev->udev->dev, "ath9k_htc: USB layer initialized\n"); - - return 0; - -err_htc_hw_init: - ath9k_htc_hw_free(hif_dev->htc_handle); -err_htc_hw_alloc: - ath9k_hif_usb_dev_deinit(hif_dev); -err_hif_init_usb: - usb_set_intfdata(interface, NULL); - kfree(hif_dev); - usb_put_dev(udev); -err_alloc: - return ret; -} - -static void ath9k_hif_usb_disconnect(struct usb_interface *interface) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct hif_device_usb *hif_dev = - (struct hif_device_usb *) usb_get_intfdata(interface); - - if (hif_dev) { - ath9k_htc_hw_deinit(hif_dev->htc_handle, true); - ath9k_htc_hw_free(hif_dev->htc_handle); - ath9k_hif_usb_dev_deinit(hif_dev); - usb_set_intfdata(interface, NULL); - } - - if (hif_dev->flags & HIF_USB_START) - usb_reset_device(udev); - - kfree(hif_dev); - dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n"); - usb_put_dev(udev); -} - -#ifdef CONFIG_PM -static int ath9k_hif_usb_suspend(struct usb_interface *interface, - pm_message_t message) -{ - struct hif_device_usb *hif_dev = - (struct hif_device_usb *) usb_get_intfdata(interface); - - ath9k_hif_usb_dealloc_urbs(hif_dev); - - return 0; -} - -static int ath9k_hif_usb_resume(struct usb_interface *interface) -{ - struct hif_device_usb *hif_dev = - (struct hif_device_usb *) usb_get_intfdata(interface); - int ret; - - ret = ath9k_hif_usb_alloc_urbs(hif_dev); - if (ret) - return ret; - - if (hif_dev->firmware) { - ret = ath9k_hif_usb_download_fw(hif_dev); - if (ret) - goto fail_resume; - } else { - ath9k_hif_usb_dealloc_urbs(hif_dev); - return -EIO; - } - - mdelay(100); - - ret = ath9k_htc_resume(hif_dev->htc_handle); - - if (ret) - goto fail_resume; - - return 0; - -fail_resume: - ath9k_hif_usb_dealloc_urbs(hif_dev); - - return ret; -} -#endif - -static struct usb_driver ath9k_hif_usb_driver = { - .name = "ath9k_hif_usb", - .probe = ath9k_hif_usb_probe, - .disconnect = ath9k_hif_usb_disconnect, -#ifdef CONFIG_PM - .suspend = ath9k_hif_usb_suspend, - .resume = ath9k_hif_usb_resume, - .reset_resume = ath9k_hif_usb_resume, -#endif - .id_table = ath9k_hif_usb_ids, - .soft_unbind = 1, -}; - -int ath9k_hif_usb_init(void) -{ - return usb_register(&ath9k_hif_usb_driver); -} - -void ath9k_hif_usb_exit(void) -{ - usb_deregister(&ath9k_hif_usb_driver); -} diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h deleted file mode 100644 index 7cc3762a6789..000000000000 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2010 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef HTC_USB_H -#define HTC_USB_H - -#define AR9271_FIRMWARE 0x501000 -#define AR9271_FIRMWARE_TEXT 0x903000 - -#define FIRMWARE_DOWNLOAD 0x30 -#define FIRMWARE_DOWNLOAD_COMP 0x31 - -#define ATH_USB_RX_STREAM_MODE_TAG 0x4e00 -#define ATH_USB_TX_STREAM_MODE_TAG 0x697e - -/* FIXME: Verify these numbers (with Windows) */ -#define MAX_TX_URB_NUM 8 -#define MAX_TX_BUF_NUM 1024 -#define MAX_TX_BUF_SIZE 32768 -#define MAX_TX_AGGR_NUM 20 - -#define MAX_RX_URB_NUM 8 -#define MAX_RX_BUF_SIZE 16384 - -#define MAX_REG_OUT_URB_NUM 1 -#define MAX_REG_OUT_BUF_NUM 8 - -#define MAX_REG_IN_BUF_SIZE 64 - -/* USB Endpoint definition */ -#define USB_WLAN_TX_PIPE 1 -#define USB_WLAN_RX_PIPE 2 -#define USB_REG_IN_PIPE 3 -#define USB_REG_OUT_PIPE 4 - -#define HIF_USB_MAX_RXPIPES 2 -#define HIF_USB_MAX_TXPIPES 4 - -struct tx_buf { - u8 *buf; - u16 len; - u16 offset; - struct urb *urb; - struct sk_buff_head skb_queue; - struct hif_device_usb *hif_dev; - struct list_head list; -}; - -#define HIF_USB_TX_STOP BIT(0) -#define HIF_USB_TX_FLUSH BIT(1) - -struct hif_usb_tx { - u8 flags; - u8 tx_buf_cnt; - u16 tx_skb_cnt; - struct sk_buff_head tx_skb_queue; - struct list_head tx_buf; - struct list_head tx_pending; - spinlock_t tx_lock; -}; - -struct cmd_buf { - struct sk_buff *skb; - struct hif_device_usb *hif_dev; -}; - -#define HIF_USB_START BIT(0) - -struct hif_device_usb { - u16 device_id; - struct usb_device *udev; - struct usb_interface *interface; - const struct firmware *firmware; - struct htc_target *htc_handle; - u8 flags; - - struct hif_usb_tx tx; - - struct urb *wlan_rx_data_urb[MAX_RX_URB_NUM]; - struct urb *reg_in_urb; - - struct sk_buff *remain_skb; - int rx_remain_len; - int rx_pkt_len; - int rx_transfer_len; - int rx_pad_len; -}; - -int ath9k_hif_usb_init(void); -void ath9k_hif_usb_exit(void); - -#endif /* HTC_USB_H */ diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h deleted file mode 100644 index ab09fe3416c7..000000000000 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright (c) 2010 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef HTC_H -#define HTC_H - -#include <linux/module.h> -#include <linux/usb.h> -#include <linux/firmware.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/leds.h> -#include <net/mac80211.h> - -#include "common.h" -#include "htc_hst.h" -#include "hif_usb.h" -#include "wmi.h" - -#define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ -#define ATH_ANI_POLLINTERVAL 100 /* 100 ms */ -#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ -#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ - -#define ATH_DEFAULT_BMISS_LIMIT 10 -#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) -#define TSF_TO_TU(_h, _l) \ - ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) - -extern struct ieee80211_ops ath9k_htc_ops; -extern int modparam_nohwcrypt; - -enum htc_phymode { - HTC_MODE_AUTO = 0, - HTC_MODE_11A = 1, - HTC_MODE_11B = 2, - HTC_MODE_11G = 3, - HTC_MODE_FH = 4, - HTC_MODE_TURBO_A = 5, - HTC_MODE_TURBO_G = 6, - HTC_MODE_11NA = 7, - HTC_MODE_11NG = 8 -}; - -enum htc_opmode { - HTC_M_STA = 1, - HTC_M_IBSS = 0, - HTC_M_AHDEMO = 3, - HTC_M_HOSTAP = 6, - HTC_M_MONITOR = 8, - HTC_M_WDS = 2 -}; - -#define ATH9K_HTC_HDRSPACE sizeof(struct htc_frame_hdr) -#define ATH9K_HTC_AMPDU 1 -#define ATH9K_HTC_NORMAL 2 - -#define ATH9K_HTC_TX_CTSONLY 0x1 -#define ATH9K_HTC_TX_RTSCTS 0x2 -#define ATH9K_HTC_TX_USE_MIN_RATE 0x100 - -struct tx_frame_hdr { - u8 data_type; - u8 node_idx; - u8 vif_idx; - u8 tidno; - u32 flags; /* ATH9K_HTC_TX_* */ - u8 key_type; - u8 keyix; - u8 reserved[26]; -} __packed; - -struct tx_mgmt_hdr { - u8 node_idx; - u8 vif_idx; - u8 tidno; - u8 flags; - u8 key_type; - u8 keyix; - u16 reserved; -} __packed; - -struct tx_beacon_header { - u8 len_changed; - u8 vif_index; - u16 rev; -} __packed; - -struct ath9k_htc_target_hw { - u32 flags; - u32 flags_ext; - u32 ampdu_limit; - u8 ampdu_subframes; - u8 tx_chainmask; - u8 tx_chainmask_legacy; - u8 rtscts_ratecode; - u8 protmode; -} __packed; - -struct ath9k_htc_cap_target { - u32 flags; - u32 flags_ext; - u32 ampdu_limit; - u8 ampdu_subframes; - u8 tx_chainmask; - u8 tx_chainmask_legacy; - u8 rtscts_ratecode; - u8 protmode; -} __packed; - -struct ath9k_htc_target_vif { - u8 index; - u8 des_bssid[ETH_ALEN]; - enum htc_opmode opmode; - u8 myaddr[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - u32 flags; - u32 flags_ext; - u16 ps_sta; - u16 rtsthreshold; - u8 ath_cap; - u8 node; - s8 mcast_rate; -} __packed; - -#define ATH_HTC_STA_AUTH 0x0001 -#define ATH_HTC_STA_QOS 0x0002 -#define ATH_HTC_STA_ERP 0x0004 -#define ATH_HTC_STA_HT 0x0008 - -/* FIXME: UAPSD variables */ -struct ath9k_htc_target_sta { - u16 associd; - u16 txpower; - u32 ucastkey; - u8 macaddr[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - u8 sta_index; - u8 vif_index; - u8 vif_sta; - u16 flags; /* ATH_HTC_STA_* */ - u16 htcap; - u8 valid; - u16 capinfo; - struct ath9k_htc_target_hw *hw; - struct ath9k_htc_target_vif *vif; - u16 txseqmgmt; - u8 is_vif_sta; - u16 maxampdu; - u16 iv16; - u32 iv32; -} __packed; - -struct ath9k_htc_target_aggr { - u8 sta_index; - u8 tidno; - u8 aggr_enable; - u8 padding; -} __packed; - -#define ATH_HTC_RATE_MAX 30 - -#define WLAN_RC_DS_FLAG 0x01 -#define WLAN_RC_40_FLAG 0x02 -#define WLAN_RC_SGI_FLAG 0x04 -#define WLAN_RC_HT_FLAG 0x08 - -struct ath9k_htc_rateset { - u8 rs_nrates; - u8 rs_rates[ATH_HTC_RATE_MAX]; -}; - -struct ath9k_htc_rate { - struct ath9k_htc_rateset legacy_rates; - struct ath9k_htc_rateset ht_rates; -} __packed; - -struct ath9k_htc_target_rate { - u8 sta_index; - u8 isnew; - u32 capflags; - struct ath9k_htc_rate rates; -}; - -struct ath9k_htc_target_stats { - u32 tx_shortretry; - u32 tx_longretry; - u32 tx_xretries; - u32 ht_txunaggr_xretry; - u32 ht_tx_xretries; -} __packed; - -struct ath9k_htc_vif { - u8 index; -}; - -#define ATH9K_HTC_MAX_STA 8 -#define ATH9K_HTC_MAX_TID 8 - -enum tid_aggr_state { - AGGR_STOP = 0, - AGGR_PROGRESS, - AGGR_START, - AGGR_OPERATIONAL -}; - -struct ath9k_htc_sta { - u8 index; - enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID]; -}; - -struct ath9k_htc_aggr_work { - u16 tid; - u8 sta_addr[ETH_ALEN]; - struct ieee80211_hw *hw; - struct ieee80211_vif *vif; - enum ieee80211_ampdu_mlme_action action; - struct mutex mutex; -}; - -#define ATH9K_HTC_RXBUF 256 -#define HTC_RX_FRAME_HEADER_SIZE 40 - -struct ath9k_htc_rxbuf { - bool in_process; - struct sk_buff *skb; - struct ath_htc_rx_status rxstatus; - struct list_head list; -}; - -struct ath9k_htc_rx { - int last_rssi; /* FIXME: per-STA */ - struct list_head rxbuf; - spinlock_t rxbuflock; -}; - -struct ath9k_htc_tx_ctl { - u8 type; /* ATH9K_HTC_* */ -}; - -#ifdef CONFIG_ATH9K_HTC_DEBUGFS - -#define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) -#define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) - -struct ath_tx_stats { - u32 buf_queued; - u32 buf_completed; - u32 skb_queued; - u32 skb_completed; -}; - -struct ath_rx_stats { - u32 skb_allocated; - u32 skb_completed; - u32 skb_dropped; -}; - -struct ath9k_debug { - struct dentry *debugfs_phy; - struct dentry *debugfs_tgt_stats; - struct dentry *debugfs_xmit; - struct dentry *debugfs_recv; - struct ath_tx_stats tx_stats; - struct ath_rx_stats rx_stats; - u32 txrate; -}; - -#else - -#define TX_STAT_INC(c) do { } while (0) -#define RX_STAT_INC(c) do { } while (0) - -#endif /* CONFIG_ATH9K_HTC_DEBUGFS */ - -#define ATH_LED_PIN_DEF 1 -#define ATH_LED_PIN_9287 8 -#define ATH_LED_PIN_9271 15 -#define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ -#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ - -enum ath_led_type { - ATH_LED_RADIO, - ATH_LED_ASSOC, - ATH_LED_TX, - ATH_LED_RX -}; - -struct ath_led { - struct ath9k_htc_priv *priv; - struct led_classdev led_cdev; - enum ath_led_type led_type; - struct delayed_work brightness_work; - char name[32]; - bool registered; - int brightness; -}; - -#define OP_INVALID BIT(0) -#define OP_SCANNING BIT(1) -#define OP_FULL_RESET BIT(2) -#define OP_LED_ASSOCIATED BIT(3) -#define OP_LED_ON BIT(4) -#define OP_PREAMBLE_SHORT BIT(5) -#define OP_PROTECT_ENABLE BIT(6) -#define OP_TXAGGR BIT(7) -#define OP_ASSOCIATED BIT(8) -#define OP_ENABLE_BEACON BIT(9) -#define OP_LED_DEINIT BIT(10) - -struct ath9k_htc_priv { - struct device *dev; - struct ieee80211_hw *hw; - struct ath_hw *ah; - struct htc_target *htc; - struct wmi *wmi; - - enum htc_endpoint_id wmi_cmd_ep; - enum htc_endpoint_id beacon_ep; - enum htc_endpoint_id cab_ep; - enum htc_endpoint_id uapsd_ep; - enum htc_endpoint_id mgmt_ep; - enum htc_endpoint_id data_be_ep; - enum htc_endpoint_id data_bk_ep; - enum htc_endpoint_id data_vi_ep; - enum htc_endpoint_id data_vo_ep; - - u16 op_flags; - u16 curtxpow; - u16 txpowlimit; - u16 nvifs; - u16 nstations; - u16 seq_no; - u32 bmiss_cnt; - - struct sk_buff *beacon; - spinlock_t beacon_lock; - - struct ieee80211_vif *vif; - unsigned int rxfilter; - struct tasklet_struct wmi_tasklet; - struct tasklet_struct rx_tasklet; - struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; - struct ath9k_htc_rx rx; - struct tasklet_struct tx_tasklet; - struct sk_buff_head tx_queue; - struct ath9k_htc_aggr_work aggr_work; - struct delayed_work ath9k_aggr_work; - struct delayed_work ath9k_ani_work; - - struct ath_led radio_led; - struct ath_led assoc_led; - struct ath_led tx_led; - struct ath_led rx_led; - struct delayed_work ath9k_led_blink_work; - int led_on_duration; - int led_off_duration; - int led_on_cnt; - int led_off_cnt; - int hwq_map[ATH9K_WME_AC_VO+1]; - -#ifdef CONFIG_ATH9K_HTC_DEBUGFS - struct ath9k_debug debug; -#endif - struct ath9k_htc_target_rate tgt_rate; - - struct mutex mutex; -}; - -static inline void ath_read_cachesize(struct ath_common *common, int *csz) -{ - common->bus_ops->read_cachesize(common, csz); -} - -void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf); -void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); -void ath9k_htc_beacon_update(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif); - -void ath9k_htc_rxep(void *priv, struct sk_buff *skb, - enum htc_endpoint_id ep_id); -void ath9k_htc_txep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id, - bool txok); - -void ath9k_htc_station_work(struct work_struct *work); -void ath9k_htc_aggr_work(struct work_struct *work); -void ath9k_ani_work(struct work_struct *work);; - -int ath9k_tx_init(struct ath9k_htc_priv *priv); -void ath9k_tx_tasklet(unsigned long data); -int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb); -void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); -bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, - enum ath9k_tx_queue_subtype qtype); -int get_hw_qnum(u16 queue, int *hwq_map); -int ath_txq_update(struct ath9k_htc_priv *priv, int qnum, - struct ath9k_tx_queue_info *qinfo); - -int ath9k_rx_init(struct ath9k_htc_priv *priv); -void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); -void ath9k_host_rx_init(struct ath9k_htc_priv *priv); -void ath9k_rx_tasklet(unsigned long data); - -void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); -void ath9k_init_leds(struct ath9k_htc_priv *priv); -void ath9k_deinit_leds(struct ath9k_htc_priv *priv); - -int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, - u16 devid); -void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); -#ifdef CONFIG_PM -int ath9k_htc_resume(struct htc_target *htc_handle); -#endif -#ifdef CONFIG_ATH9K_HTC_DEBUGFS -int ath9k_debug_create_root(void); -void ath9k_debug_remove_root(void); -int ath9k_init_debug(struct ath_hw *ah); -void ath9k_exit_debug(struct ath_hw *ah); -#else -static inline int ath9k_debug_create_root(void) { return 0; }; -static inline void ath9k_debug_remove_root(void) {}; -static inline int ath9k_init_debug(struct ath_hw *ah) { return 0; }; -static inline void ath9k_exit_debug(struct ath_hw *ah) {}; -#endif /* CONFIG_ATH9K_HTC_DEBUGFS */ - -#endif /* HTC_H */ diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c deleted file mode 100644 index 25f5b5377bac..000000000000 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2010 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "htc.h" - -#define FUDGE 2 - -static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, - struct ieee80211_bss_conf *bss_conf) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_beacon_state bs; - enum ath9k_int imask = 0; - int dtimperiod, dtimcount, sleepduration; - int cfpperiod, cfpcount, bmiss_timeout; - u32 nexttbtt = 0, intval, tsftu, htc_imask = 0; - u64 tsf; - int num_beacons, offset, dtim_dec_count, cfp_dec_count; - int ret; - u8 cmd_rsp; - - memset(&bs, 0, sizeof(bs)); - - intval = bss_conf->beacon_int & ATH9K_BEACON_PERIOD; - bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_int); - - /* - * Setup dtim and cfp parameters according to - * last beacon we received (which may be none). - */ - dtimperiod = bss_conf->dtim_period; - if (dtimperiod <= 0) /* NB: 0 if not known */ - dtimperiod = 1; - dtimcount = 1; - if (dtimcount >= dtimperiod) /* NB: sanity check */ - dtimcount = 0; - cfpperiod = 1; /* NB: no PCF support yet */ - cfpcount = 0; - - sleepduration = intval; - if (sleepduration <= 0) - sleepduration = intval; - - /* - * Pull nexttbtt forward to reflect the current - * TSF and calculate dtim+cfp state for the result. - */ - tsf = ath9k_hw_gettsf64(priv->ah); - tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; - - num_beacons = tsftu / intval + 1; - offset = tsftu % intval; - nexttbtt = tsftu - offset; - if (offset) - nexttbtt += intval; - - /* DTIM Beacon every dtimperiod Beacon */ - dtim_dec_count = num_beacons % dtimperiod; - /* CFP every cfpperiod DTIM Beacon */ - cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod; - if (dtim_dec_count) - cfp_dec_count++; - - dtimcount -= dtim_dec_count; - if (dtimcount < 0) - dtimcount += dtimperiod; - - cfpcount -= cfp_dec_count; - if (cfpcount < 0) - cfpcount += cfpperiod; - - bs.bs_intval = intval; - bs.bs_nexttbtt = nexttbtt; - bs.bs_dtimperiod = dtimperiod*intval; - bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; - bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; - bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; - bs.bs_cfpmaxduration = 0; - - /* - * Calculate the number of consecutive beacons to miss* before taking - * a BMISS interrupt. The configuration is specified in TU so we only - * need calculate based on the beacon interval. Note that we clamp the - * result to at most 15 beacons. - */ - if (sleepduration > intval) { - bs.bs_bmissthreshold = ATH_DEFAULT_BMISS_LIMIT / 2; - } else { - bs.bs_bmissthreshold = DIV_ROUND_UP(bmiss_timeout, intval); - if (bs.bs_bmissthreshold > 15) - bs.bs_bmissthreshold = 15; - else if (bs.bs_bmissthreshold <= 0) - bs.bs_bmissthreshold = 1; - } - - /* - * Calculate sleep duration. The configuration is given in ms. - * We ensure a multiple of the beacon period is used. Also, if the sleep - * duration is greater than the DTIM period then it makes senses - * to make it a multiple of that. - * - * XXX fixed at 100ms - */ - - bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration); - if (bs.bs_sleepduration > bs.bs_dtimperiod) - bs.bs_sleepduration = bs.bs_dtimperiod; - - /* TSF out of range threshold fixed at 1 second */ - bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; - - ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); - ath_print(common, ATH_DBG_BEACON, - "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", - bs.bs_bmissthreshold, bs.bs_sleepduration, - bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); - - /* Set the computed STA beacon timers */ - - WMI_CMD(WMI_DISABLE_INTR_CMDID); - ath9k_hw_set_sta_beacon_timers(priv->ah, &bs); - imask |= ATH9K_INT_BMISS; - htc_imask = cpu_to_be32(imask); - WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); -} - -static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, - struct ieee80211_bss_conf *bss_conf) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - enum ath9k_int imask = 0; - u32 nexttbtt, intval, htc_imask = 0; - int ret; - u8 cmd_rsp; - - intval = bss_conf->beacon_int & ATH9K_BEACON_PERIOD; - nexttbtt = intval; - intval |= ATH9K_BEACON_ENA; - if (priv->op_flags & OP_ENABLE_BEACON) - imask |= ATH9K_INT_SWBA; - - ath_print(common, ATH_DBG_BEACON, - "IBSS Beacon config, intval: %d, imask: 0x%x\n", - bss_conf->beacon_int, imask); - - WMI_CMD(WMI_DISABLE_INTR_CMDID); - ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); - priv->bmiss_cnt = 0; - htc_imask = cpu_to_be32(imask); - WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); -} - -void ath9k_htc_beacon_update(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - - spin_lock_bh(&priv->beacon_lock); - - if (priv->beacon) - dev_kfree_skb_any(priv->beacon); - - priv->beacon = ieee80211_beacon_get(priv->hw, vif); - if (!priv->beacon) - ath_print(common, ATH_DBG_BEACON, - "Unable to allocate beacon\n"); - - spin_unlock_bh(&priv->beacon_lock); -} - -void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) -{ - struct ath9k_htc_vif *avp = (void *)priv->vif->drv_priv; - struct tx_beacon_header beacon_hdr; - struct ath9k_htc_tx_ctl tx_ctl; - struct ieee80211_tx_info *info; - u8 *tx_fhdr; - - memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); - memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); - - /* FIXME: Handle BMISS */ - if (beacon_pending != 0) { - priv->bmiss_cnt++; - return; - } - - spin_lock_bh(&priv->beacon_lock); - - if (unlikely(priv->op_flags & OP_SCANNING)) { - spin_unlock_bh(&priv->beacon_lock); - return; - } - - if (unlikely(priv->beacon == NULL)) { - spin_unlock_bh(&priv->beacon_lock); - return; - } - - /* Free the old SKB first */ - dev_kfree_skb_any(priv->beacon); - - /* Get a new beacon */ - priv->beacon = ieee80211_beacon_get(priv->hw, priv->vif); - if (!priv->beacon) { - spin_unlock_bh(&priv->beacon_lock); - return; - } - - info = IEEE80211_SKB_CB(priv->beacon); - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *) priv->beacon->data; - priv->seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(priv->seq_no); - } - - tx_ctl.type = ATH9K_HTC_NORMAL; - beacon_hdr.vif_index = avp->index; - tx_fhdr = skb_push(priv->beacon, sizeof(beacon_hdr)); - memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); - - htc_send(priv->htc, priv->beacon, priv->beacon_ep, &tx_ctl); - - spin_unlock_bh(&priv->beacon_lock); -} - -void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - ath9k_htc_beacon_config_sta(priv, bss_conf); - break; - case NL80211_IFTYPE_ADHOC: - ath9k_htc_beacon_config_adhoc(priv, bss_conf); - break; - default: - ath_print(common, ATH_DBG_CONFIG, - "Unsupported beaconing mode\n"); - return; - } -} diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c deleted file mode 100644 index a653dec140b9..000000000000 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ /dev/null @@ -1,713 +0,0 @@ -/* - * Copyright (c) 2010 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "htc.h" - -MODULE_AUTHOR("Atheros Communications"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION("Atheros driver 802.11n HTC based wireless devices"); - -static unsigned int ath9k_debug = ATH_DBG_DEFAULT; -module_param_named(debug, ath9k_debug, uint, 0); -MODULE_PARM_DESC(debug, "Debugging mask"); - -int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); - -#define CHAN2G(_freq, _idx) { \ - .center_freq = (_freq), \ - .hw_value = (_idx), \ - .max_power = 20, \ -} - -static struct ieee80211_channel ath9k_2ghz_channels[] = { - CHAN2G(2412, 0), /* Channel 1 */ - CHAN2G(2417, 1), /* Channel 2 */ - CHAN2G(2422, 2), /* Channel 3 */ - CHAN2G(2427, 3), /* Channel 4 */ - CHAN2G(2432, 4), /* Channel 5 */ - CHAN2G(2437, 5), /* Channel 6 */ - CHAN2G(2442, 6), /* Channel 7 */ - CHAN2G(2447, 7), /* Channel 8 */ - CHAN2G(2452, 8), /* Channel 9 */ - CHAN2G(2457, 9), /* Channel 10 */ - CHAN2G(2462, 10), /* Channel 11 */ - CHAN2G(2467, 11), /* Channel 12 */ - CHAN2G(2472, 12), /* Channel 13 */ - CHAN2G(2484, 13), /* Channel 14 */ -}; - -/* Atheros hardware rate code addition for short premble */ -#define SHPCHECK(__hw_rate, __flags) \ - ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0) - -#define RATE(_bitrate, _hw_rate, _flags) { \ - .bitrate = (_bitrate), \ - .flags = (_flags), \ - .hw_value = (_hw_rate), \ - .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \ -} - -static struct ieee80211_rate ath9k_legacy_rates[] = { - RATE(10, 0x1b, 0), - RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp : 0x1e */ - RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp: 0x1d */ - RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), /* short: 0x1c */ - RATE(60, 0x0b, 0), - RATE(90, 0x0f, 0), - RATE(120, 0x0a, 0), - RATE(180, 0x0e, 0), - RATE(240, 0x09, 0), - RATE(360, 0x0d, 0), - RATE(480, 0x08, 0), - RATE(540, 0x0c, 0), -}; - -static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) -{ - int time_left; - - /* Firmware can take up to 50ms to get ready, to be safe use 1 second */ - time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ); - if (!time_left) { - dev_err(priv->dev, "ath9k_htc: Target is unresponsive\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) -{ - ath9k_exit_debug(priv->ah); - ath9k_hw_deinit(priv->ah); - tasklet_kill(&priv->wmi_tasklet); - tasklet_kill(&priv->rx_tasklet); - tasklet_kill(&priv->tx_tasklet); - kfree(priv->ah); - priv->ah = NULL; -} - -static void ath9k_deinit_device(struct ath9k_htc_priv *priv) -{ - struct ieee80211_hw *hw = priv->hw; - - wiphy_rfkill_stop_polling(hw->wiphy); - ath9k_deinit_leds(priv); - ieee80211_unregister_hw(hw); - ath9k_rx_cleanup(priv); - ath9k_tx_cleanup(priv); - ath9k_deinit_priv(priv); -} - -static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv, - u16 service_id, - void (*tx) (void *, - struct sk_buff *, - enum htc_endpoint_id, - bool txok), - enum htc_endpoint_id *ep_id) -{ - struct htc_service_connreq req; - - memset(&req, 0, sizeof(struct htc_service_connreq)); - - req.service_id = service_id; - req.ep_callbacks.priv = priv; - req.ep_callbacks.rx = ath9k_htc_rxep; - req.ep_callbacks.tx = tx; - - return htc_connect_service(priv->htc, &req, ep_id); -} - -static int ath9k_init_htc_services(struct ath9k_htc_priv *priv) -{ - int ret; - - /* WMI CMD*/ - ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep); - if (ret) - goto err; - - /* Beacon */ - ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, NULL, - &priv->beacon_ep); - if (ret) - goto err; - - /* CAB */ - ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep, - &priv->cab_ep); - if (ret) - goto err; - - - /* UAPSD */ - ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep, - &priv->uapsd_ep); - if (ret) - goto err; - - /* MGMT */ - ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep, - &priv->mgmt_ep); - if (ret) - goto err; - - /* DATA BE */ - ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep, - &priv->data_be_ep); - if (ret) - goto err; - - /* DATA BK */ - ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep, - &priv->data_bk_ep); - if (ret) - goto err; - - /* DATA VI */ - ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep, - &priv->data_vi_ep); - if (ret) - goto err; - - /* DATA VO */ - ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep, - &priv->data_vo_ep); - if (ret) - goto err; - - ret = htc_init(priv->htc); - if (ret) - goto err; - - return 0; - -err: - dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n"); - return ret; -} - -static int ath9k_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *request) -{ - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ath9k_htc_priv *priv = hw->priv; - - return ath_reg_notifier_apply(wiphy, request, - ath9k_hw_regulatory(priv->ah)); -} - -static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) -{ - struct ath_hw *ah = (struct ath_hw *) hw_priv; - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; - __be32 val, reg = cpu_to_be32(reg_offset); - int r; - - r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID, - (u8 *) ®, sizeof(reg), - (u8 *) &val, sizeof(val), - 100); - if (unlikely(r)) { - ath_print(common, ATH_DBG_WMI, - "REGISTER READ FAILED: (0x%04x, %d)\n", - reg_offset, r); - return -EIO; - } - - return be32_to_cpu(val); -} - -static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) -{ - struct ath_hw *ah = (struct ath_hw *) hw_priv; - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; - __be32 buf[2] = { - cpu_to_be32(reg_offset), - cpu_to_be32(val), - }; - int r; - - r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, - (u8 *) &buf, sizeof(buf), - (u8 *) &val, sizeof(val), - 100); - if (unlikely(r)) { - ath_print(common, ATH_DBG_WMI, - "REGISTER WRITE FAILED:(0x%04x, %d)\n", - reg_offset, r); - } -} - -static const struct ath_ops ath9k_common_ops = { - .read = ath9k_ioread32, - .write = ath9k_iowrite32, -}; - -static void ath_usb_read_cachesize(struct ath_common *common, int *csz) -{ - *csz = L1_CACHE_BYTES >> 2; -} - -static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data) -{ - struct ath_hw *ah = (struct ath_hw *) common->ah; - - (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); - - if (!ath9k_hw_wait(ah, - AR_EEPROM_STATUS_DATA, - AR_EEPROM_STATUS_DATA_BUSY | - AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, - AH_WAIT_TIMEOUT)) - return false; - - *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), - AR_EEPROM_STATUS_DATA_VAL); - - return true; -} - -static const struct ath_bus_ops ath9k_usb_bus_ops = { - .read_cachesize = ath_usb_read_cachesize, - .eeprom_read = ath_usb_eeprom_read, -}; - -static void setup_ht_cap(struct ath9k_htc_priv *priv, - struct ieee80211_sta_ht_cap *ht_info) -{ - ht_info->ht_supported = true; - ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_SM_PS | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_DSSSCCK40; - - ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; - ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; - - memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - ht_info->mcs.rx_mask[0] = 0xff; - ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; -} - -static int ath9k_init_queues(struct ath9k_htc_priv *priv) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - int i; - - for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++) - priv->hwq_map[i] = -1; - - if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BE)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for BE traffic\n"); - goto err; - } - - if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BK)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for BK traffic\n"); - goto err; - } - if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_VI)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for VI traffic\n"); - goto err; - } - if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_VO)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for VO traffic\n"); - goto err; - } - - return 0; - -err: - return -EINVAL; -} - -static void ath9k_init_crypto(struct ath9k_htc_priv *priv) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - int i = 0; - - /* Get the hardware key cache size. */ - common->keymax = priv->ah->caps.keycache_size; - if (common->keymax > ATH_KEYMAX) { - ath_print(common, ATH_DBG_ANY, - "Warning, using only %u entries in %u key cache\n", - ATH_KEYMAX, common->keymax); - common->keymax = ATH_KEYMAX; - } - - /* - * Reset the key cache since some parts do not - * reset the contents on initial power up. - */ - for (i = 0; i < common->keymax; i++) - ath9k_hw_keyreset(priv->ah, (u16) i); - - if (ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_TKIP, NULL)) { - /* - * Whether we should enable h/w TKIP MIC. - * XXX: if we don't support WME TKIP MIC, then we wouldn't - * report WMM capable, so it's always safe to turn on - * TKIP MIC in this case. - */ - ath9k_hw_setcapability(priv->ah, ATH9K_CAP_TKIP_MIC, 0, 1, NULL); - } - - /* - * Check whether the separate key cache entries - * are required to handle both tx+rx MIC keys. - * With split mic keys the number of stations is limited - * to 27 otherwise 59. - */ - if (ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_TKIP, NULL) - && ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_MIC, NULL) - && ath9k_hw_getcapability(priv->ah, ATH9K_CAP_TKIP_SPLIT, - 0, NULL)) - common->splitmic = 1; - - /* turn on mcast key search if possible */ - if (!ath9k_hw_getcapability(priv->ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) - (void)ath9k_hw_setcapability(priv->ah, ATH9K_CAP_MCAST_KEYSRCH, - 1, 1, NULL); -} - -static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) -{ - if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) { - priv->sbands[IEEE80211_BAND_2GHZ].channels = - ath9k_2ghz_channels; - priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; - priv->sbands[IEEE80211_BAND_2GHZ].n_channels = - ARRAY_SIZE(ath9k_2ghz_channels); - priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; - priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates = - ARRAY_SIZE(ath9k_legacy_rates); - } -} - -static void ath9k_init_misc(struct ath9k_htc_priv *priv) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - - common->tx_chainmask = priv->ah->caps.tx_chainmask; - common->rx_chainmask = priv->ah->caps.rx_chainmask; - - if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) - memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); - - priv->op_flags |= OP_TXAGGR; -} - -static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) -{ - struct ath_hw *ah = NULL; - struct ath_common *common; - int ret = 0, csz = 0; - - priv->op_flags |= OP_INVALID; - - ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); - if (!ah) - return -ENOMEM; - - ah->hw_version.devid = devid; - ah->hw_version.subsysid = 0; /* FIXME */ - priv->ah = ah; - - common = ath9k_hw_common(ah); - common->ops = &ath9k_common_ops; - common->bus_ops = &ath9k_usb_bus_ops; - common->ah = ah; - common->hw = priv->hw; - common->priv = priv; - common->debug_mask = ath9k_debug; - - spin_lock_init(&priv->wmi->wmi_lock); - spin_lock_init(&priv->beacon_lock); - mutex_init(&priv->mutex); - mutex_init(&priv->aggr_work.mutex); - tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, - (unsigned long)priv); - tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, - (unsigned long)priv); - tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); - INIT_DELAYED_WORK(&priv->ath9k_aggr_work, ath9k_htc_aggr_work); - INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); - - /* - * Cache line size is used to size and align various - * structures used to communicate with the hardware. - */ - ath_read_cachesize(common, &csz); - common->cachelsz = csz << 2; /* convert to bytes */ - - ret = ath9k_hw_init(ah); - if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to initialize hardware; " - "initialization status: %d\n", ret); - goto err_hw; - } - - ret = ath9k_init_debug(ah); - if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to create debugfs files\n"); - goto err_debug; - } - - ret = ath9k_init_queues(priv); - if (ret) - goto err_queues; - - ath9k_init_crypto(priv); - ath9k_init_channels_rates(priv); - ath9k_init_misc(priv); - - return 0; - -err_queues: - ath9k_exit_debug(ah); -err_debug: - ath9k_hw_deinit(ah); -err_hw: - - kfree(ah); - priv->ah = NULL; - - return ret; -} - -static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, - struct ieee80211_hw *hw) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - - hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_AMPDU_AGGREGATION | - IEEE80211_HW_SPECTRUM_MGMT | - IEEE80211_HW_HAS_RATE_CONTROL; - - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC); - - hw->queues = 4; - hw->channel_change_time = 5000; - hw->max_listen_interval = 10; - hw->vif_data_size = sizeof(struct ath9k_htc_vif); - hw->sta_data_size = sizeof(struct ath9k_htc_sta); - - /* tx_frame_hdr is larger than tx_mgmt_hdr anyway */ - hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) + - sizeof(struct htc_frame_hdr) + 4; - - if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &priv->sbands[IEEE80211_BAND_2GHZ]; - - if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) { - if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) - setup_ht_cap(priv, - &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap); - } - - SET_IEEE80211_PERM_ADDR(hw, common->macaddr); -} - -static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid) -{ - struct ieee80211_hw *hw = priv->hw; - struct ath_common *common; - struct ath_hw *ah; - int error = 0; - struct ath_regulatory *reg; - - /* Bring up device */ - error = ath9k_init_priv(priv, devid); - if (error != 0) - goto err_init; - - ah = priv->ah; - common = ath9k_hw_common(ah); - ath9k_set_hw_capab(priv, hw); - - /* Initialize regulatory */ - error = ath_regd_init(&common->regulatory, priv->hw->wiphy, - ath9k_reg_notifier); - if (error) - goto err_regd; - - reg = &common->regulatory; - - /* Setup TX */ - error = ath9k_tx_init(priv); - if (error != 0) - goto err_tx; - - /* Setup RX */ - error = ath9k_rx_init(priv); - if (error != 0) - goto err_rx; - - /* Register with mac80211 */ - error = ieee80211_register_hw(hw); - if (error) - goto err_register; - - /* Handle world regulatory */ - if (!ath_is_world_regd(reg)) { - error = regulatory_hint(hw->wiphy, reg->alpha2); - if (error) - goto err_world; - } - - ath9k_init_leds(priv); - ath9k_start_rfkill_poll(priv); - - return 0; - -err_world: - ieee80211_unregister_hw(hw); -err_register: - ath9k_rx_cleanup(priv); -err_rx: - ath9k_tx_cleanup(priv); -err_tx: - /* Nothing */ -err_regd: - ath9k_deinit_priv(priv); -err_init: - return error; -} - -int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, - u16 devid) -{ - struct ieee80211_hw *hw; - struct ath9k_htc_priv *priv; - int ret; - - hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops); - if (!hw) - return -ENOMEM; - - priv = hw->priv; - priv->hw = hw; - priv->htc = htc_handle; - priv->dev = dev; - htc_handle->drv_priv = priv; - SET_IEEE80211_DEV(hw, priv->dev); - - ret = ath9k_htc_wait_for_target(priv); - if (ret) - goto err_free; - - priv->wmi = ath9k_init_wmi(priv); - if (!priv->wmi) { - ret = -EINVAL; - goto err_free; - } - - ret = ath9k_init_htc_services(priv); - if (ret) - goto err_init; - - ret = ath9k_init_device(priv, devid); - if (ret) - goto err_init; - - return 0; - -err_init: - ath9k_deinit_wmi(priv); -err_free: - ieee80211_free_hw(hw); - return ret; -} - -void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug) -{ - if (htc_handle->drv_priv) { - ath9k_deinit_device(htc_handle->drv_priv); - ath9k_deinit_wmi(htc_handle->drv_priv); - ieee80211_free_hw(htc_handle->drv_priv->hw); - } -} - -#ifdef CONFIG_PM -int ath9k_htc_resume(struct htc_target *htc_handle) -{ - int ret; - - ret = ath9k_htc_wait_for_target(htc_handle->drv_priv); - if (ret) - return ret; - - ret = ath9k_init_htc_services(htc_handle->drv_priv); - return ret; -} -#endif - -static int __init ath9k_htc_init(void) -{ - int error; - - error = ath9k_debug_create_root(); - if (error < 0) { - printk(KERN_ERR - "ath9k_htc: Unable to create debugfs root: %d\n", - error); - goto err_dbg; - } - - error = ath9k_hif_usb_init(); - if (error < 0) { - printk(KERN_ERR - "ath9k_htc: No USB devices found," - " driver not installed.\n"); - error = -ENODEV; - goto err_usb; - } - - return 0; - -err_usb: - ath9k_debug_remove_root(); -err_dbg: - return error; -} -module_init(ath9k_htc_init); - -static void __exit ath9k_htc_exit(void) -{ - ath9k_hif_usb_exit(); - ath9k_debug_remove_root(); - printk(KERN_INFO "ath9k_htc: Driver unloaded\n"); -} -module_exit(ath9k_htc_exit); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c deleted file mode 100644 index 3184a2ac7b88..000000000000 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ /dev/null @@ -1,1626 +0,0 @@ -/* - * Copyright (c) 2010 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "htc.h" - -#ifdef CONFIG_ATH9K_HTC_DEBUGFS -static struct dentry *ath9k_debugfs_root; -#endif - -/*************/ -/* Utilities */ -/*************/ - -static void ath_update_txpow(struct ath9k_htc_priv *priv) -{ - struct ath_hw *ah = priv->ah; - u32 txpow; - - if (priv->curtxpow != priv->txpowlimit) { - ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit); - /* read back in case value is clamped */ - ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); - priv->curtxpow = txpow; - } -} - -/* HACK Alert: Use 11NG for 2.4, use 11NA for 5 */ -static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, - struct ath9k_channel *ichan) -{ - enum htc_phymode mode; - - mode = HTC_MODE_AUTO; - - switch (ichan->chanmode) { - case CHANNEL_G: - case CHANNEL_G_HT20: - case CHANNEL_G_HT40PLUS: - case CHANNEL_G_HT40MINUS: - mode = HTC_MODE_11NG; - break; - case CHANNEL_A: - case CHANNEL_A_HT20: - case CHANNEL_A_HT40PLUS: - case CHANNEL_A_HT40MINUS: - mode = HTC_MODE_11NA; - break; - default: - break; - } - - return mode; -} - -static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, - struct ieee80211_hw *hw, - struct ath9k_channel *hchan) -{ - struct ath_hw *ah = priv->ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ieee80211_conf *conf = &common->hw->conf; - bool fastcc = true; - struct ieee80211_channel *channel = hw->conf.channel; - enum htc_phymode mode; - u16 htc_mode; - u8 cmd_rsp; - int ret; - - if (priv->op_flags & OP_INVALID) - return -EIO; - - if (priv->op_flags & OP_FULL_RESET) - fastcc = false; - - /* Fiddle around with fastcc later on, for now just use full reset */ - fastcc = false; - - htc_stop(priv->htc); - WMI_CMD(WMI_DISABLE_INTR_CMDID); - WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); - WMI_CMD(WMI_STOP_RECV_CMDID); - - ath_print(common, ATH_DBG_CONFIG, - "(%u MHz) -> (%u MHz), HT: %d, HT40: %d\n", - priv->ah->curchan->channel, - channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf)); - - ret = ath9k_hw_reset(ah, hchan, fastcc); - if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset channel (%u Mhz) " - "reset status %d\n", channel->center_freq, ret); - goto err; - } - - ath_update_txpow(priv); - - WMI_CMD(WMI_START_RECV_CMDID); - if (ret) - goto err; - - ath9k_host_rx_init(priv); - - mode = ath9k_htc_get_curmode(priv, hchan); - htc_mode = cpu_to_be16(mode); - WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); - if (ret) - goto err; - - WMI_CMD(WMI_ENABLE_INTR_CMDID); - if (ret) - goto err; - - htc_start(priv->htc); - - priv->op_flags &= ~OP_FULL_RESET; -err: - return ret; -} - -static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_target_vif hvif; - int ret = 0; - u8 cmd_rsp; - - if (priv->nvifs > 0) - return -ENOBUFS; - - memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); - memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); - - hvif.opmode = cpu_to_be32(HTC_M_MONITOR); - priv->ah->opmode = NL80211_IFTYPE_MONITOR; - hvif.index = priv->nvifs; - - WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); - if (ret) - return ret; - - priv->nvifs++; - return 0; -} - -static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_target_vif hvif; - int ret = 0; - u8 cmd_rsp; - - memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); - memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); - hvif.index = 0; /* Should do for now */ - WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); - priv->nvifs--; - - return ret; -} - -static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_target_sta tsta; - struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; - struct ath9k_htc_sta *ista; - int ret; - u8 cmd_rsp; - - if (priv->nstations >= ATH9K_HTC_MAX_STA) - return -ENOBUFS; - - memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); - - if (sta) { - ista = (struct ath9k_htc_sta *) sta->drv_priv; - memcpy(&tsta.macaddr, sta->addr, ETH_ALEN); - memcpy(&tsta.bssid, common->curbssid, ETH_ALEN); - tsta.associd = common->curaid; - tsta.is_vif_sta = 0; - tsta.valid = true; - ista->index = priv->nstations; - } else { - memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); - tsta.is_vif_sta = 1; - } - - tsta.sta_index = priv->nstations; - tsta.vif_index = avp->index; - tsta.maxampdu = 0xffff; - if (sta && sta->ht_cap.ht_supported) - tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); - - WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); - if (ret) { - if (sta) - ath_print(common, ATH_DBG_FATAL, - "Unable to add station entry for: %pM\n", sta->addr); - return ret; - } - - if (sta) - ath_print(common, ATH_DBG_CONFIG, - "Added a station entry for: %pM (idx: %d)\n", - sta->addr, tsta.sta_index); - - priv->nstations++; - return 0; -} - -static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_sta *ista; - int ret; - u8 cmd_rsp, sta_idx; - - if (sta) { - ista = (struct ath9k_htc_sta *) sta->drv_priv; - sta_idx = ista->index; - } else { - sta_idx = 0; - } - - WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); - if (ret) { - if (sta) - ath_print(common, ATH_DBG_FATAL, - "Unable to remove station entry for: %pM\n", - sta->addr); - return ret; - } - - if (sta) - ath_print(common, ATH_DBG_CONFIG, - "Removed a station entry for: %pM (idx: %d)\n", - sta->addr, sta_idx); - - priv->nstations--; - return 0; -} - -static int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) -{ - struct ath9k_htc_cap_target tcap; - int ret; - u8 cmd_rsp; - - memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); - - /* FIXME: Values are hardcoded */ - tcap.flags = 0x240c40; - tcap.flags_ext = 0x80601000; - tcap.ampdu_limit = 0xffff0000; - tcap.ampdu_subframes = 20; - tcap.tx_chainmask_legacy = 1; - tcap.protmode = 1; - tcap.tx_chainmask = 1; - - WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); - - return ret; -} - -static int ath9k_htc_init_rate(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; - struct ieee80211_supported_band *sband; - struct ath9k_htc_target_rate trate; - u32 caps = 0; - u8 cmd_rsp; - int i, j, ret; - - memset(&trate, 0, sizeof(trate)); - - /* Only 2GHz is supported */ - sband = priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ]; - - for (i = 0, j = 0; i < sband->n_bitrates; i++) { - if (sta->supp_rates[sband->band] & BIT(i)) { - priv->tgt_rate.rates.legacy_rates.rs_rates[j] - = (sband->bitrates[i].bitrate * 2) / 10; - j++; - } - } - priv->tgt_rate.rates.legacy_rates.rs_nrates = j; - - if (sta->ht_cap.ht_supported) { - for (i = 0, j = 0; i < 77; i++) { - if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) - priv->tgt_rate.rates.ht_rates.rs_rates[j++] = i; - if (j == ATH_HTC_RATE_MAX) - break; - } - priv->tgt_rate.rates.ht_rates.rs_nrates = j; - - caps = WLAN_RC_HT_FLAG; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) - caps |= WLAN_RC_40_FLAG; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) - caps |= WLAN_RC_SGI_FLAG; - - } - - priv->tgt_rate.sta_index = ista->index; - priv->tgt_rate.isnew = 1; - trate = priv->tgt_rate; - priv->tgt_rate.capflags = caps; - trate.capflags = cpu_to_be32(caps); - - WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate); - if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to initialize Rate information on target\n"); - return ret; - } - - ath_print(common, ATH_DBG_CONFIG, - "Updated target STA: %pM (caps: 0x%x)\n", sta->addr, caps); - return 0; -} - -static bool check_rc_update(struct ieee80211_hw *hw, bool *cw40) -{ - struct ath9k_htc_priv *priv = hw->priv; - struct ieee80211_conf *conf = &hw->conf; - - if (!conf_is_ht(conf)) - return false; - - if (!(priv->op_flags & OP_ASSOCIATED) || - (priv->op_flags & OP_SCANNING)) - return false; - - if (conf_is_ht40(conf)) { - if (priv->ah->curchan->chanmode & - (CHANNEL_HT40PLUS | CHANNEL_HT40MINUS)) { - return false; - } else { - *cw40 = true; - return true; - } - } else { /* ht20 */ - if (priv->ah->curchan->chanmode & CHANNEL_HT20) - return false; - else - return true; - } -} - -static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40) -{ - struct ath9k_htc_target_rate trate; - struct ath_common *common = ath9k_hw_common(priv->ah); - int ret; - u8 cmd_rsp; - - memset(&trate, 0, sizeof(trate)); - - trate = priv->tgt_rate; - - if (is_cw40) - priv->tgt_rate.capflags |= WLAN_RC_40_FLAG; - else - priv->tgt_rate.capflags &= ~WLAN_RC_40_FLAG; - - trate.capflags = cpu_to_be32(priv->tgt_rate.capflags); - - WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate); - if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to update Rate information on target\n"); - return; - } - - ath_print(common, ATH_DBG_CONFIG, "Rate control updated with " - "caps:0x%x on target\n", priv->tgt_rate.capflags); -} - -static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif, - u8 *sta_addr, u8 tid, bool oper) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_target_aggr aggr; - struct ieee80211_sta *sta = NULL; - struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; - int ret = 0; - u8 cmd_rsp; - - if (tid > ATH9K_HTC_MAX_TID) - return -EINVAL; - - rcu_read_lock(); - sta = ieee80211_find_sta(vif, sta_addr); - if (sta) { - ista = (struct ath9k_htc_sta *) sta->drv_priv; - } else { - rcu_read_unlock(); - return -EINVAL; - } - - if (!ista) { - rcu_read_unlock(); - return -EINVAL; - } - - memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); - - aggr.sta_index = ista->index; - rcu_read_unlock(); - aggr.tidno = tid; - aggr.aggr_enable = oper; - - if (oper) - ista->tid_state[tid] = AGGR_START; - else - ista->tid_state[tid] = AGGR_STOP; - - WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); - if (ret) - ath_print(common, ATH_DBG_CONFIG, - "Unable to %s TX aggregation for (%pM, %d)\n", - (oper) ? "start" : "stop", sta->addr, tid); - else - ath_print(common, ATH_DBG_CONFIG, - "%s aggregation for (%pM, %d)\n", - (oper) ? "Starting" : "Stopping", sta->addr, tid); - - return ret; -} - -void ath9k_htc_aggr_work(struct work_struct *work) -{ - int ret = 0; - struct ath9k_htc_priv *priv = - container_of(work, struct ath9k_htc_priv, - ath9k_aggr_work.work); - struct ath9k_htc_aggr_work *wk = &priv->aggr_work; - - mutex_lock(&wk->mutex); - - switch (wk->action) { - case IEEE80211_AMPDU_TX_START: - ret = ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr, - wk->tid, true); - if (!ret) - ieee80211_start_tx_ba_cb(wk->vif, wk->sta_addr, - wk->tid); - break; - case IEEE80211_AMPDU_TX_STOP: - ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr, - wk->tid, false); - ieee80211_stop_tx_ba_cb(wk->vif, wk->sta_addr, wk->tid); - break; - default: - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, - "Unknown AMPDU action\n"); - } - - mutex_unlock(&wk->mutex); -} - -/*********/ -/* DEBUG */ -/*********/ - -#ifdef CONFIG_ATH9K_HTC_DEBUGFS - -static int ath9k_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath9k_htc_priv *priv = - (struct ath9k_htc_priv *) file->private_data; - struct ath9k_htc_target_stats cmd_rsp; - char buf[512]; - unsigned int len = 0; - int ret = 0; - - memset(&cmd_rsp, 0, sizeof(cmd_rsp)); - - WMI_CMD(WMI_TGT_STATS_CMDID); - if (ret) - return -EINVAL; - - - len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Short Retries", - be32_to_cpu(cmd_rsp.tx_shortretry)); - len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Long Retries", - be32_to_cpu(cmd_rsp.tx_longretry)); - len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Xretries", - be32_to_cpu(cmd_rsp.tx_xretries)); - len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Unaggr. Xretries", - be32_to_cpu(cmd_rsp.ht_txunaggr_xretry)); - len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Xretries (HT)", - be32_to_cpu(cmd_rsp.ht_tx_xretries)); - len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Rate", priv->debug.txrate); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_tgt_stats = { - .read = read_file_tgt_stats, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - -static ssize_t read_file_xmit(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath9k_htc_priv *priv = - (struct ath9k_htc_priv *) file->private_data; - char buf[512]; - unsigned int len = 0; - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "Buffers queued", - priv->debug.tx_stats.buf_queued); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "Buffers completed", - priv->debug.tx_stats.buf_completed); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs queued", - priv->debug.tx_stats.skb_queued); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs completed", - priv->debug.tx_stats.skb_completed); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_xmit = { - .read = read_file_xmit, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - -static ssize_t read_file_recv(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath9k_htc_priv *priv = - (struct ath9k_htc_priv *) file->private_data; - char buf[512]; - unsigned int len = 0; - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs allocated", - priv->debug.rx_stats.skb_allocated); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs completed", - priv->debug.rx_stats.skb_completed); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs Dropped", - priv->debug.rx_stats.skb_dropped); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_recv = { - .read = read_file_recv, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - -int ath9k_init_debug(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; - - if (!ath9k_debugfs_root) - return -ENOENT; - - priv->debug.debugfs_phy = debugfs_create_dir(wiphy_name(priv->hw->wiphy), - ath9k_debugfs_root); - if (!priv->debug.debugfs_phy) - goto err; - - priv->debug.debugfs_tgt_stats = debugfs_create_file("tgt_stats", S_IRUSR, - priv->debug.debugfs_phy, - priv, &fops_tgt_stats); - if (!priv->debug.debugfs_tgt_stats) - goto err; - - - priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR, - priv->debug.debugfs_phy, - priv, &fops_xmit); - if (!priv->debug.debugfs_xmit) - goto err; - - priv->debug.debugfs_recv = debugfs_create_file("recv", S_IRUSR, - priv->debug.debugfs_phy, - priv, &fops_recv); - if (!priv->debug.debugfs_recv) - goto err; - - return 0; - -err: - ath9k_exit_debug(ah); - return -ENOMEM; -} - -void ath9k_exit_debug(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; - - debugfs_remove(priv->debug.debugfs_recv); - debugfs_remove(priv->debug.debugfs_xmit); - debugfs_remove(priv->debug.debugfs_tgt_stats); - debugfs_remove(priv->debug.debugfs_phy); -} - -int ath9k_debug_create_root(void) -{ - ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (!ath9k_debugfs_root) - return -ENOENT; - - return 0; -} - -void ath9k_debug_remove_root(void) -{ - debugfs_remove(ath9k_debugfs_root); - ath9k_debugfs_root = NULL; -} - -#endif /* CONFIG_ATH9K_HTC_DEBUGFS */ - -/*******/ -/* ANI */ -/*******/ - -static void ath_start_ani(struct ath9k_htc_priv *priv) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - unsigned long timestamp = jiffies_to_msecs(jiffies); - - common->ani.longcal_timer = timestamp; - common->ani.shortcal_timer = timestamp; - common->ani.checkani_timer = timestamp; - - ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work, - msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); -} - -void ath9k_ani_work(struct work_struct *work) -{ - struct ath9k_htc_priv *priv = - container_of(work, struct ath9k_htc_priv, - ath9k_ani_work.work); - struct ath_hw *ah = priv->ah; - struct ath_common *common = ath9k_hw_common(ah); - bool longcal = false; - bool shortcal = false; - bool aniflag = false; - unsigned int timestamp = jiffies_to_msecs(jiffies); - u32 cal_interval, short_cal_interval; - - short_cal_interval = ATH_STA_SHORT_CALINTERVAL; - - /* Long calibration runs independently of short calibration. */ - if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { - longcal = true; - ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); - common->ani.longcal_timer = timestamp; - } - - /* Short calibration applies only while caldone is false */ - if (!common->ani.caldone) { - if ((timestamp - common->ani.shortcal_timer) >= - short_cal_interval) { - shortcal = true; - ath_print(common, ATH_DBG_ANI, - "shortcal @%lu\n", jiffies); - common->ani.shortcal_timer = timestamp; - common->ani.resetcal_timer = timestamp; - } - } else { - if ((timestamp - common->ani.resetcal_timer) >= - ATH_RESTART_CALINTERVAL) { - common->ani.caldone = ath9k_hw_reset_calvalid(ah); - if (common->ani.caldone) - common->ani.resetcal_timer = timestamp; - } - } - - /* Verify whether we must check ANI */ - if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { - aniflag = true; - common->ani.checkani_timer = timestamp; - } - - /* Skip all processing if there's nothing to do. */ - if (longcal || shortcal || aniflag) { - /* Call ANI routine if necessary */ - if (aniflag) - ath9k_hw_ani_monitor(ah, ah->curchan); - - /* Perform calibration if necessary */ - if (longcal || shortcal) { - common->ani.caldone = - ath9k_hw_calibrate(ah, ah->curchan, - common->rx_chainmask, - longcal); - - if (longcal) - common->ani.noise_floor = - ath9k_hw_getchan_noise(ah, ah->curchan); - - ath_print(common, ATH_DBG_ANI, - " calibrate chan %u/%x nf: %d\n", - ah->curchan->channel, - ah->curchan->channelFlags, - common->ani.noise_floor); - } - } - - /* - * Set timer interval based on previous results. - * The interval must be the shortest necessary to satisfy ANI, - * short calibration and long calibration. - */ - cal_interval = ATH_LONG_CALINTERVAL; - if (priv->ah->config.enable_ani) - cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); - if (!common->ani.caldone) - cal_interval = min(cal_interval, (u32)short_cal_interval); - - ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work, - msecs_to_jiffies(cal_interval)); -} - -/*******/ -/* LED */ -/*******/ - -static void ath9k_led_blink_work(struct work_struct *work) -{ - struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, - ath9k_led_blink_work.work); - - if (!(priv->op_flags & OP_LED_ASSOCIATED)) - return; - - if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) || - (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); - else - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, - (priv->op_flags & OP_LED_ON) ? 1 : 0); - - ieee80211_queue_delayed_work(priv->hw, - &priv->ath9k_led_blink_work, - (priv->op_flags & OP_LED_ON) ? - msecs_to_jiffies(priv->led_off_duration) : - msecs_to_jiffies(priv->led_on_duration)); - - priv->led_on_duration = priv->led_on_cnt ? - max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) : - ATH_LED_ON_DURATION_IDLE; - priv->led_off_duration = priv->led_off_cnt ? - max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) : - ATH_LED_OFF_DURATION_IDLE; - priv->led_on_cnt = priv->led_off_cnt = 0; - - if (priv->op_flags & OP_LED_ON) - priv->op_flags &= ~OP_LED_ON; - else - priv->op_flags |= OP_LED_ON; -} - -static void ath9k_led_brightness_work(struct work_struct *work) -{ - struct ath_led *led = container_of(work, struct ath_led, - brightness_work.work); - struct ath9k_htc_priv *priv = led->priv; - - switch (led->brightness) { - case LED_OFF: - if (led->led_type == ATH_LED_ASSOC || - led->led_type == ATH_LED_RADIO) { - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, - (led->led_type == ATH_LED_RADIO)); - priv->op_flags &= ~OP_LED_ASSOCIATED; - if (led->led_type == ATH_LED_RADIO) - priv->op_flags &= ~OP_LED_ON; - } else { - priv->led_off_cnt++; - } - break; - case LED_FULL: - if (led->led_type == ATH_LED_ASSOC) { - priv->op_flags |= OP_LED_ASSOCIATED; - ieee80211_queue_delayed_work(priv->hw, - &priv->ath9k_led_blink_work, 0); - } else if (led->led_type == ATH_LED_RADIO) { - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); - priv->op_flags |= OP_LED_ON; - } else { - priv->led_on_cnt++; - } - break; - default: - break; - } -} - -static void ath9k_led_brightness(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); - struct ath9k_htc_priv *priv = led->priv; - - led->brightness = brightness; - if (!(priv->op_flags & OP_LED_DEINIT)) - ieee80211_queue_delayed_work(priv->hw, - &led->brightness_work, 0); -} - -static void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv) -{ - cancel_delayed_work_sync(&priv->radio_led.brightness_work); - cancel_delayed_work_sync(&priv->assoc_led.brightness_work); - cancel_delayed_work_sync(&priv->tx_led.brightness_work); - cancel_delayed_work_sync(&priv->rx_led.brightness_work); -} - -static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led, - char *trigger) -{ - int ret; - - led->priv = priv; - led->led_cdev.name = led->name; - led->led_cdev.default_trigger = trigger; - led->led_cdev.brightness_set = ath9k_led_brightness; - - ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev); - if (ret) - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, - "Failed to register led:%s", led->name); - else - led->registered = 1; - - INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work); - - return ret; -} - -static void ath9k_unregister_led(struct ath_led *led) -{ - if (led->registered) { - led_classdev_unregister(&led->led_cdev); - led->registered = 0; - } -} - -void ath9k_deinit_leds(struct ath9k_htc_priv *priv) -{ - priv->op_flags |= OP_LED_DEINIT; - ath9k_unregister_led(&priv->assoc_led); - priv->op_flags &= ~OP_LED_ASSOCIATED; - ath9k_unregister_led(&priv->tx_led); - ath9k_unregister_led(&priv->rx_led); - ath9k_unregister_led(&priv->radio_led); - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); -} - -void ath9k_init_leds(struct ath9k_htc_priv *priv) -{ - char *trigger; - int ret; - - if (AR_SREV_9287(priv->ah)) - priv->ah->led_pin = ATH_LED_PIN_9287; - else if (AR_SREV_9271(priv->ah)) - priv->ah->led_pin = ATH_LED_PIN_9271; - else - priv->ah->led_pin = ATH_LED_PIN_DEF; - - /* Configure gpio 1 for output */ - ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - /* LED off, active low */ - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); - - INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work); - - trigger = ieee80211_get_radio_led_name(priv->hw); - snprintf(priv->radio_led.name, sizeof(priv->radio_led.name), - "ath9k-%s::radio", wiphy_name(priv->hw->wiphy)); - ret = ath9k_register_led(priv, &priv->radio_led, trigger); - priv->radio_led.led_type = ATH_LED_RADIO; - if (ret) - goto fail; - - trigger = ieee80211_get_assoc_led_name(priv->hw); - snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name), - "ath9k-%s::assoc", wiphy_name(priv->hw->wiphy)); - ret = ath9k_register_led(priv, &priv->assoc_led, trigger); - priv->assoc_led.led_type = ATH_LED_ASSOC; - if (ret) - goto fail; - - trigger = ieee80211_get_tx_led_name(priv->hw); - snprintf(priv->tx_led.name, sizeof(priv->tx_led.name), - "ath9k-%s::tx", wiphy_name(priv->hw->wiphy)); - ret = ath9k_register_led(priv, &priv->tx_led, trigger); - priv->tx_led.led_type = ATH_LED_TX; - if (ret) - goto fail; - - trigger = ieee80211_get_rx_led_name(priv->hw); - snprintf(priv->rx_led.name, sizeof(priv->rx_led.name), - "ath9k-%s::rx", wiphy_name(priv->hw->wiphy)); - ret = ath9k_register_led(priv, &priv->rx_led, trigger); - priv->rx_led.led_type = ATH_LED_RX; - if (ret) - goto fail; - - priv->op_flags &= ~OP_LED_DEINIT; - - return; - -fail: - cancel_delayed_work_sync(&priv->ath9k_led_blink_work); - ath9k_deinit_leds(priv); -} - -/*******************/ -/* Rfkill */ -/*******************/ - -static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv) -{ - return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) == - priv->ah->rfkill_polarity; -} - -static void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw) -{ - struct ath9k_htc_priv *priv = hw->priv; - bool blocked = !!ath_is_rfkill_set(priv); - - wiphy_rfkill_set_hw_state(hw->wiphy, blocked); -} - -void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv) -{ - if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - wiphy_rfkill_start_polling(priv->hw->wiphy); -} - -/**********************/ -/* mac80211 Callbacks */ -/**********************/ - -static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr; - struct ath9k_htc_priv *priv = hw->priv; - int padpos, padsize; - - hdr = (struct ieee80211_hdr *) skb->data; - - /* Add the padding after the header if this is not already done */ - padpos = ath9k_cmn_padpos(hdr->frame_control); - padsize = padpos & 3; - if (padsize && skb->len > padpos) { - if (skb_headroom(skb) < padsize) - return -1; - skb_push(skb, padsize); - memmove(skb->data, skb->data + padsize, padpos); - } - - if (ath9k_htc_tx_start(priv, skb) != 0) { - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, "Tx failed"); - goto fail_tx; - } - - return 0; - -fail_tx: - dev_kfree_skb_any(skb); - return 0; -} - -static int ath9k_htc_start(struct ieee80211_hw *hw) -{ - struct ath9k_htc_priv *priv = hw->priv; - struct ath_hw *ah = priv->ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ieee80211_channel *curchan = hw->conf.channel; - struct ath9k_channel *init_channel; - int ret = 0; - enum htc_phymode mode; - u16 htc_mode; - u8 cmd_rsp; - - ath_print(common, ATH_DBG_CONFIG, - "Starting driver with initial channel: %d MHz\n", - curchan->center_freq); - - mutex_lock(&priv->mutex); - - /* setup initial channel */ - init_channel = ath9k_cmn_get_curchannel(hw, ah); - - /* Reset SERDES registers */ - ath9k_hw_configpcipowersave(ah, 0, 0); - - ath9k_hw_htc_resetinit(ah); - ret = ath9k_hw_reset(ah, init_channel, false); - if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d " - "(freq %u MHz)\n", ret, curchan->center_freq); - goto mutex_unlock; - } - - ath_update_txpow(priv); - - mode = ath9k_htc_get_curmode(priv, init_channel); - htc_mode = cpu_to_be16(mode); - WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); - if (ret) - goto mutex_unlock; - - WMI_CMD(WMI_ATH_INIT_CMDID); - if (ret) - goto mutex_unlock; - - WMI_CMD(WMI_START_RECV_CMDID); - if (ret) - goto mutex_unlock; - - ath9k_host_rx_init(priv); - - priv->op_flags &= ~OP_INVALID; - htc_start(priv->htc); - -mutex_unlock: - mutex_unlock(&priv->mutex); - return ret; -} - -static void ath9k_htc_stop(struct ieee80211_hw *hw) -{ - struct ath9k_htc_priv *priv = hw->priv; - struct ath_hw *ah = priv->ah; - struct ath_common *common = ath9k_hw_common(ah); - int ret = 0; - u8 cmd_rsp; - - mutex_lock(&priv->mutex); - - if (priv->op_flags & OP_INVALID) { - ath_print(common, ATH_DBG_ANY, "Device not present\n"); - mutex_unlock(&priv->mutex); - return; - } - - htc_stop(priv->htc); - WMI_CMD(WMI_DISABLE_INTR_CMDID); - WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); - WMI_CMD(WMI_STOP_RECV_CMDID); - ath9k_hw_phy_disable(ah); - ath9k_hw_disable(ah); - ath9k_hw_configpcipowersave(ah, 1, 1); - ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); - - cancel_delayed_work_sync(&priv->ath9k_ani_work); - cancel_delayed_work_sync(&priv->ath9k_aggr_work); - cancel_delayed_work_sync(&priv->ath9k_led_blink_work); - ath9k_led_stop_brightness(priv); - skb_queue_purge(&priv->tx_queue); - - /* Remove monitor interface here */ - if (ah->opmode == NL80211_IFTYPE_MONITOR) { - if (ath9k_htc_remove_monitor_interface(priv)) - ath_print(common, ATH_DBG_FATAL, - "Unable to remove monitor interface\n"); - else - ath_print(common, ATH_DBG_CONFIG, - "Monitor interface removed\n"); - } - - priv->op_flags |= OP_INVALID; - mutex_unlock(&priv->mutex); - - ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); -} - -static int ath9k_htc_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct ath9k_htc_priv *priv = hw->priv; - struct ath9k_htc_vif *avp = (void *)vif->drv_priv; - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_target_vif hvif; - int ret = 0; - u8 cmd_rsp; - - mutex_lock(&priv->mutex); - - /* Only one interface for now */ - if (priv->nvifs > 0) { - ret = -ENOBUFS; - goto out; - } - - memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); - memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - hvif.opmode = cpu_to_be32(HTC_M_STA); - break; - case NL80211_IFTYPE_ADHOC: - hvif.opmode = cpu_to_be32(HTC_M_IBSS); - break; - default: - ath_print(common, ATH_DBG_FATAL, - "Interface type %d not yet supported\n", vif->type); - ret = -EOPNOTSUPP; - goto out; - } - - ath_print(common, ATH_DBG_CONFIG, - "Attach a VIF of type: %d\n", vif->type); - - priv->ah->opmode = vif->type; - - /* Index starts from zero on the target */ - avp->index = hvif.index = priv->nvifs; - hvif.rtsthreshold = cpu_to_be16(2304); - WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); - if (ret) - goto out; - - priv->nvifs++; - - /* - * We need a node in target to tx mgmt frames - * before association. - */ - ret = ath9k_htc_add_station(priv, vif, NULL); - if (ret) - goto out; - - ret = ath9k_htc_update_cap_target(priv); - if (ret) - ath_print(common, ATH_DBG_CONFIG, "Failed to update" - " capability in target \n"); - - priv->vif = vif; -out: - mutex_unlock(&priv->mutex); - return ret; -} - -static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct ath9k_htc_priv *priv = hw->priv; - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_vif *avp = (void *)vif->drv_priv; - struct ath9k_htc_target_vif hvif; - int ret = 0; - u8 cmd_rsp; - - ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); - - mutex_lock(&priv->mutex); - - memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); - memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); - hvif.index = avp->index; - WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); - priv->nvifs--; - - ath9k_htc_remove_station(priv, vif, NULL); - - if (vif->type == NL80211_IFTYPE_ADHOC) { - spin_lock_bh(&priv->beacon_lock); - if (priv->beacon) - dev_kfree_skb_any(priv->beacon); - priv->beacon = NULL; - spin_unlock_bh(&priv->beacon_lock); - } - - priv->vif = NULL; - - mutex_unlock(&priv->mutex); -} - -static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) -{ - struct ath9k_htc_priv *priv = hw->priv; - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ieee80211_conf *conf = &hw->conf; - - mutex_lock(&priv->mutex); - - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - struct ieee80211_channel *curchan = hw->conf.channel; - int pos = curchan->hw_value; - bool is_cw40 = false; - - ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", - curchan->center_freq); - - if (check_rc_update(hw, &is_cw40)) - ath9k_htc_rc_update(priv, is_cw40); - - ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]); - - if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { - ath_print(common, ATH_DBG_FATAL, - "Unable to set channel\n"); - mutex_unlock(&priv->mutex); - return -EINVAL; - } - - } - - if (changed & IEEE80211_CONF_CHANGE_MONITOR) { - if (conf->flags & IEEE80211_CONF_MONITOR) { - if (ath9k_htc_add_monitor_interface(priv)) - ath_print(common, ATH_DBG_FATAL, - "Failed to set monitor mode\n"); - else - ath_print(common, ATH_DBG_CONFIG, - "HW opmode set to Monitor mode\n"); - } - } - - mutex_unlock(&priv->mutex); - - return 0; -} - -#define SUPPORTED_FILTERS \ - (FIF_PROMISC_IN_BSS | \ - FIF_ALLMULTI | \ - FIF_CONTROL | \ - FIF_PSPOLL | \ - FIF_OTHER_BSS | \ - FIF_BCN_PRBRESP_PROMISC | \ - FIF_FCSFAIL) - -static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct ath9k_htc_priv *priv = hw->priv; - u32 rfilt; - - mutex_lock(&priv->mutex); - - changed_flags &= SUPPORTED_FILTERS; - *total_flags &= SUPPORTED_FILTERS; - - priv->rxfilter = *total_flags; - rfilt = ath9k_cmn_calcrxfilter(hw, priv->ah, priv->rxfilter); - ath9k_hw_setrxfilter(priv->ah, rfilt); - - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG, - "Set HW RX filter: 0x%x\n", rfilt); - - mutex_unlock(&priv->mutex); -} - -static void ath9k_htc_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) -{ - struct ath9k_htc_priv *priv = hw->priv; - int ret; - - switch (cmd) { - case STA_NOTIFY_ADD: - ret = ath9k_htc_add_station(priv, vif, sta); - if (!ret) - ath9k_htc_init_rate(priv, vif, sta); - break; - case STA_NOTIFY_REMOVE: - ath9k_htc_remove_station(priv, vif, sta); - break; - default: - break; - } -} - -static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct ath9k_htc_priv *priv = hw->priv; - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_tx_queue_info qi; - int ret = 0, qnum; - - if (queue >= WME_NUM_AC) - return 0; - - mutex_lock(&priv->mutex); - - memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); - - qi.tqi_aifs = params->aifs; - qi.tqi_cwmin = params->cw_min; - qi.tqi_cwmax = params->cw_max; - qi.tqi_burstTime = params->txop; - - qnum = get_hw_qnum(queue, priv->hwq_map); - - ath_print(common, ATH_DBG_CONFIG, - "Configure tx [queue/hwq] [%d/%d], " - "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", - queue, qnum, params->aifs, params->cw_min, - params->cw_max, params->txop); - - ret = ath_txq_update(priv, qnum, &qi); - if (ret) - ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); - - mutex_unlock(&priv->mutex); - - return ret; -} - -static int ath9k_htc_set_key(struct ieee80211_hw *hw, - enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct ath9k_htc_priv *priv = hw->priv; - struct ath_common *common = ath9k_hw_common(priv->ah); - int ret = 0; - - if (modparam_nohwcrypt) - return -ENOSPC; - - mutex_lock(&priv->mutex); - ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); - - switch (cmd) { - case SET_KEY: - ret = ath9k_cmn_key_config(common, vif, sta, key); - if (ret >= 0) { - key->hw_key_idx = ret; - /* push IV and Michael MIC generation to stack */ - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - if (key->alg == ALG_TKIP) - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - if (priv->ah->sw_mgmt_crypto && key->alg == ALG_CCMP) - key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; - ret = 0; - } - break; - case DISABLE_KEY: - ath9k_cmn_key_delete(common, key); - break; - default: - ret = -EINVAL; - } - - mutex_unlock(&priv->mutex); - - return ret; -} - -static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changed) -{ - struct ath9k_htc_priv *priv = hw->priv; - struct ath_hw *ah = priv->ah; - struct ath_common *common = ath9k_hw_common(ah); - - mutex_lock(&priv->mutex); - - if (changed & BSS_CHANGED_ASSOC) { - common->curaid = bss_conf->assoc ? - bss_conf->aid : 0; - ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", - bss_conf->assoc); - - if (bss_conf->assoc) { - priv->op_flags |= OP_ASSOCIATED; - ath_start_ani(priv); - } else { - priv->op_flags &= ~OP_ASSOCIATED; - cancel_delayed_work_sync(&priv->ath9k_ani_work); - } - } - - if (changed & BSS_CHANGED_BSSID) { - /* Set BSSID */ - memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); - ath9k_hw_write_associd(ah); - - ath_print(common, ATH_DBG_CONFIG, - "BSSID: %pM aid: 0x%x\n", - common->curbssid, common->curaid); - } - - if ((changed & BSS_CHANGED_BEACON_INT) || - (changed & BSS_CHANGED_BEACON) || - ((changed & BSS_CHANGED_BEACON_ENABLED) && - bss_conf->enable_beacon)) { - priv->op_flags |= OP_ENABLE_BEACON; - ath9k_htc_beacon_config(priv, vif, bss_conf); - } - - if (changed & BSS_CHANGED_BEACON) - ath9k_htc_beacon_update(priv, vif); - - if ((changed & BSS_CHANGED_BEACON_ENABLED) && - !bss_conf->enable_beacon) { - priv->op_flags &= ~OP_ENABLE_BEACON; - ath9k_htc_beacon_config(priv, vif, bss_conf); - } - - if (changed & BSS_CHANGED_ERP_PREAMBLE) { - ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", - bss_conf->use_short_preamble); - if (bss_conf->use_short_preamble) - priv->op_flags |= OP_PREAMBLE_SHORT; - else - priv->op_flags &= ~OP_PREAMBLE_SHORT; - } - - if (changed & BSS_CHANGED_ERP_CTS_PROT) { - ath_print(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", - bss_conf->use_cts_prot); - if (bss_conf->use_cts_prot && - hw->conf.channel->band != IEEE80211_BAND_5GHZ) - priv->op_flags |= OP_PROTECT_ENABLE; - else - priv->op_flags &= ~OP_PROTECT_ENABLE; - } - - if (changed & BSS_CHANGED_ERP_SLOT) { - if (bss_conf->use_short_slot) - ah->slottime = 9; - else - ah->slottime = 20; - - ath9k_hw_init_global_settings(ah); - } - - mutex_unlock(&priv->mutex); -} - -static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw) -{ - struct ath9k_htc_priv *priv = hw->priv; - u64 tsf; - - mutex_lock(&priv->mutex); - tsf = ath9k_hw_gettsf64(priv->ah); - mutex_unlock(&priv->mutex); - - return tsf; -} - -static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf) -{ - struct ath9k_htc_priv *priv = hw->priv; - - mutex_lock(&priv->mutex); - ath9k_hw_settsf64(priv->ah, tsf); - mutex_unlock(&priv->mutex); -} - -static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw) -{ - struct ath9k_htc_priv *priv = hw->priv; - - mutex_lock(&priv->mutex); - ath9k_hw_reset_tsf(priv->ah); - mutex_unlock(&priv->mutex); -} - -static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn) -{ - struct ath9k_htc_priv *priv = hw->priv; - struct ath9k_htc_aggr_work *work = &priv->aggr_work; - struct ath9k_htc_sta *ista; - - switch (action) { - case IEEE80211_AMPDU_RX_START: - break; - case IEEE80211_AMPDU_RX_STOP: - break; - case IEEE80211_AMPDU_TX_START: - case IEEE80211_AMPDU_TX_STOP: - if (!(priv->op_flags & OP_TXAGGR)) - return -ENOTSUPP; - memcpy(work->sta_addr, sta->addr, ETH_ALEN); - work->hw = hw; - work->vif = vif; - work->action = action; - work->tid = tid; - ieee80211_queue_delayed_work(hw, &priv->ath9k_aggr_work, 0); - break; - case IEEE80211_AMPDU_TX_OPERATIONAL: - ista = (struct ath9k_htc_sta *) sta->drv_priv; - ista->tid_state[tid] = AGGR_OPERATIONAL; - break; - default: - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, - "Unknown AMPDU action\n"); - } - - return 0; -} - -static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) -{ - struct ath9k_htc_priv *priv = hw->priv; - - mutex_lock(&priv->mutex); - spin_lock_bh(&priv->beacon_lock); - priv->op_flags |= OP_SCANNING; - spin_unlock_bh(&priv->beacon_lock); - cancel_delayed_work_sync(&priv->ath9k_ani_work); - mutex_unlock(&priv->mutex); -} - -static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) -{ - struct ath9k_htc_priv *priv = hw->priv; - - mutex_lock(&priv->mutex); - spin_lock_bh(&priv->beacon_lock); - priv->op_flags &= ~OP_SCANNING; - spin_unlock_bh(&priv->beacon_lock); - priv->op_flags |= OP_FULL_RESET; - ath_start_ani(priv); - mutex_unlock(&priv->mutex); -} - -static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value) -{ - return 0; -} - -static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw, - u8 coverage_class) -{ - struct ath9k_htc_priv *priv = hw->priv; - - mutex_lock(&priv->mutex); - priv->ah->coverage_class = coverage_class; - ath9k_hw_init_global_settings(priv->ah); - mutex_unlock(&priv->mutex); -} - -struct ieee80211_ops ath9k_htc_ops = { - .tx = ath9k_htc_tx, - .start = ath9k_htc_start, - .stop = ath9k_htc_stop, - .add_interface = ath9k_htc_add_interface, - .remove_interface = ath9k_htc_remove_interface, - .config = ath9k_htc_config, - .configure_filter = ath9k_htc_configure_filter, - .sta_notify = ath9k_htc_sta_notify, - .conf_tx = ath9k_htc_conf_tx, - .bss_info_changed = ath9k_htc_bss_info_changed, - .set_key = ath9k_htc_set_key, - .get_tsf = ath9k_htc_get_tsf, - .set_tsf = ath9k_htc_set_tsf, - .reset_tsf = ath9k_htc_reset_tsf, - .ampdu_action = ath9k_htc_ampdu_action, - .sw_scan_start = ath9k_htc_sw_scan_start, - .sw_scan_complete = ath9k_htc_sw_scan_complete, - .set_rts_threshold = ath9k_htc_set_rts_threshold, - .rfkill_poll = ath9k_htc_rfkill_poll_state, - .set_coverage_class = ath9k_htc_set_coverage_class, -}; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c deleted file mode 100644 index dba22d3f87c3..000000000000 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Copyright (c) 2010 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "htc.h" - -/******/ -/* TX */ -/******/ - -int get_hw_qnum(u16 queue, int *hwq_map) -{ - switch (queue) { - case 0: - return hwq_map[ATH9K_WME_AC_VO]; - case 1: - return hwq_map[ATH9K_WME_AC_VI]; - case 2: - return hwq_map[ATH9K_WME_AC_BE]; - case 3: - return hwq_map[ATH9K_WME_AC_BK]; - default: - return hwq_map[ATH9K_WME_AC_BE]; - } -} - -int ath_txq_update(struct ath9k_htc_priv *priv, int qnum, - struct ath9k_tx_queue_info *qinfo) -{ - struct ath_hw *ah = priv->ah; - int error = 0; - struct ath9k_tx_queue_info qi; - - ath9k_hw_get_txq_props(ah, qnum, &qi); - - qi.tqi_aifs = qinfo->tqi_aifs; - qi.tqi_cwmin = qinfo->tqi_cwmin / 2; /* XXX */ - qi.tqi_cwmax = qinfo->tqi_cwmax; - qi.tqi_burstTime = qinfo->tqi_burstTime; - qi.tqi_readyTime = qinfo->tqi_readyTime; - - if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "Unable to update hardware queue %u!\n", qnum); - error = -EIO; - } else { - ath9k_hw_resettxqueue(ah, qnum); - } - - return error; -} - -int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_sta *sta = tx_info->control.sta; - struct ath9k_htc_sta *ista; - struct ath9k_htc_vif *avp; - struct ath9k_htc_tx_ctl tx_ctl; - enum htc_endpoint_id epid; - u16 qnum, hw_qnum; - __le16 fc; - u8 *tx_fhdr; - u8 sta_idx; - - hdr = (struct ieee80211_hdr *) skb->data; - fc = hdr->frame_control; - - avp = (struct ath9k_htc_vif *) tx_info->control.vif->drv_priv; - if (sta) { - ista = (struct ath9k_htc_sta *) sta->drv_priv; - sta_idx = ista->index; - } else { - sta_idx = 0; - } - - memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); - - if (ieee80211_is_data(fc)) { - struct tx_frame_hdr tx_hdr; - u8 *qc; - - memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); - - tx_hdr.node_idx = sta_idx; - tx_hdr.vif_idx = avp->index; - - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { - tx_ctl.type = ATH9K_HTC_AMPDU; - tx_hdr.data_type = ATH9K_HTC_AMPDU; - } else { - tx_ctl.type = ATH9K_HTC_NORMAL; - tx_hdr.data_type = ATH9K_HTC_NORMAL; - } - - if (ieee80211_is_data(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - } - - /* Check for RTS protection */ - if (priv->hw->wiphy->rts_threshold != (u32) -1) - if (skb->len > priv->hw->wiphy->rts_threshold) - tx_hdr.flags |= ATH9K_HTC_TX_RTSCTS; - - /* CTS-to-self */ - if (!(tx_hdr.flags & ATH9K_HTC_TX_RTSCTS) && - (priv->op_flags & OP_PROTECT_ENABLE)) - tx_hdr.flags |= ATH9K_HTC_TX_CTSONLY; - - tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); - if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) - tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; - else - tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; - - tx_fhdr = skb_push(skb, sizeof(tx_hdr)); - memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); - - qnum = skb_get_queue_mapping(skb); - hw_qnum = get_hw_qnum(qnum, priv->hwq_map); - - switch (hw_qnum) { - case 0: - epid = priv->data_be_ep; - break; - case 2: - epid = priv->data_vi_ep; - break; - case 3: - epid = priv->data_vo_ep; - break; - case 1: - default: - epid = priv->data_bk_ep; - break; - } - } else { - struct tx_mgmt_hdr mgmt_hdr; - - memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); - - tx_ctl.type = ATH9K_HTC_NORMAL; - - mgmt_hdr.node_idx = sta_idx; - mgmt_hdr.vif_idx = avp->index; - mgmt_hdr.tidno = 0; - mgmt_hdr.flags = 0; - - mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); - if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) - mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; - else - mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; - - tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); - memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); - epid = priv->mgmt_ep; - } - - return htc_send(priv->htc, skb, epid, &tx_ctl); -} - -void ath9k_tx_tasklet(unsigned long data) -{ - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; - struct ieee80211_sta *sta; - struct ieee80211_hdr *hdr; - struct ieee80211_tx_info *tx_info; - struct sk_buff *skb = NULL; - __le16 fc; - - while ((skb = skb_dequeue(&priv->tx_queue)) != NULL) { - - hdr = (struct ieee80211_hdr *) skb->data; - fc = hdr->frame_control; - tx_info = IEEE80211_SKB_CB(skb); - sta = tx_info->control.sta; - - rcu_read_lock(); - - if (sta && conf_is_ht(&priv->hw->conf) && - (priv->op_flags & OP_TXAGGR) - && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { - if (ieee80211_is_data_qos(fc)) { - u8 *qc, tid; - struct ath9k_htc_sta *ista; - - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; - ista = (struct ath9k_htc_sta *)sta->drv_priv; - - if ((tid < ATH9K_HTC_MAX_TID) && - ista->tid_state[tid] == AGGR_STOP) { - ieee80211_start_tx_ba_session(sta, tid); - ista->tid_state[tid] = AGGR_PROGRESS; - } - } - } - - rcu_read_unlock(); - - memset(&tx_info->status, 0, sizeof(tx_info->status)); - ieee80211_tx_status(priv->hw, skb); - } -} - -void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, - enum htc_endpoint_id ep_id, bool txok) -{ - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; - struct ieee80211_tx_info *tx_info; - - if (!skb) - return; - - if (ep_id == priv->mgmt_ep) - skb_pull(skb, sizeof(struct tx_mgmt_hdr)); - else - /* TODO: Check for cab/uapsd/data */ - skb_pull(skb, sizeof(struct tx_frame_hdr)); - - tx_info = IEEE80211_SKB_CB(skb); - - if (txok) - tx_info->flags |= IEEE80211_TX_STAT_ACK; - - skb_queue_tail(&priv->tx_queue, skb); - tasklet_schedule(&priv->tx_tasklet); -} - -int ath9k_tx_init(struct ath9k_htc_priv *priv) -{ - skb_queue_head_init(&priv->tx_queue); - return 0; -} - -void ath9k_tx_cleanup(struct ath9k_htc_priv *priv) -{ - -} - -bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, - enum ath9k_tx_queue_subtype subtype) -{ - struct ath_hw *ah = priv->ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_tx_queue_info qi; - int qnum; - - memset(&qi, 0, sizeof(qi)); - - qi.tqi_subtype = subtype; - qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; - qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; - qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; - qi.tqi_physCompBuf = 0; - qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | TXQ_FLAG_TXDESCINT_ENABLE; - - qnum = ath9k_hw_setuptxqueue(priv->ah, ATH9K_TX_QUEUE_DATA, &qi); - if (qnum == -1) - return false; - - if (qnum >= ARRAY_SIZE(priv->hwq_map)) { - ath_print(common, ATH_DBG_FATAL, - "qnum %u out of range, max %u!\n", - qnum, (unsigned int)ARRAY_SIZE(priv->hwq_map)); - ath9k_hw_releasetxqueue(ah, qnum); - return false; - } - - priv->hwq_map[subtype] = qnum; - return true; -} - -/******/ -/* RX */ -/******/ - -void ath9k_host_rx_init(struct ath9k_htc_priv *priv) -{ - ath9k_hw_rxena(priv->ah); - ath9k_cmn_opmode_init(priv->hw, priv->ah, priv->rxfilter); - ath9k_hw_startpcureceive(priv->ah); - priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER; -} - -static void ath9k_process_rate(struct ieee80211_hw *hw, - struct ieee80211_rx_status *rxs, - u8 rx_rate, u8 rs_flags) -{ - struct ieee80211_supported_band *sband; - enum ieee80211_band band; - unsigned int i = 0; - - if (rx_rate & 0x80) { - /* HT rate */ - rxs->flag |= RX_FLAG_HT; - if (rs_flags & ATH9K_RX_2040) - rxs->flag |= RX_FLAG_40MHZ; - if (rs_flags & ATH9K_RX_GI) - rxs->flag |= RX_FLAG_SHORT_GI; - rxs->rate_idx = rx_rate & 0x7f; - return; - } - - band = hw->conf.channel->band; - sband = hw->wiphy->bands[band]; - - for (i = 0; i < sband->n_bitrates; i++) { - if (sband->bitrates[i].hw_value == rx_rate) { - rxs->rate_idx = i; - return; - } - if (sband->bitrates[i].hw_value_short == rx_rate) { - rxs->rate_idx = i; - rxs->flag |= RX_FLAG_SHORTPRE; - return; - } - } - -} - -static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, - struct ath9k_htc_rxbuf *rxbuf, - struct ieee80211_rx_status *rx_status) - -{ - struct ieee80211_hdr *hdr; - struct ieee80211_hw *hw = priv->hw; - struct sk_buff *skb = rxbuf->skb; - struct ath_common *common = ath9k_hw_common(priv->ah); - int hdrlen, padpos, padsize; - int last_rssi = ATH_RSSI_DUMMY_MARKER; - __le16 fc; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - - padpos = ath9k_cmn_padpos(fc); - - padsize = padpos & 3; - if (padsize && skb->len >= padpos+padsize) { - memmove(skb->data + padsize, skb->data, padpos); - skb_pull(skb, padsize); - } - - memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); - - if (rxbuf->rxstatus.rs_status != 0) { - if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_CRC) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_PHY) - goto rx_next; - - if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT) { - /* FIXME */ - } else if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_MIC) { - if (ieee80211_is_ctl(fc)) - /* - * Sometimes, we get invalid - * MIC failures on valid control frames. - * Remove these mic errors. - */ - rxbuf->rxstatus.rs_status &= ~ATH9K_RXERR_MIC; - else - rx_status->flag |= RX_FLAG_MMIC_ERROR; - } - - /* - * Reject error frames with the exception of - * decryption and MIC failures. For monitor mode, - * we also ignore the CRC error. - */ - if (priv->ah->opmode == NL80211_IFTYPE_MONITOR) { - if (rxbuf->rxstatus.rs_status & - ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | - ATH9K_RXERR_CRC)) - goto rx_next; - } else { - if (rxbuf->rxstatus.rs_status & - ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { - goto rx_next; - } - } - } - - if (!(rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT)) { - u8 keyix; - keyix = rxbuf->rxstatus.rs_keyix; - if (keyix != ATH9K_RXKEYIX_INVALID) { - rx_status->flag |= RX_FLAG_DECRYPTED; - } else if (ieee80211_has_protected(fc) && - skb->len >= hdrlen + 4) { - keyix = skb->data[hdrlen + 3] >> 6; - if (test_bit(keyix, common->keymap)) - rx_status->flag |= RX_FLAG_DECRYPTED; - } - } - - ath9k_process_rate(hw, rx_status, rxbuf->rxstatus.rs_rate, - rxbuf->rxstatus.rs_flags); - - if (priv->op_flags & OP_ASSOCIATED) { - if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD && - !rxbuf->rxstatus.rs_moreaggr) - ATH_RSSI_LPF(priv->rx.last_rssi, - rxbuf->rxstatus.rs_rssi); - - last_rssi = priv->rx.last_rssi; - - if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) - rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi, - ATH_RSSI_EP_MULTIPLIER); - - if (rxbuf->rxstatus.rs_rssi < 0) - rxbuf->rxstatus.rs_rssi = 0; - - if (ieee80211_is_beacon(fc)) - priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi; - } - - rx_status->mactime = rxbuf->rxstatus.rs_tstamp; - rx_status->band = hw->conf.channel->band; - rx_status->freq = hw->conf.channel->center_freq; - rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR; - rx_status->antenna = rxbuf->rxstatus.rs_antenna; - rx_status->flag |= RX_FLAG_TSFT; - - return true; - -rx_next: - return false; -} - -/* - * FIXME: Handle FLUSH later on. - */ -void ath9k_rx_tasklet(unsigned long data) -{ - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; - struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; - struct ieee80211_rx_status rx_status; - struct sk_buff *skb; - unsigned long flags; - - - do { - spin_lock_irqsave(&priv->rx.rxbuflock, flags); - list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) { - if (tmp_buf->in_process) { - rxbuf = tmp_buf; - break; - } - } - - if (rxbuf == NULL) { - spin_unlock_irqrestore(&priv->rx.rxbuflock, flags); - break; - } - - if (!rxbuf->skb) - goto requeue; - - if (!ath9k_rx_prepare(priv, rxbuf, &rx_status)) { - dev_kfree_skb_any(rxbuf->skb); - goto requeue; - } - - memcpy(IEEE80211_SKB_RXCB(rxbuf->skb), &rx_status, - sizeof(struct ieee80211_rx_status)); - skb = rxbuf->skb; - spin_unlock_irqrestore(&priv->rx.rxbuflock, flags); - - ieee80211_rx(priv->hw, skb); - - spin_lock_irqsave(&priv->rx.rxbuflock, flags); -requeue: - rxbuf->in_process = false; - rxbuf->skb = NULL; - list_move_tail(&rxbuf->list, &priv->rx.rxbuf); - rxbuf = NULL; - spin_unlock_irqrestore(&priv->rx.rxbuflock, flags); - } while (1); - -} - -void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, - enum htc_endpoint_id ep_id) -{ - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)drv_priv; - struct ath_hw *ah = priv->ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; - struct ath_htc_rx_status *rxstatus; - u32 len = 0; - - spin_lock(&priv->rx.rxbuflock); - list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) { - if (!tmp_buf->in_process) { - rxbuf = tmp_buf; - break; - } - } - spin_unlock(&priv->rx.rxbuflock); - - if (rxbuf == NULL) { - ath_print(common, ATH_DBG_ANY, - "No free RX buffer\n"); - goto err; - } - - len = skb->len; - if (len <= HTC_RX_FRAME_HEADER_SIZE) { - ath_print(common, ATH_DBG_FATAL, - "Corrupted RX frame, dropping\n"); - goto err; - } - - rxstatus = (struct ath_htc_rx_status *)skb->data; - - rxstatus->rs_tstamp = be64_to_cpu(rxstatus->rs_tstamp); - rxstatus->rs_datalen = be16_to_cpu(rxstatus->rs_datalen); - rxstatus->evm0 = be32_to_cpu(rxstatus->evm0); - rxstatus->evm1 = be32_to_cpu(rxstatus->evm1); - rxstatus->evm2 = be32_to_cpu(rxstatus->evm2); - - if (rxstatus->rs_datalen - (len - HTC_RX_FRAME_HEADER_SIZE) != 0) { - ath_print(common, ATH_DBG_FATAL, - "Corrupted RX data len, dropping " - "(epid: %d, dlen: %d, skblen: %d)\n", - ep_id, rxstatus->rs_datalen, len); - goto err; - } - - spin_lock(&priv->rx.rxbuflock); - memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); - skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); - skb->len = rxstatus->rs_datalen; - rxbuf->skb = skb; - rxbuf->in_process = true; - spin_unlock(&priv->rx.rxbuflock); - - tasklet_schedule(&priv->rx_tasklet); - return; -err: - dev_kfree_skb_any(skb); - return; -} - -/* FIXME: Locking for cleanup/init */ - -void ath9k_rx_cleanup(struct ath9k_htc_priv *priv) -{ - struct ath9k_htc_rxbuf *rxbuf, *tbuf; - - list_for_each_entry_safe(rxbuf, tbuf, &priv->rx.rxbuf, list) { - list_del(&rxbuf->list); - if (rxbuf->skb) - dev_kfree_skb_any(rxbuf->skb); - kfree(rxbuf); - } -} - -int ath9k_rx_init(struct ath9k_htc_priv *priv) -{ - struct ath_hw *ah = priv->ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_htc_rxbuf *rxbuf; - int i = 0; - - INIT_LIST_HEAD(&priv->rx.rxbuf); - spin_lock_init(&priv->rx.rxbuflock); - - for (i = 0; i < ATH9K_HTC_RXBUF; i++) { - rxbuf = kzalloc(sizeof(struct ath9k_htc_rxbuf), GFP_KERNEL); - if (rxbuf == NULL) { - ath_print(common, ATH_DBG_FATAL, - "Unable to allocate RX buffers\n"); - goto err; - } - list_add_tail(&rxbuf->list, &priv->rx.rxbuf); - } - - return 0; - -err: - ath9k_rx_cleanup(priv); - return -ENOMEM; -} diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c deleted file mode 100644 index 9a48999d0979..000000000000 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Copyright (c) 2010 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "htc.h" - -static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, - u16 len, u8 flags, u8 epid, - struct ath9k_htc_tx_ctl *tx_ctl) -{ - struct htc_frame_hdr *hdr; - struct htc_endpoint *endpoint = &target->endpoint[epid]; - int status; - - hdr = (struct htc_frame_hdr *) - skb_push(skb, sizeof(struct htc_frame_hdr)); - hdr->endpoint_id = epid; - hdr->flags = flags; - hdr->payload_len = cpu_to_be16(len); - - status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb, - tx_ctl); - return status; -} - -static struct htc_endpoint *get_next_avail_ep(struct htc_endpoint *endpoint) -{ - enum htc_endpoint_id avail_epid; - - for (avail_epid = ENDPOINT_MAX; avail_epid > ENDPOINT0; avail_epid--) - if (endpoint[avail_epid].service_id == 0) - return &endpoint[avail_epid]; - return NULL; -} - -static u8 service_to_ulpipe(u16 service_id) -{ - switch (service_id) { - case WMI_CONTROL_SVC: - return 4; - case WMI_BEACON_SVC: - case WMI_CAB_SVC: - case WMI_UAPSD_SVC: - case WMI_MGMT_SVC: - case WMI_DATA_VO_SVC: - case WMI_DATA_VI_SVC: - case WMI_DATA_BE_SVC: - case WMI_DATA_BK_SVC: - return 1; - default: - return 0; - } -} - -static u8 service_to_dlpipe(u16 service_id) -{ - switch (service_id) { - case WMI_CONTROL_SVC: - return 3; - case WMI_BEACON_SVC: - case WMI_CAB_SVC: - case WMI_UAPSD_SVC: - case WMI_MGMT_SVC: - case WMI_DATA_VO_SVC: - case WMI_DATA_VI_SVC: - case WMI_DATA_BE_SVC: - case WMI_DATA_BK_SVC: - return 2; - default: - return 0; - } -} - -static void htc_process_target_rdy(struct htc_target *target, - void *buf) -{ - struct htc_endpoint *endpoint; - struct htc_ready_msg *htc_ready_msg = (struct htc_ready_msg *) buf; - - target->credits = be16_to_cpu(htc_ready_msg->credits); - target->credit_size = be16_to_cpu(htc_ready_msg->credit_size); - - endpoint = &target->endpoint[ENDPOINT0]; - endpoint->service_id = HTC_CTRL_RSVD_SVC; - endpoint->max_msglen = HTC_MAX_CONTROL_MESSAGE_LENGTH; - complete(&target->target_wait); -} - -static void htc_process_conn_rsp(struct htc_target *target, - struct htc_frame_hdr *htc_hdr) -{ - struct htc_conn_svc_rspmsg *svc_rspmsg; - struct htc_endpoint *endpoint, *tmp_endpoint = NULL; - u16 service_id; - u16 max_msglen; - enum htc_endpoint_id epid, tepid; - - svc_rspmsg = (struct htc_conn_svc_rspmsg *) - ((void *) htc_hdr + sizeof(struct htc_frame_hdr)); - - if (svc_rspmsg->status == HTC_SERVICE_SUCCESS) { - epid = svc_rspmsg->endpoint_id; - service_id = be16_to_cpu(svc_rspmsg->service_id); - max_msglen = be16_to_cpu(svc_rspmsg->max_msg_len); - endpoint = &target->endpoint[epid]; - - for (tepid = ENDPOINT_MAX; tepid > ENDPOINT0; tepid--) { - tmp_endpoint = &target->endpoint[tepid]; - if (tmp_endpoint->service_id == service_id) { - tmp_endpoint->service_id = 0; - break; - } - } - - if (!tmp_endpoint) - return; - - endpoint->service_id = service_id; - endpoint->max_txqdepth = tmp_endpoint->max_txqdepth; - endpoint->ep_callbacks = tmp_endpoint->ep_callbacks; - endpoint->ul_pipeid = tmp_endpoint->ul_pipeid; - endpoint->dl_pipeid = tmp_endpoint->dl_pipeid; - endpoint->max_msglen = max_msglen; - target->conn_rsp_epid = epid; - complete(&target->cmd_wait); - } else { - target->conn_rsp_epid = ENDPOINT_UNUSED; - } -} - -static int htc_config_pipe_credits(struct htc_target *target) -{ - struct sk_buff *skb; - struct htc_config_pipe_msg *cp_msg; - int ret, time_left; - - skb = dev_alloc_skb(50 + sizeof(struct htc_frame_hdr)); - if (!skb) { - dev_err(target->dev, "failed to allocate send buffer\n"); - return -ENOMEM; - } - skb_reserve(skb, sizeof(struct htc_frame_hdr)); - - cp_msg = (struct htc_config_pipe_msg *) - skb_put(skb, sizeof(struct htc_config_pipe_msg)); - - cp_msg->message_id = cpu_to_be16(HTC_MSG_CONFIG_PIPE_ID); - cp_msg->pipe_id = USB_WLAN_TX_PIPE; - cp_msg->credits = 28; - - target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS; - - ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); - if (ret) - goto err; - - time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); - if (!time_left) { - dev_err(target->dev, "HTC credit config timeout\n"); - return -ETIMEDOUT; - } - - return 0; -err: - dev_kfree_skb(skb); - return -EINVAL; -} - -static int htc_setup_complete(struct htc_target *target) -{ - struct sk_buff *skb; - struct htc_comp_msg *comp_msg; - int ret = 0, time_left; - - skb = dev_alloc_skb(50 + sizeof(struct htc_frame_hdr)); - if (!skb) { - dev_err(target->dev, "failed to allocate send buffer\n"); - return -ENOMEM; - } - skb_reserve(skb, sizeof(struct htc_frame_hdr)); - - comp_msg = (struct htc_comp_msg *) - skb_put(skb, sizeof(struct htc_comp_msg)); - comp_msg->msg_id = cpu_to_be16(HTC_MSG_SETUP_COMPLETE_ID); - - target->htc_flags |= HTC_OP_START_WAIT; - - ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); - if (ret) - goto err; - - time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); - if (!time_left) { - dev_err(target->dev, "HTC start timeout\n"); - return -ETIMEDOUT; - } - - return 0; - -err: - dev_kfree_skb(skb); - return -EINVAL; -} - -/* HTC APIs */ - -int htc_init(struct htc_target *target) -{ - int ret; - - ret = htc_config_pipe_credits(target); - if (ret) - return ret; - - return htc_setup_complete(target); -} - -int htc_connect_service(struct htc_target *target, - struct htc_service_connreq *service_connreq, - enum htc_endpoint_id *conn_rsp_epid) -{ - struct sk_buff *skb; - struct htc_endpoint *endpoint; - struct htc_conn_svc_msg *conn_msg; - int ret, time_left; - - /* Find an available endpoint */ - endpoint = get_next_avail_ep(target->endpoint); - if (!endpoint) { - dev_err(target->dev, "Endpoint is not available for" - "service %d\n", service_connreq->service_id); - return -EINVAL; - } - - endpoint->service_id = service_connreq->service_id; - endpoint->max_txqdepth = service_connreq->max_send_qdepth; - endpoint->ul_pipeid = service_to_ulpipe(service_connreq->service_id); - endpoint->dl_pipeid = service_to_dlpipe(service_connreq->service_id); - endpoint->ep_callbacks = service_connreq->ep_callbacks; - - skb = dev_alloc_skb(sizeof(struct htc_conn_svc_msg) + - sizeof(struct htc_frame_hdr)); - if (!skb) { - dev_err(target->dev, "Failed to allocate buf to send" - "service connect req\n"); - return -ENOMEM; - } - - skb_reserve(skb, sizeof(struct htc_frame_hdr)); - - conn_msg = (struct htc_conn_svc_msg *) - skb_put(skb, sizeof(struct htc_conn_svc_msg)); - conn_msg->service_id = cpu_to_be16(service_connreq->service_id); - conn_msg->msg_id = cpu_to_be16(HTC_MSG_CONNECT_SERVICE_ID); - conn_msg->con_flags = cpu_to_be16(service_connreq->con_flags); - conn_msg->dl_pipeid = endpoint->dl_pipeid; - conn_msg->ul_pipeid = endpoint->ul_pipeid; - - ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); - if (ret) - goto err; - - time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); - if (!time_left) { - dev_err(target->dev, "Service connection timeout for: %d\n", - service_connreq->service_id); - return -ETIMEDOUT; - } - - *conn_rsp_epid = target->conn_rsp_epid; - return 0; -err: - dev_kfree_skb(skb); - return ret; -} - -int htc_send(struct htc_target *target, struct sk_buff *skb, - enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl) -{ - return htc_issue_send(target, skb, skb->len, 0, epid, tx_ctl); -} - -void htc_stop(struct htc_target *target) -{ - enum htc_endpoint_id epid; - struct htc_endpoint *endpoint; - - for (epid = ENDPOINT0; epid <= ENDPOINT_MAX; epid++) { - endpoint = &target->endpoint[epid]; - if (endpoint->service_id != 0) - target->hif->stop(target->hif_dev, endpoint->ul_pipeid); - } -} - -void htc_start(struct htc_target *target) -{ - enum htc_endpoint_id epid; - struct htc_endpoint *endpoint; - - for (epid = ENDPOINT0; epid <= ENDPOINT_MAX; epid++) { - endpoint = &target->endpoint[epid]; - if (endpoint->service_id != 0) - target->hif->start(target->hif_dev, - endpoint->ul_pipeid); - } -} - -void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, - struct sk_buff *skb, bool txok) -{ - struct htc_endpoint *endpoint; - struct htc_frame_hdr *htc_hdr; - - if (htc_handle->htc_flags & HTC_OP_CONFIG_PIPE_CREDITS) { - complete(&htc_handle->cmd_wait); - htc_handle->htc_flags &= ~HTC_OP_CONFIG_PIPE_CREDITS; - } - - if (htc_handle->htc_flags & HTC_OP_START_WAIT) { - complete(&htc_handle->cmd_wait); - htc_handle->htc_flags &= ~HTC_OP_START_WAIT; - } - - if (skb) { - htc_hdr = (struct htc_frame_hdr *) skb->data; - endpoint = &htc_handle->endpoint[htc_hdr->endpoint_id]; - skb_pull(skb, sizeof(struct htc_frame_hdr)); - - if (endpoint->ep_callbacks.tx) { - endpoint->ep_callbacks.tx(htc_handle->drv_priv, skb, - htc_hdr->endpoint_id, txok); - } - } -} - -/* - * HTC Messages are handled directly here and the obtained SKB - * is freed. - * - * Sevice messages (Data, WMI) passed to the corresponding - * endpoint RX handlers, which have to free the SKB. - */ -void ath9k_htc_rx_msg(struct htc_target *htc_handle, - struct sk_buff *skb, u32 len, u8 pipe_id) -{ - struct htc_frame_hdr *htc_hdr; - enum htc_endpoint_id epid; - struct htc_endpoint *endpoint; - u16 *msg_id; - - if (!htc_handle || !skb) - return; - - htc_hdr = (struct htc_frame_hdr *) skb->data; - epid = htc_hdr->endpoint_id; - - if (epid >= ENDPOINT_MAX) { - dev_kfree_skb_any(skb); - return; - } - - if (epid == ENDPOINT0) { - - /* Handle trailer */ - if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) { - if (be32_to_cpu(*(u32 *) skb->data) == 0x00C60000) - /* Move past the Watchdog pattern */ - htc_hdr = (struct htc_frame_hdr *) skb->data + 4; - } - - /* Get the message ID */ - msg_id = (u16 *) ((void *) htc_hdr + - sizeof(struct htc_frame_hdr)); - - /* Now process HTC messages */ - switch (be16_to_cpu(*msg_id)) { - case HTC_MSG_READY_ID: - htc_process_target_rdy(htc_handle, htc_hdr); - break; - case HTC_MSG_CONNECT_SERVICE_RESPONSE_ID: - htc_process_conn_rsp(htc_handle, htc_hdr); - break; - default: - break; - } - - dev_kfree_skb_any(skb); - - } else { - if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) - skb_trim(skb, len - htc_hdr->control[0]); - - skb_pull(skb, sizeof(struct htc_frame_hdr)); - - endpoint = &htc_handle->endpoint[epid]; - if (endpoint->ep_callbacks.rx) - endpoint->ep_callbacks.rx(endpoint->ep_callbacks.priv, - skb, epid); - } -} - -struct htc_target *ath9k_htc_hw_alloc(void *hif_handle) -{ - struct htc_target *target; - - target = kzalloc(sizeof(struct htc_target), GFP_KERNEL); - if (!target) - printk(KERN_ERR "Unable to allocate memory for" - "target device\n"); - - return target; -} - -void ath9k_htc_hw_free(struct htc_target *htc) -{ - kfree(htc); -} - -int ath9k_htc_hw_init(struct ath9k_htc_hif *hif, struct htc_target *target, - void *hif_handle, struct device *dev, u16 devid, - enum ath9k_hif_transports transport) -{ - struct htc_endpoint *endpoint; - int err = 0; - - init_completion(&target->target_wait); - init_completion(&target->cmd_wait); - - target->hif = hif; - target->hif_dev = hif_handle; - target->dev = dev; - - /* Assign control endpoint pipe IDs */ - endpoint = &target->endpoint[ENDPOINT0]; - endpoint->ul_pipeid = hif->control_ul_pipe; - endpoint->dl_pipeid = hif->control_dl_pipe; - - err = ath9k_htc_probe_device(target, dev, devid); - if (err) { - printk(KERN_ERR "Failed to initialize the device\n"); - return -ENODEV; - } - - return 0; -} - -void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug) -{ - if (target) - ath9k_htc_disconnect_device(target, hot_unplug); -} diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h deleted file mode 100644 index cd7048ffd239..000000000000 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2010 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef HTC_HST_H -#define HTC_HST_H - -struct ath9k_htc_priv; -struct htc_target; -struct ath9k_htc_tx_ctl; - -enum ath9k_hif_transports { - ATH9K_HIF_USB, -}; - -struct ath9k_htc_hif { - struct list_head list; - const enum ath9k_hif_transports transport; - const char *name; - - u8 control_dl_pipe; - u8 control_ul_pipe; - - void (*start) (void *hif_handle, u8 pipe); - void (*stop) (void *hif_handle, u8 pipe); - int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf, - struct ath9k_htc_tx_ctl *tx_ctl); -}; - -enum htc_endpoint_id { - ENDPOINT_UNUSED = -1, - ENDPOINT0 = 0, - ENDPOINT1 = 1, - ENDPOINT2 = 2, - ENDPOINT3 = 3, - ENDPOINT4 = 4, - ENDPOINT5 = 5, - ENDPOINT6 = 6, - ENDPOINT7 = 7, - ENDPOINT8 = 8, - ENDPOINT_MAX = 22 -}; - -/* Htc frame hdr flags */ -#define HTC_FLAGS_RECV_TRAILER (1 << 1) - -struct htc_frame_hdr { - u8 endpoint_id; - u8 flags; - u16 payload_len; - u8 control[4]; -} __packed; - -struct htc_ready_msg { - u16 message_id; - u16 credits; - u16 credit_size; - u8 max_endpoints; - u8 pad; -} __packed; - -struct htc_config_pipe_msg { - u16 message_id; - u8 pipe_id; - u8 credits; -} __packed; - -struct htc_packet { - void *pktcontext; - u8 *buf; - u8 *buf_payload; - u32 buflen; - u32 payload_len; - - int endpoint; - int status; - - void *context; - u32 reserved; -}; - -struct htc_ep_callbacks { - void *priv; - void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok); - void (*rx) (void *, struct sk_buff *, enum htc_endpoint_id); -}; - -#define HTC_TX_QUEUE_SIZE 256 - -struct htc_txq { - struct sk_buff *buf[HTC_TX_QUEUE_SIZE]; - u32 txqdepth; - u16 txbuf_cnt; - u16 txq_head; - u16 txq_tail; -}; - -struct htc_endpoint { - u16 service_id; - - struct htc_ep_callbacks ep_callbacks; - struct htc_txq htc_txq; - u32 max_txqdepth; - int max_msglen; - - u8 ul_pipeid; - u8 dl_pipeid; -}; - -#define HTC_MAX_CONTROL_MESSAGE_LENGTH 255 -#define HTC_CONTROL_BUFFER_SIZE \ - (HTC_MAX_CONTROL_MESSAGE_LENGTH + sizeof(struct htc_frame_hdr)) - -#define NUM_CONTROL_BUFFERS 8 -#define HST_ENDPOINT_MAX 8 - -struct htc_control_buf { - struct htc_packet htc_pkt; - u8 buf[HTC_CONTROL_BUFFER_SIZE]; -}; - -#define HTC_OP_START_WAIT BIT(0) -#define HTC_OP_CONFIG_PIPE_CREDITS BIT(1) - -struct htc_target { - void *hif_dev; - struct ath9k_htc_priv *drv_priv; - struct device *dev; - struct ath9k_htc_hif *hif; - struct htc_endpoint endpoint[HST_ENDPOINT_MAX]; - struct completion target_wait; - struct completion cmd_wait; - struct list_head list; - enum htc_endpoint_id conn_rsp_epid; - u16 credits; - u16 credit_size; - u8 htc_flags; -}; - -enum htc_msg_id { - HTC_MSG_READY_ID = 1, - HTC_MSG_CONNECT_SERVICE_ID, - HTC_MSG_CONNECT_SERVICE_RESPONSE_ID, - HTC_MSG_SETUP_COMPLETE_ID, - HTC_MSG_CONFIG_PIPE_ID, - HTC_MSG_CONFIG_PIPE_RESPONSE_ID, -}; - -struct htc_service_connreq { - u16 service_id; - u16 con_flags; - u32 max_send_qdepth; - struct htc_ep_callbacks ep_callbacks; -}; - -/* Current service IDs */ - -enum htc_service_group_ids{ - RSVD_SERVICE_GROUP = 0, - WMI_SERVICE_GROUP = 1, - - HTC_SERVICE_GROUP_LAST = 255 -}; - -#define MAKE_SERVICE_ID(group, index) \ - (int)(((int)group << 8) | (int)(index)) - -/* NOTE: service ID of 0x0000 is reserved and should never be used */ -#define HTC_CTRL_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP, 1) -#define HTC_LOOPBACK_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP, 2) - -#define WMI_CONTROL_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 0) -#define WMI_BEACON_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 1) -#define WMI_CAB_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 2) -#define WMI_UAPSD_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 3) -#define WMI_MGMT_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 4) -#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 5) -#define WMI_DATA_VI_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 6) -#define WMI_DATA_BE_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 7) -#define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 8) - -struct htc_conn_svc_msg { - u16 msg_id; - u16 service_id; - u16 con_flags; - u8 dl_pipeid; - u8 ul_pipeid; - u8 svc_meta_len; - u8 pad; -} __packed; - -/* connect response status codes */ -#define HTC_SERVICE_SUCCESS 0 -#define HTC_SERVICE_NOT_FOUND 1 -#define HTC_SERVICE_FAILED 2 -#define HTC_SERVICE_NO_RESOURCES 3 -#define HTC_SERVICE_NO_MORE_EP 4 - -struct htc_conn_svc_rspmsg { - u16 msg_id; - u16 service_id; - u8 status; - u8 endpoint_id; - u16 max_msg_len; - u8 svc_meta_len; - u8 pad; -} __packed; - -struct htc_comp_msg { - u16 msg_id; -} __packed; - -int htc_init(struct htc_target *target); -int htc_connect_service(struct htc_target *target, - struct htc_service_connreq *service_connreq, - enum htc_endpoint_id *conn_rsp_eid); -int htc_send(struct htc_target *target, struct sk_buff *skb, - enum htc_endpoint_id eid, struct ath9k_htc_tx_ctl *tx_ctl); -void htc_stop(struct htc_target *target); -void htc_start(struct htc_target *target); - -void ath9k_htc_rx_msg(struct htc_target *htc_handle, - struct sk_buff *skb, u32 len, u8 pipe_id); -void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, - struct sk_buff *skb, bool txok); - -struct htc_target *ath9k_htc_hw_alloc(void *hif_handle); -void ath9k_htc_hw_free(struct htc_target *htc); -int ath9k_htc_hw_init(struct ath9k_htc_hif *hif, struct htc_target *target, - void *hif_handle, struct device *dev, u16 devid, - enum ath9k_hif_transports transport); -void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug); - -#endif /* HTC_HST_H */ diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index a5e543bd2271..29851e6376a9 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -150,32 +150,6 @@ struct ath_rx_status { u32 evm2; }; -struct ath_htc_rx_status { - u64 rs_tstamp; - u16 rs_datalen; - u8 rs_status; - u8 rs_phyerr; - int8_t rs_rssi; - int8_t rs_rssi_ctl0; - int8_t rs_rssi_ctl1; - int8_t rs_rssi_ctl2; - int8_t rs_rssi_ext0; - int8_t rs_rssi_ext1; - int8_t rs_rssi_ext2; - u8 rs_keyix; - u8 rs_rate; - u8 rs_antenna; - u8 rs_more; - u8 rs_isaggr; - u8 rs_moreaggr; - u8 rs_num_delims; - u8 rs_flags; - u8 rs_dummy; - u32 evm0; - u32 evm1; - u32 evm2; -}; - #define ATH9K_RXERR_CRC 0x01 #define ATH9K_RXERR_PHY 0x02 #define ATH9K_RXERR_FIFO 0x04 diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c deleted file mode 100644 index 818dea0164ec..000000000000 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (c) 2010 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "htc.h" - -static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) -{ - switch (wmi_cmd) { - case WMI_ECHO_CMDID: - return "WMI_ECHO_CMDID"; - case WMI_ACCESS_MEMORY_CMDID: - return "WMI_ACCESS_MEMORY_CMDID"; - case WMI_DISABLE_INTR_CMDID: - return "WMI_DISABLE_INTR_CMDID"; - case WMI_ENABLE_INTR_CMDID: - return "WMI_ENABLE_INTR_CMDID"; - case WMI_RX_LINK_CMDID: - return "WMI_RX_LINK_CMDID"; - case WMI_ATH_INIT_CMDID: - return "WMI_ATH_INIT_CMDID"; - case WMI_ABORT_TXQ_CMDID: - return "WMI_ABORT_TXQ_CMDID"; - case WMI_STOP_TX_DMA_CMDID: - return "WMI_STOP_TX_DMA_CMDID"; - case WMI_STOP_DMA_RECV_CMDID: - return "WMI_STOP_DMA_RECV_CMDID"; - case WMI_ABORT_TX_DMA_CMDID: - return "WMI_ABORT_TX_DMA_CMDID"; - case WMI_DRAIN_TXQ_CMDID: - return "WMI_DRAIN_TXQ_CMDID"; - case WMI_DRAIN_TXQ_ALL_CMDID: - return "WMI_DRAIN_TXQ_ALL_CMDID"; - case WMI_START_RECV_CMDID: - return "WMI_START_RECV_CMDID"; - case WMI_STOP_RECV_CMDID: - return "WMI_STOP_RECV_CMDID"; - case WMI_FLUSH_RECV_CMDID: - return "WMI_FLUSH_RECV_CMDID"; - case WMI_SET_MODE_CMDID: - return "WMI_SET_MODE_CMDID"; - case WMI_RESET_CMDID: - return "WMI_RESET_CMDID"; - case WMI_NODE_CREATE_CMDID: - return "WMI_NODE_CREATE_CMDID"; - case WMI_NODE_REMOVE_CMDID: - return "WMI_NODE_REMOVE_CMDID"; - case WMI_VAP_REMOVE_CMDID: - return "WMI_VAP_REMOVE_CMDID"; - case WMI_VAP_CREATE_CMDID: - return "WMI_VAP_CREATE_CMDID"; - case WMI_BEACON_UPDATE_CMDID: - return "WMI_BEACON_UPDATE_CMDID"; - case WMI_REG_READ_CMDID: - return "WMI_REG_READ_CMDID"; - case WMI_REG_WRITE_CMDID: - return "WMI_REG_WRITE_CMDID"; - case WMI_RC_STATE_CHANGE_CMDID: - return "WMI_RC_STATE_CHANGE_CMDID"; - case WMI_RC_RATE_UPDATE_CMDID: - return "WMI_RC_RATE_UPDATE_CMDID"; - case WMI_DEBUG_INFO_CMDID: - return "WMI_DEBUG_INFO_CMDID"; - case WMI_HOST_ATTACH: - return "WMI_HOST_ATTACH"; - case WMI_TARGET_IC_UPDATE_CMDID: - return "WMI_TARGET_IC_UPDATE_CMDID"; - case WMI_TGT_STATS_CMDID: - return "WMI_TGT_STATS_CMDID"; - case WMI_TX_AGGR_ENABLE_CMDID: - return "WMI_TX_AGGR_ENABLE_CMDID"; - case WMI_TGT_DETACH_CMDID: - return "WMI_TGT_DETACH_CMDID"; - case WMI_TGT_TXQ_ENABLE_CMDID: - return "WMI_TGT_TXQ_ENABLE_CMDID"; - } - - return "Bogus"; -} - -struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv) -{ - struct wmi *wmi; - - wmi = kzalloc(sizeof(struct wmi), GFP_KERNEL); - if (!wmi) - return NULL; - - wmi->drv_priv = priv; - wmi->stopped = false; - mutex_init(&wmi->op_mutex); - init_completion(&wmi->cmd_wait); - - return wmi; -} - -void ath9k_deinit_wmi(struct ath9k_htc_priv *priv) -{ - struct wmi *wmi = priv->wmi; - - mutex_lock(&wmi->op_mutex); - wmi->stopped = true; - mutex_unlock(&wmi->op_mutex); - - kfree(priv->wmi); -} - -void ath9k_wmi_tasklet(unsigned long data) -{ - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; - struct ath_common *common = ath9k_hw_common(priv->ah); - struct wmi_cmd_hdr *hdr; - struct wmi_swba *swba_hdr; - enum wmi_event_id event; - struct sk_buff *skb; - void *wmi_event; - unsigned long flags; -#ifdef CONFIG_ATH9K_HTC_DEBUGFS - u32 txrate; -#endif - - spin_lock_irqsave(&priv->wmi->wmi_lock, flags); - skb = priv->wmi->wmi_skb; - spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); - - hdr = (struct wmi_cmd_hdr *) skb->data; - event = be16_to_cpu(hdr->command_id); - wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); - - ath_print(common, ATH_DBG_WMI, - "WMI Event: 0x%x\n", event); - - switch (event) { - case WMI_TGT_RDY_EVENTID: - break; - case WMI_SWBA_EVENTID: - swba_hdr = (struct wmi_swba *) wmi_event; - ath9k_htc_swba(priv, swba_hdr->beacon_pending); - break; - case WMI_FATAL_EVENTID: - break; - case WMI_TXTO_EVENTID: - break; - case WMI_BMISS_EVENTID: - break; - case WMI_WLAN_TXCOMP_EVENTID: - break; - case WMI_DELBA_EVENTID: - break; - case WMI_TXRATE_EVENTID: -#ifdef CONFIG_ATH9K_HTC_DEBUGFS - txrate = ((struct wmi_event_txrate *)wmi_event)->txrate; - priv->debug.txrate = be32_to_cpu(txrate); -#endif - break; - default: - break; - } - - dev_kfree_skb_any(skb); -} - -static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) -{ - skb_pull(skb, sizeof(struct wmi_cmd_hdr)); - - if (wmi->cmd_rsp_buf != NULL && wmi->cmd_rsp_len != 0) - memcpy(wmi->cmd_rsp_buf, skb->data, wmi->cmd_rsp_len); - - complete(&wmi->cmd_wait); -} - -static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, - enum htc_endpoint_id epid) -{ - struct wmi *wmi = (struct wmi *) priv; - struct wmi_cmd_hdr *hdr; - u16 cmd_id; - - if (unlikely(wmi->stopped)) - goto free_skb; - - hdr = (struct wmi_cmd_hdr *) skb->data; - cmd_id = be16_to_cpu(hdr->command_id); - - if (cmd_id & 0x1000) { - spin_lock(&wmi->wmi_lock); - wmi->wmi_skb = skb; - spin_unlock(&wmi->wmi_lock); - tasklet_schedule(&wmi->drv_priv->wmi_tasklet); - return; - } - - /* WMI command response */ - ath9k_wmi_rsp_callback(wmi, skb); - -free_skb: - dev_kfree_skb_any(skb); -} - -static void ath9k_wmi_ctrl_tx(void *priv, struct sk_buff *skb, - enum htc_endpoint_id epid, bool txok) -{ - dev_kfree_skb_any(skb); -} - -int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi, - enum htc_endpoint_id *wmi_ctrl_epid) -{ - struct htc_service_connreq connect; - int ret; - - wmi->htc = htc; - - memset(&connect, 0, sizeof(connect)); - - connect.ep_callbacks.priv = wmi; - connect.ep_callbacks.tx = ath9k_wmi_ctrl_tx; - connect.ep_callbacks.rx = ath9k_wmi_ctrl_rx; - connect.service_id = WMI_CONTROL_SVC; - - ret = htc_connect_service(htc, &connect, &wmi->ctrl_epid); - if (ret) - return ret; - - *wmi_ctrl_epid = wmi->ctrl_epid; - - return 0; -} - -static int ath9k_wmi_cmd_issue(struct wmi *wmi, - struct sk_buff *skb, - enum wmi_cmd_id cmd, u16 len) -{ - struct wmi_cmd_hdr *hdr; - - hdr = (struct wmi_cmd_hdr *) skb_push(skb, sizeof(struct wmi_cmd_hdr)); - hdr->command_id = cpu_to_be16(cmd); - hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id); - - return htc_send(wmi->htc, skb, wmi->ctrl_epid, NULL); -} - -int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, - u8 *cmd_buf, u32 cmd_len, - u8 *rsp_buf, u32 rsp_len, - u32 timeout) -{ - struct ath_hw *ah = wmi->drv_priv->ah; - struct ath_common *common = ath9k_hw_common(ah); - u16 headroom = sizeof(struct htc_frame_hdr) + - sizeof(struct wmi_cmd_hdr); - struct sk_buff *skb; - u8 *data; - int time_left, ret = 0; - - if (!wmi) - return -EINVAL; - - skb = dev_alloc_skb(headroom + cmd_len); - if (!skb) - return -ENOMEM; - - skb_reserve(skb, headroom); - - if (cmd_len != 0 && cmd_buf != NULL) { - data = (u8 *) skb_put(skb, cmd_len); - memcpy(data, cmd_buf, cmd_len); - } - - mutex_lock(&wmi->op_mutex); - - /* check if wmi stopped flag is set */ - if (unlikely(wmi->stopped)) { - ret = -EPROTO; - goto out; - } - - /* record the rsp buffer and length */ - wmi->cmd_rsp_buf = rsp_buf; - wmi->cmd_rsp_len = rsp_len; - - ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len); - if (ret) - goto out; - - time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout); - if (!time_left) { - ath_print(common, ATH_DBG_WMI, - "Timeout waiting for WMI command: %s\n", - wmi_cmd_to_name(cmd_id)); - mutex_unlock(&wmi->op_mutex); - return -ETIMEDOUT; - } - - mutex_unlock(&wmi->op_mutex); - - return 0; - -out: - ath_print(common, ATH_DBG_WMI, - "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id)); - mutex_unlock(&wmi->op_mutex); - dev_kfree_skb_any(skb); - - return ret; -} diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h deleted file mode 100644 index 39ef926f27c2..000000000000 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2010 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef WMI_H -#define WMI_H - - -struct wmi_event_txrate { - u32 txrate; - struct { - u8 rssi_thresh; - u8 per; - } rc_stats; -} __packed; - -struct wmi_cmd_hdr { - u16 command_id; - u16 seq_no; -} __packed; - -struct wmi_swba { - u8 beacon_pending; -} __packed; - -enum wmi_cmd_id { - WMI_ECHO_CMDID = 0x0001, - WMI_ACCESS_MEMORY_CMDID, - - /* Commands to Target */ - WMI_DISABLE_INTR_CMDID, - WMI_ENABLE_INTR_CMDID, - WMI_RX_LINK_CMDID, - WMI_ATH_INIT_CMDID, - WMI_ABORT_TXQ_CMDID, - WMI_STOP_TX_DMA_CMDID, - WMI_STOP_DMA_RECV_CMDID, - WMI_ABORT_TX_DMA_CMDID, - WMI_DRAIN_TXQ_CMDID, - WMI_DRAIN_TXQ_ALL_CMDID, - WMI_START_RECV_CMDID, - WMI_STOP_RECV_CMDID, - WMI_FLUSH_RECV_CMDID, - WMI_SET_MODE_CMDID, - WMI_RESET_CMDID, - WMI_NODE_CREATE_CMDID, - WMI_NODE_REMOVE_CMDID, - WMI_VAP_REMOVE_CMDID, - WMI_VAP_CREATE_CMDID, - WMI_BEACON_UPDATE_CMDID, - WMI_REG_READ_CMDID, - WMI_REG_WRITE_CMDID, - WMI_RC_STATE_CHANGE_CMDID, - WMI_RC_RATE_UPDATE_CMDID, - WMI_DEBUG_INFO_CMDID, - WMI_HOST_ATTACH, - WMI_TARGET_IC_UPDATE_CMDID, - WMI_TGT_STATS_CMDID, - WMI_TX_AGGR_ENABLE_CMDID, - WMI_TGT_DETACH_CMDID, - WMI_TGT_TXQ_ENABLE_CMDID, -}; - -enum wmi_event_id { - WMI_TGT_RDY_EVENTID = 0x1001, - WMI_SWBA_EVENTID, - WMI_FATAL_EVENTID, - WMI_TXTO_EVENTID, - WMI_BMISS_EVENTID, - WMI_WLAN_TXCOMP_EVENTID, - WMI_DELBA_EVENTID, - WMI_TXRATE_EVENTID, -}; - -struct wmi { - struct ath9k_htc_priv *drv_priv; - struct htc_target *htc; - enum htc_endpoint_id ctrl_epid; - struct mutex op_mutex; - struct completion cmd_wait; - u16 tx_seq_id; - u8 *cmd_rsp_buf; - u32 cmd_rsp_len; - bool stopped; - - struct sk_buff *wmi_skb; - spinlock_t wmi_lock; -}; - -struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv); -void ath9k_deinit_wmi(struct ath9k_htc_priv *priv); -int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi, - enum htc_endpoint_id *wmi_ctrl_epid); -int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, - u8 *cmd_buf, u32 cmd_len, - u8 *rsp_buf, u32 rsp_len, - u32 timeout); -void ath9k_wmi_tasklet(unsigned long data); - -#define WMI_CMD(_wmi_cmd) \ - do { \ - ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, NULL, 0, \ - (u8 *) &cmd_rsp, \ - sizeof(cmd_rsp), HZ); \ - } while (0) - -#define WMI_CMD_BUF(_wmi_cmd, _buf) \ - do { \ - ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, \ - (u8 *) _buf, sizeof(*_buf), \ - &cmd_rsp, sizeof(cmd_rsp), HZ); \ - } while (0) - -#endif /* WMI_H */ diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h index 873bf526e11f..8263633c003c 100644 --- a/drivers/net/wireless/ath/debug.h +++ b/drivers/net/wireless/ath/debug.h @@ -59,7 +59,6 @@ enum ATH_DEBUG { ATH_DBG_PS = 0x00000800, ATH_DBG_HWTIMER = 0x00001000, ATH_DBG_BTCOEX = 0x00002000, - ATH_DBG_WMI = 0x00004000, ATH_DBG_ANY = 0xffffffff }; |