Commit 7905e357 authored by David S. Miller's avatar David S. Miller
parents 083ba279 76232ebf
...@@ -2279,26 +2279,25 @@ void gelic_wl_interrupt(struct net_device *netdev, u64 status) ...@@ -2279,26 +2279,25 @@ void gelic_wl_interrupt(struct net_device *netdev, u64 status)
/* /*
* driver helpers * driver helpers
*/ */
#define IW_IOCTL(n) [(n) - SIOCSIWCOMMIT]
static const iw_handler gelic_wl_wext_handler[] = static const iw_handler gelic_wl_wext_handler[] =
{ {
IW_IOCTL(SIOCGIWNAME) = gelic_wl_get_name, IW_HANDLER(SIOCGIWNAME, gelic_wl_get_name),
IW_IOCTL(SIOCGIWRANGE) = gelic_wl_get_range, IW_HANDLER(SIOCGIWRANGE, gelic_wl_get_range),
IW_IOCTL(SIOCSIWSCAN) = gelic_wl_set_scan, IW_HANDLER(SIOCSIWSCAN, gelic_wl_set_scan),
IW_IOCTL(SIOCGIWSCAN) = gelic_wl_get_scan, IW_HANDLER(SIOCGIWSCAN, gelic_wl_get_scan),
IW_IOCTL(SIOCSIWAUTH) = gelic_wl_set_auth, IW_HANDLER(SIOCSIWAUTH, gelic_wl_set_auth),
IW_IOCTL(SIOCGIWAUTH) = gelic_wl_get_auth, IW_HANDLER(SIOCGIWAUTH, gelic_wl_get_auth),
IW_IOCTL(SIOCSIWESSID) = gelic_wl_set_essid, IW_HANDLER(SIOCSIWESSID, gelic_wl_set_essid),
IW_IOCTL(SIOCGIWESSID) = gelic_wl_get_essid, IW_HANDLER(SIOCGIWESSID, gelic_wl_get_essid),
IW_IOCTL(SIOCSIWENCODE) = gelic_wl_set_encode, IW_HANDLER(SIOCSIWENCODE, gelic_wl_set_encode),
IW_IOCTL(SIOCGIWENCODE) = gelic_wl_get_encode, IW_HANDLER(SIOCGIWENCODE, gelic_wl_get_encode),
IW_IOCTL(SIOCSIWAP) = gelic_wl_set_ap, IW_HANDLER(SIOCSIWAP, gelic_wl_set_ap),
IW_IOCTL(SIOCGIWAP) = gelic_wl_get_ap, IW_HANDLER(SIOCGIWAP, gelic_wl_get_ap),
IW_IOCTL(SIOCSIWENCODEEXT) = gelic_wl_set_encodeext, IW_HANDLER(SIOCSIWENCODEEXT, gelic_wl_set_encodeext),
IW_IOCTL(SIOCGIWENCODEEXT) = gelic_wl_get_encodeext, IW_HANDLER(SIOCGIWENCODEEXT, gelic_wl_get_encodeext),
IW_IOCTL(SIOCSIWMODE) = gelic_wl_set_mode, IW_HANDLER(SIOCSIWMODE, gelic_wl_set_mode),
IW_IOCTL(SIOCGIWMODE) = gelic_wl_get_mode, IW_HANDLER(SIOCGIWMODE, gelic_wl_get_mode),
IW_IOCTL(SIOCGIWNICKN) = gelic_wl_get_nick, IW_HANDLER(SIOCGIWNICKN, gelic_wl_get_nick),
}; };
static const struct iw_handler_def gelic_wl_wext_handler_def = { static const struct iw_handler_def gelic_wl_wext_handler_def = {
......
...@@ -3,7 +3,7 @@ menuconfig ATH_COMMON ...@@ -3,7 +3,7 @@ menuconfig ATH_COMMON
depends on CFG80211 depends on CFG80211
---help--- ---help---
This will enable the support for the Atheros wireless drivers. This will enable the support for the Atheros wireless drivers.
ath5k, ath9k and ar9170 drivers share some common code, this option ath5k, ath9k, ath9k_htc and ar9170 drivers share some common code, this option
enables the common ath.ko module which shares common helpers. enables the common ath.ko module which shares common helpers.
For more information and documentation on this module you can visit: For more information and documentation on this module you can visit:
......
...@@ -32,3 +32,24 @@ config ATH9K_DEBUGFS ...@@ -32,3 +32,24 @@ config ATH9K_DEBUGFS
Also required for changing debug message flags at run time. 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.
...@@ -28,3 +28,13 @@ obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o ...@@ -28,3 +28,13 @@ obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o
obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o
ath9k_common-y:= 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
...@@ -101,9 +101,13 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, ...@@ -101,9 +101,13 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah,
nf = 0 - ((nf ^ 0x1ff) + 1); nf = 0 - ((nf ^ 0x1ff) + 1);
ath_print(common, ATH_DBG_CALIBRATE, ath_print(common, ATH_DBG_CALIBRATE,
"NF calibrated [ctl] [chain 0] is %d\n", nf); "NF calibrated [ctl] [chain 0] is %d\n", nf);
if (AR_SREV_9271(ah) && (nf >= -114))
nf = -116;
nfarray[0] = nf; nfarray[0] = nf;
if (!AR_SREV_9285(ah)) { if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) {
if (AR_SREV_9280_10_OR_LATER(ah)) if (AR_SREV_9280_10_OR_LATER(ah))
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
AR9280_PHY_CH1_MINCCA_PWR); AR9280_PHY_CH1_MINCCA_PWR);
...@@ -139,9 +143,13 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, ...@@ -139,9 +143,13 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah,
nf = 0 - ((nf ^ 0x1ff) + 1); nf = 0 - ((nf ^ 0x1ff) + 1);
ath_print(common, ATH_DBG_CALIBRATE, ath_print(common, ATH_DBG_CALIBRATE,
"NF calibrated [ext] [chain 0] is %d\n", nf); "NF calibrated [ext] [chain 0] is %d\n", nf);
if (AR_SREV_9271(ah) && (nf >= -114))
nf = -116;
nfarray[3] = nf; nfarray[3] = nf;
if (!AR_SREV_9285(ah)) { if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) {
if (AR_SREV_9280_10_OR_LATER(ah)) if (AR_SREV_9280_10_OR_LATER(ah))
nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
AR9280_PHY_CH1_EXT_MINCCA_PWR); AR9280_PHY_CH1_EXT_MINCCA_PWR);
...@@ -621,7 +629,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) ...@@ -621,7 +629,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
u8 chainmask, rx_chain_status; u8 chainmask, rx_chain_status;
rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK);
if (AR_SREV_9285(ah)) if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
chainmask = 0x9; chainmask = 0x9;
else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) {
if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4))
...@@ -715,7 +723,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) ...@@ -715,7 +723,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah)
if (AR_SREV_9280(ah)) if (AR_SREV_9280(ah))
noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE;
else if (AR_SREV_9285(ah)) else if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE;
else if (AR_SREV_9287(ah)) else if (AR_SREV_9287(ah))
noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE; noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE;
...@@ -1051,9 +1059,12 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, ...@@ -1051,9 +1059,12 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
/* Do NF cal only at longer intervals */ /* Do NF cal only at longer intervals */
if (longcal) { if (longcal) {
/* Do periodic PAOffset Cal */ /* Do periodic PAOffset Cal */
if (AR_SREV_9271(ah)) if (AR_SREV_9271(ah)) {
ath9k_hw_9271_pa_cal(ah, false); if (!ah->pacal_info.skipcount)
else if (AR_SREV_9285_11_OR_LATER(ah)) { ath9k_hw_9271_pa_cal(ah, false);
else
ah->pacal_info.skipcount--;
} else if (AR_SREV_9285_11_OR_LATER(ah)) {
if (!ah->pacal_info.skipcount) if (!ah->pacal_info.skipcount)
ath9k_hw_9285_pa_cal(ah, false); ath9k_hw_9285_pa_cal(ah, false);
else else
......
This diff is collapsed.
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
/* Common header for Atheros 802.11n base driver cores */ /* Common header for Atheros 802.11n base driver cores */
#define IEEE80211_WEP_NKID 4
#define WME_NUM_TID 16 #define WME_NUM_TID 16
#define WME_BA_BMP_SIZE 64 #define WME_BA_BMP_SIZE 64
#define WME_MAX_BA WME_BA_BMP_SIZE #define WME_MAX_BA WME_BA_BMP_SIZE
...@@ -125,3 +127,18 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, ...@@ -125,3 +127,18 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
bool decrypt_error); bool decrypt_error);
int ath9k_cmn_padpos(__le16 frame_control); 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);
This diff is collapsed.
/*
* 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 */
This diff is collapsed.
/*
* 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;
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* 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 */
This diff is collapsed.
This diff is collapsed.
...@@ -758,6 +758,9 @@ static void ath9k_deinit_softc(struct ath_softc *sc) ...@@ -758,6 +758,9 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
tasklet_kill(&sc->intr_tq); tasklet_kill(&sc->intr_tq);
tasklet_kill(&sc->bcon_tasklet); tasklet_kill(&sc->bcon_tasklet);
kfree(sc->sc_ah);
sc->sc_ah = NULL;
} }
void ath9k_deinit_device(struct ath_softc *sc) void ath9k_deinit_device(struct ath_softc *sc)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -59,6 +59,7 @@ enum ATH_DEBUG { ...@@ -59,6 +59,7 @@ enum ATH_DEBUG {
ATH_DBG_PS = 0x00000800, ATH_DBG_PS = 0x00000800,
ATH_DBG_HWTIMER = 0x00001000, ATH_DBG_HWTIMER = 0x00001000,
ATH_DBG_BTCOEX = 0x00002000, ATH_DBG_BTCOEX = 0x00002000,
ATH_DBG_WMI = 0x00004000,
ATH_DBG_ANY = 0xffffffff ATH_DBG_ANY = 0xffffffff
}; };
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment