提交 01a28298 编写于 作者: J John W. Linville

Merge branch 'master' of...

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem

Conflicts:
	drivers/net/wireless/ath/ath9k/hw.c
#
# This outlines the Linux authentication/association and
# deauthentication/disassociation flows.
#
# This can be converted into a diagram using the service
# at http://www.websequencediagrams.com/
#
participant userspace
participant mac80211
participant driver
alt authentication needed (not FT)
userspace->mac80211: authenticate
alt authenticated/authenticating already
mac80211->driver: sta_state(AP, not-exists)
mac80211->driver: bss_info_changed(clear BSSID)
else associated
note over mac80211,driver
like deauth/disassoc, without sending the
BA session stop & deauth/disassoc frames
end note
end
mac80211->driver: config(channel, non-HT)
mac80211->driver: bss_info_changed(set BSSID, basic rate bitmap)
mac80211->driver: sta_state(AP, exists)
alt no probe request data known
mac80211->driver: TX directed probe request
driver->mac80211: RX probe response
end
mac80211->driver: TX auth frame
driver->mac80211: RX auth frame
alt WEP shared key auth
mac80211->driver: TX auth frame
driver->mac80211: RX auth frame
end
mac80211->driver: sta_state(AP, authenticated)
mac80211->userspace: RX auth frame
end
userspace->mac80211: associate
alt authenticated or associated
note over mac80211,driver: cleanup like for authenticate
end
alt not previously authenticated (FT)
mac80211->driver: config(channel, non-HT)
mac80211->driver: bss_info_changed(set BSSID, basic rate bitmap)
mac80211->driver: sta_state(AP, exists)
mac80211->driver: sta_state(AP, authenticated)
end
mac80211->driver: TX assoc
driver->mac80211: RX assoc response
note over mac80211: init rate control
mac80211->driver: sta_state(AP, associated)
alt not using WPA
mac80211->driver: sta_state(AP, authorized)
end
mac80211->driver: set up QoS parameters
alt is HT channel
mac80211->driver: config(channel, HT params)
end
mac80211->driver: bss_info_changed(QoS, HT, associated with AID)
mac80211->userspace: associated
note left of userspace: associated now
alt using WPA
note over userspace
do 4-way-handshake
(data frames)
end note
userspace->mac80211: authorized
mac80211->driver: sta_state(AP, authorized)
end
userspace->mac80211: deauthenticate/disassociate
mac80211->driver: stop BA sessions
mac80211->driver: TX deauth/disassoc
mac80211->driver: flush frames
mac80211->driver: sta_state(AP,associated)
mac80211->driver: sta_state(AP,authenticated)
mac80211->driver: sta_state(AP,exists)
mac80211->driver: sta_state(AP,not-exists)
mac80211->driver: turn off powersave
mac80211->driver: bss_info_changed(clear BSSID, not associated, no QoS, ...)
mac80211->driver: config(non-HT channel type)
mac80211->userspace: disconnected
......@@ -174,28 +174,24 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry);
void ath_hw_cycle_counters_update(struct ath_common *common);
int32_t ath_hw_get_listen_time(struct ath_common *common);
extern __printf(2, 3) void ath_printk(const char *level, const char *fmt, ...);
#define _ath_printk(level, common, fmt, ...) \
do { \
__always_unused struct ath_common *unused = common; \
ath_printk(level, fmt, ##__VA_ARGS__); \
} while (0)
__printf(3, 4)
void ath_printk(const char *level, const struct ath_common *common,
const char *fmt, ...);
#define ath_emerg(common, fmt, ...) \
_ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__)
ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__)
#define ath_alert(common, fmt, ...) \
_ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__)
ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__)
#define ath_crit(common, fmt, ...) \
_ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__)
ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__)
#define ath_err(common, fmt, ...) \
_ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__)
ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__)
#define ath_warn(common, fmt, ...) \
_ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__)
ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__)
#define ath_notice(common, fmt, ...) \
_ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__)
ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__)
#define ath_info(common, fmt, ...) \
_ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__)
ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__)
/**
* enum ath_debug_level - atheros wireless debug level
......@@ -256,7 +252,7 @@ enum ATH_DEBUG {
#define ath_dbg(common, dbg_mask, fmt, ...) \
do { \
if ((common)->debug_mask & ATH_DBG_##dbg_mask) \
_ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__); \
ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__); \
} while (0)
#define ATH_DBG_WARN(foo, arg...) WARN(foo, arg)
......
#------------------------------------------------------------------------------
# Copyright (c) 2004-2010 Atheros Communications Inc.
# Copyright (c) 2004-2011 Atheros Communications Inc.
# Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
# All rights reserved.
#
#
......
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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
......@@ -105,7 +106,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
}
ath6kl_dbg(ATH6KL_DBG_BMI, "target info (ver: 0x%x type: 0x%x)\n",
targ_info->version, targ_info->type);
targ_info->version, targ_info->type);
return 0;
}
......@@ -192,7 +193,7 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
memset(ar->bmi.cmd_buf, 0, ar->bmi.max_data_size + header);
ath6kl_dbg(ATH6KL_DBG_BMI,
"bmi write memory: addr: 0x%x, len: %d\n", addr, len);
"bmi write memory: addr: 0x%x, len: %d\n", addr, len);
len_remain = len;
while (len_remain) {
......@@ -434,7 +435,7 @@ int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len)
memcpy(&(ar->bmi.cmd_buf[offset]), &tx_len, sizeof(tx_len));
offset += sizeof(tx_len);
memcpy(&(ar->bmi.cmd_buf[offset]), &buf[len - len_remain],
tx_len);
tx_len);
offset += tx_len;
ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset);
......
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011 Qualcomm Atheros, 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
......@@ -222,6 +223,29 @@ struct ath6kl_bmi_target_info {
__le32 type; /* target type */
} __packed;
#define ath6kl_bmi_write_hi32(ar, item, val) \
({ \
u32 addr; \
__le32 v; \
\
addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item)); \
v = cpu_to_le32(val); \
ath6kl_bmi_write(ar, addr, (u8 *) &v, sizeof(v)); \
})
#define ath6kl_bmi_read_hi32(ar, item, val) \
({ \
u32 addr, *check_type = val; \
__le32 tmp; \
int ret; \
\
(void) (check_type == val); \
addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item)); \
ret = ath6kl_bmi_read(ar, addr, (u8 *) &tmp, 4); \
*val = le32_to_cpu(tmp); \
ret; \
})
int ath6kl_bmi_init(struct ath6kl *ar);
void ath6kl_bmi_cleanup(struct ath6kl *ar);
void ath6kl_bmi_reset(struct ath6kl *ar);
......
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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
......@@ -68,6 +69,10 @@ static struct ieee80211_rate ath6kl_rates[] = {
#define ath6kl_g_rates (ath6kl_rates + 0)
#define ath6kl_g_rates_size 12
#define ath6kl_g_htcap (IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \
IEEE80211_HT_CAP_SGI_20 | \
IEEE80211_HT_CAP_SGI_40)
static struct ieee80211_channel ath6kl_2ghz_channels[] = {
CHAN2G(1, 2412, 0),
CHAN2G(2, 2417, 0),
......@@ -112,6 +117,8 @@ static struct ieee80211_supported_band ath6kl_band_2ghz = {
.channels = ath6kl_2ghz_channels,
.n_bitrates = ath6kl_g_rates_size,
.bitrates = ath6kl_g_rates,
.ht_cap.cap = ath6kl_g_htcap,
.ht_cap.ht_supported = true,
};
static struct ieee80211_supported_band ath6kl_band_5ghz = {
......@@ -119,6 +126,8 @@ static struct ieee80211_supported_band ath6kl_band_5ghz = {
.channels = ath6kl_5ghz_a_channels,
.n_bitrates = ath6kl_a_rates_size,
.bitrates = ath6kl_a_rates,
.ht_cap.cap = ath6kl_g_htcap,
.ht_cap.ht_supported = true,
};
#define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */
......@@ -381,7 +390,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
return false;
if (ar->ibss_if_active || ((type == NL80211_IFTYPE_ADHOC) &&
ar->num_vif))
ar->num_vif))
return false;
if (type == NL80211_IFTYPE_STATION ||
......@@ -407,6 +416,12 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
return false;
}
static bool ath6kl_is_tx_pending(struct ath6kl *ar)
{
return ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0;
}
static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_connect_params *sme)
{
......@@ -414,6 +429,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
struct ath6kl_vif *vif = netdev_priv(dev);
int status;
u8 nw_subtype = (ar->p2p) ? SUBTYPE_P2PDEV : SUBTYPE_NONE;
u16 interval;
ath6kl_cfg80211_sscan_disable(vif);
......@@ -450,8 +466,8 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
* sleep until the command queue drains
*/
wait_event_interruptible_timeout(ar->event_wq,
ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0,
WMI_TIMEOUT);
ath6kl_is_tx_pending(ar),
WMI_TIMEOUT);
if (signal_pending(current)) {
ath6kl_err("cmd queue drain timeout\n");
up(&ar->sem);
......@@ -546,7 +562,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
if (!ar->usr_bss_filter) {
clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
if (ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
ALL_BSS_FILTER, 0) != 0) {
ALL_BSS_FILTER, 0) != 0) {
ath6kl_err("couldn't set bss filtering\n");
up(&ar->sem);
return -EIO;
......@@ -568,6 +584,20 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
vif->grp_crypto_len, vif->ch_hint);
vif->reconnect_flag = 0;
if (vif->nw_type == INFRA_NETWORK) {
interval = max_t(u16, vif->listen_intvl_t,
ATH6KL_MAX_WOW_LISTEN_INTL);
status = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
interval,
0);
if (status) {
ath6kl_err("couldn't set listen intervel\n");
up(&ar->sem);
return status;
}
}
status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
vif->dot11_auth_mode, vif->auth_mode,
vif->prwise_crypto,
......@@ -590,8 +620,8 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
}
if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) &&
((vif->auth_mode == WPA_PSK_AUTH)
|| (vif->auth_mode == WPA2_PSK_AUTH))) {
((vif->auth_mode == WPA_PSK_AUTH) ||
(vif->auth_mode == WPA2_PSK_AUTH))) {
mod_timer(&vif->disconnect_timer,
jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL));
}
......@@ -824,13 +854,13 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
if (vif->sme_state == SME_CONNECTING) {
cfg80211_connect_result(vif->ndev,
bssid, NULL, 0,
NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
bssid, NULL, 0,
NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
} else if (vif->sme_state == SME_CONNECTED) {
cfg80211_disconnected(vif->ndev, reason,
NULL, 0, GFP_KERNEL);
NULL, 0, GFP_KERNEL);
}
vif->sme_state = SME_DISCONNECTED;
......@@ -876,19 +906,14 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
request->ssids[i].ssid);
}
/*
* FIXME: we should clear the IE in fw if it's not set so just
* remove the check altogether
*/
if (request->ie) {
ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
WMI_FRAME_PROBE_REQ,
request->ie, request->ie_len);
if (ret) {
ath6kl_err("failed to set Probe Request appie for "
"scan");
return ret;
}
/* this also clears IE in fw if it's not set */
ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
WMI_FRAME_PROBE_REQ,
request->ie, request->ie_len);
if (ret) {
ath6kl_err("failed to set Probe Request appie for "
"scan");
return ret;
}
/*
......@@ -917,7 +942,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
force_fg_scan = 1;
if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
ar->fw_capabilities)) {
ar->fw_capabilities)) {
/*
* If capable of doing P2P mgmt operations using
* station interface, send additional information like
......@@ -926,14 +951,17 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
*/
ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
WMI_LONG_SCAN, force_fg_scan,
false, 0, 0, n_channels,
channels, request->no_cck,
false, 0,
ATH6KL_FG_SCAN_INTERVAL,
n_channels, channels,
request->no_cck,
request->rates);
} else {
ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx,
WMI_LONG_SCAN, force_fg_scan,
false, 0, 0, n_channels,
channels);
false, 0,
ATH6KL_FG_SCAN_INTERVAL,
n_channels, channels);
}
if (ret)
ath6kl_err("wmi_startscan_cmd failed\n");
......@@ -1046,9 +1074,9 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
return -ENOTSUPP;
}
if (((vif->auth_mode == WPA_PSK_AUTH)
|| (vif->auth_mode == WPA2_PSK_AUTH))
&& (key_usage & GROUP_USAGE))
if (((vif->auth_mode == WPA_PSK_AUTH) ||
(vif->auth_mode == WPA2_PSK_AUTH)) &&
(key_usage & GROUP_USAGE))
del_timer(&vif->disconnect_timer);
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
......@@ -1058,7 +1086,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
if (vif->nw_type == AP_NETWORK && !pairwise &&
(key_type == TKIP_CRYPT || key_type == AES_CRYPT ||
key_type == WAPI_CRYPT) && params) {
key_type == WAPI_CRYPT)) {
ar->ap_mode_bkey.valid = true;
ar->ap_mode_bkey.key_index = key_index;
ar->ap_mode_bkey.key_type = key_type;
......@@ -1263,7 +1291,6 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
{
struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
struct ath6kl_vif *vif;
u8 ath6kl_dbm;
int dbm = MBM_TO_DBM(mbm);
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
......@@ -1280,7 +1307,7 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
case NL80211_TX_POWER_AUTOMATIC:
return 0;
case NL80211_TX_POWER_LIMITED:
ar->tx_pwr = ath6kl_dbm = dbm;
ar->tx_pwr = dbm;
break;
default:
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n",
......@@ -1288,7 +1315,7 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
return -EOPNOTSUPP;
}
ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx, ath6kl_dbm);
ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx, dbm);
return 0;
}
......@@ -1349,7 +1376,7 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
}
if (ath6kl_wmi_powermode_cmd(ar->wmi, vif->fw_vif_idx,
mode.pwr_mode) != 0) {
mode.pwr_mode) != 0) {
ath6kl_err("wmi_powermode_cmd failed\n");
return -EIO;
}
......@@ -1904,7 +1931,7 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
struct ath6kl_vif *vif;
int ret, left;
u32 filter = 0;
u16 i;
u16 i, bmiss_time;
u8 index = 0;
__be32 ips[MAX_IP_ADDRS];
......@@ -1941,6 +1968,34 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
if (ret)
return ret;
netif_stop_queue(vif->ndev);
if (vif->nw_type != AP_NETWORK) {
ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
ATH6KL_MAX_WOW_LISTEN_INTL,
0);
if (ret)
return ret;
/* Set listen interval x 15 times as bmiss time */
bmiss_time = ATH6KL_MAX_WOW_LISTEN_INTL * 15;
if (bmiss_time > ATH6KL_MAX_BMISS_TIME)
bmiss_time = ATH6KL_MAX_BMISS_TIME;
ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
bmiss_time, 0);
if (ret)
return ret;
ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
0xFFFF, 0, 0xFFFF, 0, 0, 0,
0, 0, 0, 0);
if (ret)
return ret;
}
ar->state = ATH6KL_STATE_SUSPENDING;
/* Setup own IP addr for ARP agent. */
in_dev = __in_dev_get_rtnl(vif->ndev);
if (!in_dev)
......@@ -2019,15 +2074,46 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
if (!vif)
return -EIO;
ar->state = ATH6KL_STATE_RESUMING;
ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
ATH6KL_HOST_MODE_AWAKE);
return ret;
if (ret) {
ath6kl_warn("Failed to configure host sleep mode for "
"wow resume: %d\n", ret);
ar->state = ATH6KL_STATE_WOW;
return ret;
}
if (vif->nw_type != AP_NETWORK) {
ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
if (ret)
return ret;
ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
vif->listen_intvl_t, 0);
if (ret)
return ret;
ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
vif->bmiss_time_t, 0);
if (ret)
return ret;
}
ar->state = ATH6KL_STATE_ON;
netif_wake_queue(vif->ndev);
return 0;
}
int ath6kl_cfg80211_suspend(struct ath6kl *ar,
enum ath6kl_cfg_suspend_mode mode,
struct cfg80211_wowlan *wow)
{
enum ath6kl_state prev_state;
int ret;
switch (mode) {
......@@ -2038,11 +2124,14 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
/* Flush all non control pkts in TX path */
ath6kl_tx_data_cleanup(ar);
prev_state = ar->state;
ret = ath6kl_wow_suspend(ar, wow);
if (ret) {
ath6kl_err("wow suspend failed: %d\n", ret);
ar->state = prev_state;
return ret;
}
ar->state = ATH6KL_STATE_WOW;
break;
......@@ -2114,7 +2203,6 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
return ret;
}
ar->state = ATH6KL_STATE_ON;
break;
case ATH6KL_STATE_DEEPSLEEP:
......@@ -2188,6 +2276,9 @@ static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
*/
void ath6kl_check_wow_status(struct ath6kl *ar)
{
if (ar->state == ATH6KL_STATE_SUSPENDING)
return;
if (ar->state == ATH6KL_STATE_WOW)
ath6kl_cfg80211_resume(ar);
}
......@@ -2275,30 +2366,27 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif,
struct ath6kl *ar = vif->ar;
int res;
if (info->beacon_ies) {
res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
WMI_FRAME_BEACON,
info->beacon_ies,
info->beacon_ies_len);
if (res)
return res;
}
/* this also clears IE in fw if it's not set */
res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
WMI_FRAME_BEACON,
info->beacon_ies,
info->beacon_ies_len);
if (res)
return res;
if (info->proberesp_ies) {
res = ath6kl_set_ap_probe_resp_ies(vif, info->proberesp_ies,
info->proberesp_ies_len);
if (res)
return res;
}
/* this also clears IE in fw if it's not set */
res = ath6kl_set_ap_probe_resp_ies(vif, info->proberesp_ies,
info->proberesp_ies_len);
if (res)
return res;
if (info->assocresp_ies) {
res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
WMI_FRAME_ASSOC_RESP,
info->assocresp_ies,
info->assocresp_ies_len);
if (res)
return res;
}
/* this also clears IE in fw if it's not set */
res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
WMI_FRAME_ASSOC_RESP,
info->assocresp_ies,
info->assocresp_ies_len);
if (res)
return res;
return 0;
}
......@@ -2309,6 +2397,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev);
struct ieee80211_mgmt *mgmt;
bool hidden = false;
u8 *ies;
int ies_len;
struct wmi_connect_cmd p;
......@@ -2345,7 +2434,11 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
memcpy(vif->ssid, info->ssid, info->ssid_len);
vif->ssid_len = info->ssid_len;
if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
return -EOPNOTSUPP; /* TODO */
hidden = true;
res = ath6kl_wmi_ap_hidden_ssid(ar->wmi, vif->fw_vif_idx, hidden);
if (res)
return res;
ret = ath6kl_set_auth_type(vif, info->auth_type);
if (ret)
......@@ -2584,6 +2677,76 @@ static int ath6kl_send_go_probe_resp(struct ath6kl_vif *vif,
return ret;
}
static bool ath6kl_mgmt_powersave_ap(struct ath6kl_vif *vif,
u32 id,
u32 freq,
u32 wait,
const u8 *buf,
size_t len,
bool *more_data,
bool no_cck)
{
struct ieee80211_mgmt *mgmt;
struct ath6kl_sta *conn;
bool is_psq_empty = false;
struct ath6kl_mgmt_buff *mgmt_buf;
size_t mgmt_buf_size;
struct ath6kl *ar = vif->ar;
mgmt = (struct ieee80211_mgmt *) buf;
if (is_multicast_ether_addr(mgmt->da))
return false;
conn = ath6kl_find_sta(vif, mgmt->da);
if (!conn)
return false;
if (conn->sta_flags & STA_PS_SLEEP) {
if (!(conn->sta_flags & STA_PS_POLLED)) {
/* Queue the frames if the STA is sleeping */
mgmt_buf_size = len + sizeof(struct ath6kl_mgmt_buff);
mgmt_buf = kmalloc(mgmt_buf_size, GFP_KERNEL);
if (!mgmt_buf)
return false;
INIT_LIST_HEAD(&mgmt_buf->list);
mgmt_buf->id = id;
mgmt_buf->freq = freq;
mgmt_buf->wait = wait;
mgmt_buf->len = len;
mgmt_buf->no_cck = no_cck;
memcpy(mgmt_buf->buf, buf, len);
spin_lock_bh(&conn->psq_lock);
is_psq_empty = skb_queue_empty(&conn->psq) &&
(conn->mgmt_psq_len == 0);
list_add_tail(&mgmt_buf->list, &conn->mgmt_psq);
conn->mgmt_psq_len++;
spin_unlock_bh(&conn->psq_lock);
/*
* If this is the first pkt getting queued
* for this STA, update the PVB for this
* STA.
*/
if (is_psq_empty)
ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx,
conn->aid, 1);
return true;
}
/*
* This tx is because of a PsPoll.
* Determine if MoreData bit has to be set.
*/
spin_lock_bh(&conn->psq_lock);
if (!skb_queue_empty(&conn->psq) || (conn->mgmt_psq_len != 0))
*more_data = true;
spin_unlock_bh(&conn->psq_lock);
}
return false;
}
static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type,
......@@ -2595,6 +2758,7 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
struct ath6kl_vif *vif = netdev_priv(dev);
u32 id;
const struct ieee80211_mgmt *mgmt;
bool more_data, queued;
mgmt = (const struct ieee80211_mgmt *) buf;
if (buf + len >= mgmt->u.probe_resp.variable &&
......@@ -2620,22 +2784,19 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
*cookie = id;
if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
ar->fw_capabilities)) {
/*
* If capable of doing P2P mgmt operations using
* station interface, send additional information like
* supported rates to advertise and xmit rates for
* probe requests
*/
return ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx, id,
chan->center_freq, wait,
buf, len, no_cck);
} else {
return ath6kl_wmi_send_action_cmd(ar->wmi, vif->fw_vif_idx, id,
chan->center_freq, wait,
buf, len);
/* AP mode Power saving processing */
if (vif->nw_type == AP_NETWORK) {
queued = ath6kl_mgmt_powersave_ap(vif,
id, chan->center_freq,
wait, buf,
len, &more_data, no_cck);
if (queued)
return 0;
}
return ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx, id,
chan->center_freq, wait,
buf, len, no_cck);
}
static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
......@@ -2929,7 +3090,10 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
vif->wdev.netdev = ndev;
vif->wdev.iftype = type;
vif->fw_vif_idx = fw_vif_idx;
vif->nw_type = vif->next_mode = nw_type;
vif->nw_type = nw_type;
vif->next_mode = nw_type;
vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
if (fw_vif_idx != 0)
......@@ -3009,18 +3173,36 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
wiphy->max_sched_scan_ssids = 10;
ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
WIPHY_FLAG_HAVE_AP_SME |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities))
ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
ar->wiphy->probe_resp_offload =
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U;
ret = wiphy_register(wiphy);
if (ret < 0) {
ath6kl_err("couldn't register wiphy device\n");
return ret;
}
ar->wiphy_registered = true;
return 0;
}
void ath6kl_cfg80211_cleanup(struct ath6kl *ar)
{
wiphy_unregister(ar->wiphy);
ar->wiphy_registered = false;
}
struct ath6kl *ath6kl_cfg80211_create(void)
......
/*
* Copyright (c) 2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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 (c) 2010-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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 (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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
......@@ -26,12 +27,14 @@
unsigned int debug_mask;
static unsigned int suspend_mode;
static unsigned int wow_mode;
static unsigned int uart_debug;
static unsigned int ath6kl_p2p;
static unsigned int testmode;
module_param(debug_mask, uint, 0644);
module_param(suspend_mode, uint, 0644);
module_param(wow_mode, uint, 0644);
module_param(uart_debug, uint, 0644);
module_param(ath6kl_p2p, uint, 0644);
module_param(testmode, uint, 0644);
......@@ -97,48 +100,12 @@ int ath6kl_core_init(struct ath6kl *ar)
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi);
ret = ath6kl_cfg80211_init(ar);
if (ret)
goto err_node_cleanup;
ret = ath6kl_debug_init(ar);
if (ret) {
wiphy_unregister(ar->wiphy);
goto err_node_cleanup;
}
for (i = 0; i < ar->vif_max; i++)
ar->avail_idx_map |= BIT(i);
rtnl_lock();
/* Add an initial station interface */
ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0,
INFRA_NETWORK);
rtnl_unlock();
if (!ndev) {
ath6kl_err("Failed to instantiate a network device\n");
ret = -ENOMEM;
wiphy_unregister(ar->wiphy);
goto err_debug_init;
}
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
__func__, ndev->name, ndev, ar);
/* setup access class priority mappings */
ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */
ar->ac_stream_pri_map[WMM_AC_BE] = 1;
ar->ac_stream_pri_map[WMM_AC_VI] = 2;
ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */
/* give our connected endpoints some buffers */
ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep);
ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]);
/* allocate some buffers that handle larger AMSDU frames */
ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS);
......@@ -148,32 +115,25 @@ int ath6kl_core_init(struct ath6kl *ar)
ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
if (suspend_mode &&
suspend_mode >= WLAN_POWER_STATE_CUT_PWR &&
suspend_mode <= WLAN_POWER_STATE_WOW)
suspend_mode >= WLAN_POWER_STATE_CUT_PWR &&
suspend_mode <= WLAN_POWER_STATE_WOW)
ar->suspend_mode = suspend_mode;
else
ar->suspend_mode = 0;
if (suspend_mode == WLAN_POWER_STATE_WOW &&
(wow_mode == WLAN_POWER_STATE_CUT_PWR ||
wow_mode == WLAN_POWER_STATE_DEEP_SLEEP))
ar->wow_suspend_mode = wow_mode;
else
ar->wow_suspend_mode = 0;
if (uart_debug)
ar->conf_flags |= ATH6KL_CONF_UART_DEBUG;
ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
WIPHY_FLAG_HAVE_AP_SME |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities))
ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
ar->wiphy->probe_resp_offload =
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U;
set_bit(FIRST_BOOT, &ar->flag);
ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
ath6kl_debug_init(ar);
ret = ath6kl_init_hw_start(ar);
if (ret) {
......@@ -181,24 +141,47 @@ int ath6kl_core_init(struct ath6kl *ar)
goto err_rxbuf_cleanup;
}
/*
* Set mac address which is received in ready event
* FIXME: Move to ath6kl_interface_add()
*/
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
/* give our connected endpoints some buffers */
ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep);
ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]);
ret = ath6kl_cfg80211_init(ar);
if (ret)
goto err_rxbuf_cleanup;
ret = ath6kl_debug_init_fs(ar);
if (ret) {
wiphy_unregister(ar->wiphy);
goto err_rxbuf_cleanup;
}
for (i = 0; i < ar->vif_max; i++)
ar->avail_idx_map |= BIT(i);
rtnl_lock();
/* Add an initial station interface */
ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0,
INFRA_NETWORK);
rtnl_unlock();
if (!ndev) {
ath6kl_err("Failed to instantiate a network device\n");
ret = -ENOMEM;
wiphy_unregister(ar->wiphy);
goto err_rxbuf_cleanup;
}
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
__func__, ndev->name, ndev, ar);
return ret;
err_rxbuf_cleanup:
ath6kl_debug_cleanup(ar);
ath6kl_htc_flush_rx_buf(ar->htc_target);
ath6kl_cleanup_amsdu_rxbufs(ar);
rtnl_lock();
ath6kl_cfg80211_vif_cleanup(netdev_priv(ndev));
rtnl_unlock();
wiphy_unregister(ar->wiphy);
err_debug_init:
ath6kl_debug_cleanup(ar);
err_node_cleanup:
ath6kl_wmi_shutdown(ar->wmi);
clear_bit(WMI_ENABLED, &ar->flag);
ar->wmi = NULL;
......@@ -245,9 +228,7 @@ struct ath6kl *ath6kl_core_create(struct device *dev)
clear_bit(SKIP_SCAN, &ar->flag);
clear_bit(DESTROY_IN_PROGRESS, &ar->flag);
ar->listen_intvl_b = A_DEFAULT_LISTEN_INTERVAL;
ar->tx_pwr = 0;
ar->intra_bss = 1;
ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD;
......@@ -261,6 +242,8 @@ struct ath6kl *ath6kl_core_create(struct device *dev)
spin_lock_init(&ar->sta_list[ctr].psq_lock);
skb_queue_head_init(&ar->sta_list[ctr].psq);
skb_queue_head_init(&ar->sta_list[ctr].apsdq);
ar->sta_list[ctr].mgmt_psq_len = 0;
INIT_LIST_HEAD(&ar->sta_list[ctr].mgmt_psq);
ar->sta_list[ctr].aggr_conn =
kzalloc(sizeof(struct aggr_info_conn), GFP_KERNEL);
if (!ar->sta_list[ctr].aggr_conn) {
......
/*
* Copyright (c) 2010-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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
......@@ -59,8 +60,9 @@
#define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC)
#define DISCON_TIMER_INTVAL 10000 /* in msec */
#define A_DEFAULT_LISTEN_INTERVAL 1 /* beacon intervals */
#define A_MAX_WOW_LISTEN_INTERVAL 1000
/* Channel dwell time in fg scan */
#define ATH6KL_FG_SCAN_INTERVAL 50 /* in ms */
/* includes also the null byte */
#define ATH6KL_FIRMWARE_MAGIC "QCA-ATH6KL"
......@@ -183,6 +185,11 @@ struct ath6kl_fw_ie {
#define MBOX_YIELD_LIMIT 99
#define ATH6KL_DEFAULT_LISTEN_INTVAL 100 /* in TUs */
#define ATH6KL_DEFAULT_BMISS_TIME 1500
#define ATH6KL_MAX_WOW_LISTEN_INTL 300 /* in TUs */
#define ATH6KL_MAX_BMISS_TIME 5000
/* configuration lags */
/*
* ATH6KL_CONF_IGNORE_ERP_BARKER: Ignore the barker premable in
......@@ -226,6 +233,12 @@ struct rxtid {
u32 hold_q_sz;
struct skb_hold_q *hold_q;
struct sk_buff_head q;
/*
* FIXME: No clue what this should protect. Apparently it should
* protect some of the fields above but they are also accessed
* without taking the lock.
*/
spinlock_t lock;
};
......@@ -285,6 +298,16 @@ struct ath6kl_cookie {
struct ath6kl_cookie *arc_list_next;
};
struct ath6kl_mgmt_buff {
struct list_head list;
u32 freq;
u32 wait;
u32 id;
bool no_cck;
size_t len;
u8 buf[0];
};
struct ath6kl_sta {
u16 sta_flags;
u8 mac[ETH_ALEN];
......@@ -294,7 +317,12 @@ struct ath6kl_sta {
u8 auth;
u8 wpa_ie[ATH6KL_MAX_IE];
struct sk_buff_head psq;
/* protects psq, mgmt_psq, apsdq, and mgmt_psq_len fields */
spinlock_t psq_lock;
struct list_head mgmt_psq;
size_t mgmt_psq_len;
u8 apsd_info;
struct sk_buff_head apsdq;
struct aggr_info_conn *aggr_conn;
......@@ -494,6 +522,8 @@ struct ath6kl_vif {
bool probe_req_report;
u16 next_chan;
u16 assoc_bss_beacon_int;
u16 listen_intvl_t;
u16 bmiss_time_t;
u8 assoc_bss_dtim_period;
struct net_device_stats net_stats;
struct target_stats target_stats;
......@@ -521,6 +551,8 @@ enum ath6kl_dev_state {
enum ath6kl_state {
ATH6KL_STATE_OFF,
ATH6KL_STATE_ON,
ATH6KL_STATE_SUSPENDING,
ATH6KL_STATE_RESUMING,
ATH6KL_STATE_DEEPSLEEP,
ATH6KL_STATE_CUTPOWER,
ATH6KL_STATE_WOW,
......@@ -549,9 +581,14 @@ struct ath6kl {
unsigned int vif_max;
u8 max_norm_iface;
u8 avail_idx_map;
/*
* Protects at least amsdu_rx_buffer_queue, ath6kl_alloc_cookie()
* calls, tx_pending and total_tx_data_pend.
*/
spinlock_t lock;
struct semaphore sem;
u16 listen_intvl_b;
u8 lrssi_roam_threshold;
struct ath6kl_version version;
u32 target_type;
......@@ -577,7 +614,13 @@ struct ath6kl {
u8 sta_list_index;
struct ath6kl_req_key ap_mode_bkey;
struct sk_buff_head mcastpsq;
/*
* FIXME: protects access to mcastpsq but is actually useless as
* all skbe_queue_*() functions provide serialisation themselves
*/
spinlock_t mcastpsq_lock;
u8 intra_bss;
struct wmi_ap_mode_stat ap_stats;
u8 ap_country_code[3];
......@@ -620,6 +663,7 @@ struct ath6kl {
u16 conf_flags;
u16 suspend_mode;
u16 wow_suspend_mode;
wait_queue_head_t event_wq;
struct ath6kl_mbox_info mbox_info;
......@@ -650,12 +694,16 @@ struct ath6kl {
bool p2p;
bool wiphy_registered;
#ifdef CONFIG_ATH6KL_DEBUG
struct {
struct circ_buf fwlog_buf;
spinlock_t fwlog_lock;
void *fwlog_tmp;
struct sk_buff_head fwlog_queue;
struct completion fwlog_completion;
bool fwlog_open;
u32 fwlog_mask;
unsigned int dbgfs_diag_reg;
u32 diag_reg_addr_wr;
u32 diag_reg_val_wr;
......@@ -727,10 +775,10 @@ struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target,
void aggr_module_destroy(struct aggr_info *aggr_info);
void aggr_reset_state(struct aggr_info_conn *aggr_conn);
struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 * node_addr);
struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 *node_addr);
struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid);
void ath6kl_ready_event(void *devt, u8 * datap, u32 sw_ver, u32 abi_ver);
void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver);
int ath6kl_control_tx(void *devt, struct sk_buff *skb,
enum htc_endpoint_id eid);
void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel,
......
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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
......@@ -16,7 +17,7 @@
#include "core.h"
#include <linux/circ_buf.h>
#include <linux/skbuff.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/export.h>
......@@ -32,9 +33,8 @@ struct ath6kl_fwlog_slot {
u8 payload[0];
};
#define ATH6KL_FWLOG_SIZE 32768
#define ATH6KL_FWLOG_SLOT_SIZE (sizeof(struct ath6kl_fwlog_slot) + \
ATH6KL_FWLOG_PAYLOAD_SIZE)
#define ATH6KL_FWLOG_MAX_ENTRIES 20
#define ATH6KL_FWLOG_VALID_MASK 0x1ffff
int ath6kl_printk(const char *level, const char *fmt, ...)
......@@ -119,29 +119,29 @@ void ath6kl_dump_registers(struct ath6kl_device *dev,
if (irq_proc_reg != NULL) {
ath6kl_dbg(ATH6KL_DBG_IRQ,
"Host Int status: 0x%x\n",
irq_proc_reg->host_int_status);
"Host Int status: 0x%x\n",
irq_proc_reg->host_int_status);
ath6kl_dbg(ATH6KL_DBG_IRQ,
"CPU Int status: 0x%x\n",
irq_proc_reg->cpu_int_status);
irq_proc_reg->cpu_int_status);
ath6kl_dbg(ATH6KL_DBG_IRQ,
"Error Int status: 0x%x\n",
irq_proc_reg->error_int_status);
irq_proc_reg->error_int_status);
ath6kl_dbg(ATH6KL_DBG_IRQ,
"Counter Int status: 0x%x\n",
irq_proc_reg->counter_int_status);
irq_proc_reg->counter_int_status);
ath6kl_dbg(ATH6KL_DBG_IRQ,
"Mbox Frame: 0x%x\n",
irq_proc_reg->mbox_frame);
irq_proc_reg->mbox_frame);
ath6kl_dbg(ATH6KL_DBG_IRQ,
"Rx Lookahead Valid: 0x%x\n",
irq_proc_reg->rx_lkahd_valid);
irq_proc_reg->rx_lkahd_valid);
ath6kl_dbg(ATH6KL_DBG_IRQ,
"Rx Lookahead 0: 0x%x\n",
irq_proc_reg->rx_lkahd[0]);
irq_proc_reg->rx_lkahd[0]);
ath6kl_dbg(ATH6KL_DBG_IRQ,
"Rx Lookahead 1: 0x%x\n",
irq_proc_reg->rx_lkahd[1]);
irq_proc_reg->rx_lkahd[1]);
if (dev->ar->mbox_info.gmbox_addr != 0) {
/*
......@@ -149,27 +149,27 @@ void ath6kl_dump_registers(struct ath6kl_device *dev,
* additional state.
*/
ath6kl_dbg(ATH6KL_DBG_IRQ,
"GMBOX Host Int status 2: 0x%x\n",
irq_proc_reg->host_int_status2);
"GMBOX Host Int status 2: 0x%x\n",
irq_proc_reg->host_int_status2);
ath6kl_dbg(ATH6KL_DBG_IRQ,
"GMBOX RX Avail: 0x%x\n",
irq_proc_reg->gmbox_rx_avail);
"GMBOX RX Avail: 0x%x\n",
irq_proc_reg->gmbox_rx_avail);
ath6kl_dbg(ATH6KL_DBG_IRQ,
"GMBOX lookahead alias 0: 0x%x\n",
irq_proc_reg->rx_gmbox_lkahd_alias[0]);
"GMBOX lookahead alias 0: 0x%x\n",
irq_proc_reg->rx_gmbox_lkahd_alias[0]);
ath6kl_dbg(ATH6KL_DBG_IRQ,
"GMBOX lookahead alias 1: 0x%x\n",
irq_proc_reg->rx_gmbox_lkahd_alias[1]);
"GMBOX lookahead alias 1: 0x%x\n",
irq_proc_reg->rx_gmbox_lkahd_alias[1]);
}
}
if (irq_enable_reg != NULL) {
ath6kl_dbg(ATH6KL_DBG_IRQ,
"Int status Enable: 0x%x\n",
irq_enable_reg->int_status_en);
"Int status Enable: 0x%x\n",
irq_enable_reg->int_status_en);
ath6kl_dbg(ATH6KL_DBG_IRQ, "Counter Int status Enable: 0x%x\n",
irq_enable_reg->cntr_int_status_en);
irq_enable_reg->cntr_int_status_en);
}
ath6kl_dbg(ATH6KL_DBG_IRQ, "<------------------------------->\n");
}
......@@ -268,105 +268,103 @@ static const struct file_operations fops_war_stats = {
.llseek = default_llseek,
};
static void ath6kl_debug_fwlog_add(struct ath6kl *ar, const void *buf,
size_t buf_len)
void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len)
{
struct circ_buf *fwlog = &ar->debug.fwlog_buf;
size_t space;
int i;
struct ath6kl_fwlog_slot *slot;
struct sk_buff *skb;
size_t slot_len;
/* entries must all be equal size */
if (WARN_ON(buf_len != ATH6KL_FWLOG_SLOT_SIZE))
if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE))
return;
space = CIRC_SPACE(fwlog->head, fwlog->tail, ATH6KL_FWLOG_SIZE);
if (space < buf_len)
/* discard oldest slot */
fwlog->tail = (fwlog->tail + ATH6KL_FWLOG_SLOT_SIZE) &
(ATH6KL_FWLOG_SIZE - 1);
slot_len = sizeof(*slot) + ATH6KL_FWLOG_PAYLOAD_SIZE;
for (i = 0; i < buf_len; i += space) {
space = CIRC_SPACE_TO_END(fwlog->head, fwlog->tail,
ATH6KL_FWLOG_SIZE);
skb = alloc_skb(slot_len, GFP_KERNEL);
if (!skb)
return;
if ((size_t) space > buf_len - i)
space = buf_len - i;
slot = (struct ath6kl_fwlog_slot *) skb_put(skb, slot_len);
slot->timestamp = cpu_to_le32(jiffies);
slot->length = cpu_to_le32(len);
memcpy(slot->payload, buf, len);
memcpy(&fwlog->buf[fwlog->head], buf, space);
fwlog->head = (fwlog->head + space) & (ATH6KL_FWLOG_SIZE - 1);
}
/* Need to pad each record to fixed length ATH6KL_FWLOG_PAYLOAD_SIZE */
memset(slot->payload + len, 0, ATH6KL_FWLOG_PAYLOAD_SIZE - len);
}
spin_lock(&ar->debug.fwlog_queue.lock);
void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len)
{
struct ath6kl_fwlog_slot *slot = ar->debug.fwlog_tmp;
size_t slot_len;
__skb_queue_tail(&ar->debug.fwlog_queue, skb);
complete(&ar->debug.fwlog_completion);
if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE))
return;
/* drop oldest entries */
while (skb_queue_len(&ar->debug.fwlog_queue) >
ATH6KL_FWLOG_MAX_ENTRIES) {
skb = __skb_dequeue(&ar->debug.fwlog_queue);
kfree_skb(skb);
}
spin_lock_bh(&ar->debug.fwlog_lock);
spin_unlock(&ar->debug.fwlog_queue.lock);
slot->timestamp = cpu_to_le32(jiffies);
slot->length = cpu_to_le32(len);
memcpy(slot->payload, buf, len);
return;
}
slot_len = sizeof(*slot) + len;
static int ath6kl_fwlog_open(struct inode *inode, struct file *file)
{
struct ath6kl *ar = inode->i_private;
if (slot_len < ATH6KL_FWLOG_SLOT_SIZE)
memset(slot->payload + len, 0,
ATH6KL_FWLOG_SLOT_SIZE - slot_len);
if (ar->debug.fwlog_open)
return -EBUSY;
ath6kl_debug_fwlog_add(ar, slot, ATH6KL_FWLOG_SLOT_SIZE);
ar->debug.fwlog_open = true;
spin_unlock_bh(&ar->debug.fwlog_lock);
file->private_data = inode->i_private;
return 0;
}
static bool ath6kl_debug_fwlog_empty(struct ath6kl *ar)
static int ath6kl_fwlog_release(struct inode *inode, struct file *file)
{
return CIRC_CNT(ar->debug.fwlog_buf.head,
ar->debug.fwlog_buf.tail,
ATH6KL_FWLOG_SLOT_SIZE) == 0;
struct ath6kl *ar = inode->i_private;
ar->debug.fwlog_open = false;
return 0;
}
static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath6kl *ar = file->private_data;
struct circ_buf *fwlog = &ar->debug.fwlog_buf;
size_t len = 0, buf_len = count;
struct sk_buff *skb;
ssize_t ret_cnt;
size_t len = 0;
char *buf;
int ccnt;
buf = vmalloc(buf_len);
buf = vmalloc(count);
if (!buf)
return -ENOMEM;
/* read undelivered logs from firmware */
ath6kl_read_fwlogs(ar);
spin_lock_bh(&ar->debug.fwlog_lock);
spin_lock(&ar->debug.fwlog_queue.lock);
while (len < buf_len && !ath6kl_debug_fwlog_empty(ar)) {
ccnt = CIRC_CNT_TO_END(fwlog->head, fwlog->tail,
ATH6KL_FWLOG_SIZE);
while ((skb = __skb_dequeue(&ar->debug.fwlog_queue))) {
if (skb->len > count - len) {
/* not enough space, put skb back and leave */
__skb_queue_head(&ar->debug.fwlog_queue, skb);
break;
}
if ((size_t) ccnt > buf_len - len)
ccnt = buf_len - len;
memcpy(buf + len, &fwlog->buf[fwlog->tail], ccnt);
len += ccnt;
memcpy(buf + len, skb->data, skb->len);
len += skb->len;
fwlog->tail = (fwlog->tail + ccnt) &
(ATH6KL_FWLOG_SIZE - 1);
kfree_skb(skb);
}
spin_unlock_bh(&ar->debug.fwlog_lock);
spin_unlock(&ar->debug.fwlog_queue.lock);
if (WARN_ON(len > buf_len))
len = buf_len;
/* FIXME: what to do if len == 0? */
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
......@@ -376,12 +374,87 @@ static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf,
}
static const struct file_operations fops_fwlog = {
.open = ath6kl_debugfs_open,
.open = ath6kl_fwlog_open,
.release = ath6kl_fwlog_release,
.read = ath6kl_fwlog_read,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t ath6kl_fwlog_block_read(struct file *file,
char __user *user_buf,
size_t count,
loff_t *ppos)
{
struct ath6kl *ar = file->private_data;
struct sk_buff *skb;
ssize_t ret_cnt;
size_t len = 0, not_copied;
char *buf;
int ret;
buf = vmalloc(count);
if (!buf)
return -ENOMEM;
spin_lock(&ar->debug.fwlog_queue.lock);
if (skb_queue_len(&ar->debug.fwlog_queue) == 0) {
/* we must init under queue lock */
init_completion(&ar->debug.fwlog_completion);
spin_unlock(&ar->debug.fwlog_queue.lock);
ret = wait_for_completion_interruptible(
&ar->debug.fwlog_completion);
if (ret == -ERESTARTSYS)
return ret;
spin_lock(&ar->debug.fwlog_queue.lock);
}
while ((skb = __skb_dequeue(&ar->debug.fwlog_queue))) {
if (skb->len > count - len) {
/* not enough space, put skb back and leave */
__skb_queue_head(&ar->debug.fwlog_queue, skb);
break;
}
memcpy(buf + len, skb->data, skb->len);
len += skb->len;
kfree_skb(skb);
}
spin_unlock(&ar->debug.fwlog_queue.lock);
/* FIXME: what to do if len == 0? */
not_copied = copy_to_user(user_buf, buf, len);
if (not_copied != 0) {
ret_cnt = -EFAULT;
goto out;
}
*ppos = *ppos + len;
ret_cnt = len;
out:
vfree(buf);
return ret_cnt;
}
static const struct file_operations fops_fwlog_block = {
.open = ath6kl_fwlog_open,
.release = ath6kl_fwlog_release,
.read = ath6kl_fwlog_block_read,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t ath6kl_fwlog_mask_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
......@@ -667,9 +740,13 @@ static ssize_t ath6kl_endpoint_stats_read(struct file *file,
return -ENOMEM;
#define EPSTAT(name) \
len = print_endpoint_stat(target, buf, buf_len, len, \
offsetof(struct htc_endpoint_stats, name), \
#name)
do { \
len = print_endpoint_stat(target, buf, buf_len, len, \
offsetof(struct htc_endpoint_stats, \
name), \
#name); \
} while (0)
EPSTAT(cred_low_indicate);
EPSTAT(tx_issued);
EPSTAT(tx_pkt_bundled);
......@@ -779,17 +856,9 @@ static ssize_t ath6kl_regread_write(struct file *file,
size_t count, loff_t *ppos)
{
struct ath6kl *ar = file->private_data;
u8 buf[50];
unsigned int len;
unsigned long reg_addr;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (strict_strtoul(buf, 0, &reg_addr))
if (kstrtoul_from_user(user_buf, count, 0, &reg_addr))
return -EINVAL;
if ((reg_addr % 4) != 0)
......@@ -903,15 +972,8 @@ static ssize_t ath6kl_lrssi_roam_write(struct file *file,
{
struct ath6kl *ar = file->private_data;
unsigned long lrssi_roam_threshold;
char buf[32];
ssize_t len;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (strict_strtoul(buf, 0, &lrssi_roam_threshold))
if (kstrtoul_from_user(user_buf, count, 0, &lrssi_roam_threshold))
return -EINVAL;
ar->lrssi_roam_threshold = lrssi_roam_threshold;
......@@ -1558,12 +1620,12 @@ static ssize_t ath6kl_listen_int_write(struct file *file,
if (kstrtou16(buf, 0, &listen_interval))
return -EINVAL;
if ((listen_interval < 1) || (listen_interval > 50))
if ((listen_interval < 15) || (listen_interval > 3000))
return -EINVAL;
ar->listen_intvl_b = listen_interval;
ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, 0,
ar->listen_intvl_b);
vif->listen_intvl_t = listen_interval;
ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
vif->listen_intvl_t, 0);
return count;
}
......@@ -1573,10 +1635,15 @@ static ssize_t ath6kl_listen_int_read(struct file *file,
size_t count, loff_t *ppos)
{
struct ath6kl *ar = file->private_data;
struct ath6kl_vif *vif;
char buf[32];
int len;
len = scnprintf(buf, sizeof(buf), "%u\n", ar->listen_intvl_b);
vif = ath6kl_vif_first(ar);
if (!vif)
return -EIO;
len = scnprintf(buf, sizeof(buf), "%u\n", vif->listen_intvl_t);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
......@@ -1649,33 +1716,29 @@ static const struct file_operations fops_power_params = {
.llseek = default_llseek,
};
int ath6kl_debug_init(struct ath6kl *ar)
void ath6kl_debug_init(struct ath6kl *ar)
{
ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE);
if (ar->debug.fwlog_buf.buf == NULL)
return -ENOMEM;
ar->debug.fwlog_tmp = kmalloc(ATH6KL_FWLOG_SLOT_SIZE, GFP_KERNEL);
if (ar->debug.fwlog_tmp == NULL) {
vfree(ar->debug.fwlog_buf.buf);
return -ENOMEM;
}
spin_lock_init(&ar->debug.fwlog_lock);
skb_queue_head_init(&ar->debug.fwlog_queue);
init_completion(&ar->debug.fwlog_completion);
/*
* Actually we are lying here but don't know how to read the mask
* value from the firmware.
*/
ar->debug.fwlog_mask = 0;
}
/*
* Initialisation needs to happen in two stages as fwlog events can come
* before cfg80211 is initialised, and debugfs depends on cfg80211
* initialisation.
*/
int ath6kl_debug_init_fs(struct ath6kl *ar)
{
ar->debugfs_phy = debugfs_create_dir("ath6kl",
ar->wiphy->debugfsdir);
if (!ar->debugfs_phy) {
vfree(ar->debug.fwlog_buf.buf);
kfree(ar->debug.fwlog_tmp);
if (!ar->debugfs_phy)
return -ENOMEM;
}
debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar,
&fops_tgt_stats);
......@@ -1689,6 +1752,9 @@ int ath6kl_debug_init(struct ath6kl *ar)
debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar,
&fops_fwlog);
debugfs_create_file("fwlog_block", S_IRUSR, ar->debugfs_phy, ar,
&fops_fwlog_block);
debugfs_create_file("fwlog_mask", S_IRUSR | S_IWUSR, ar->debugfs_phy,
ar, &fops_fwlog_mask);
......@@ -1723,27 +1789,26 @@ int ath6kl_debug_init(struct ath6kl *ar)
ar->debugfs_phy, ar, &fops_disconnect_timeout);
debugfs_create_file("create_qos", S_IWUSR, ar->debugfs_phy, ar,
&fops_create_qos);
&fops_create_qos);
debugfs_create_file("delete_qos", S_IWUSR, ar->debugfs_phy, ar,
&fops_delete_qos);
&fops_delete_qos);
debugfs_create_file("bgscan_interval", S_IWUSR,
ar->debugfs_phy, ar, &fops_bgscan_int);
ar->debugfs_phy, ar, &fops_bgscan_int);
debugfs_create_file("listen_interval", S_IRUSR | S_IWUSR,
ar->debugfs_phy, ar, &fops_listen_int);
debugfs_create_file("power_params", S_IWUSR, ar->debugfs_phy, ar,
&fops_power_params);
&fops_power_params);
return 0;
}
void ath6kl_debug_cleanup(struct ath6kl *ar)
{
vfree(ar->debug.fwlog_buf.buf);
kfree(ar->debug.fwlog_tmp);
skb_queue_purge(&ar->debug.fwlog_queue);
kfree(ar->debug.roam_tbl);
}
......
/*
* Copyright (c) 2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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
......@@ -77,7 +78,8 @@ int ath6kl_debug_roam_tbl_event(struct ath6kl *ar, const void *buf,
size_t len);
void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive);
void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar, u8 timeout);
int ath6kl_debug_init(struct ath6kl *ar);
void ath6kl_debug_init(struct ath6kl *ar);
int ath6kl_debug_init_fs(struct ath6kl *ar);
void ath6kl_debug_cleanup(struct ath6kl *ar);
#else
......@@ -127,7 +129,11 @@ static inline void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar,
{
}
static inline int ath6kl_debug_init(struct ath6kl *ar)
static inline void ath6kl_debug_init(struct ath6kl *ar)
{
}
static inline int ath6kl_debug_init_fs(struct ath6kl *ar)
{
return 0;
}
......
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011 Qualcomm Atheros, 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 (c) 2007-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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
......@@ -89,7 +90,7 @@ static void ath6kl_hif_dump_fw_crash(struct ath6kl *ar)
}
ath6kl_dbg(ATH6KL_DBG_IRQ, "register dump data address 0x%x\n",
regdump_addr);
regdump_addr);
regdump_addr = TARG_VTOP(ar->target_type, regdump_addr);
/* fetch register dump data */
......@@ -106,9 +107,9 @@ static void ath6kl_hif_dump_fw_crash(struct ath6kl *ar)
BUILD_BUG_ON(REG_DUMP_COUNT_AR6003 % 4);
for (i = 0; i < REG_DUMP_COUNT_AR6003 / 4; i++) {
for (i = 0; i < REG_DUMP_COUNT_AR6003; i += 4) {
ath6kl_info("%d: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
4 * i,
i,
le32_to_cpu(regdump_val[i]),
le32_to_cpu(regdump_val[i + 1]),
le32_to_cpu(regdump_val[i + 2]),
......@@ -134,6 +135,7 @@ static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev)
ath6kl_warn("Failed to clear debug interrupt: %d\n", ret);
ath6kl_hif_dump_fw_crash(dev->ar);
ath6kl_read_fwlogs(dev->ar);
return ret;
}
......@@ -283,7 +285,7 @@ static int ath6kl_hif_proc_counter_intr(struct ath6kl_device *dev)
dev->irq_en_reg.cntr_int_status_en;
ath6kl_dbg(ATH6KL_DBG_IRQ,
"valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n",
"valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n",
counter_int_status);
/*
......@@ -358,7 +360,7 @@ static int ath6kl_hif_proc_cpu_intr(struct ath6kl_device *dev)
}
ath6kl_dbg(ATH6KL_DBG_IRQ,
"valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n",
"valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n",
cpu_int_status);
/* Clear the interrupt */
......
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011 Qualcomm Atheros, 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
......@@ -197,6 +198,8 @@ struct hif_scatter_req {
u8 *virt_dma_buf;
struct hif_scatter_item scat_list[1];
u32 scat_q_depth;
};
struct ath6kl_irq_proc_registers {
......@@ -220,6 +223,7 @@ struct ath6kl_irq_enable_reg {
} __packed;
struct ath6kl_device {
/* protects irq_proc_reg and irq_en_reg below */
spinlock_t lock;
struct ath6kl_irq_proc_registers irq_proc_reg;
struct ath6kl_irq_enable_reg irq_en_reg;
......
/*
* Copyright (c) 2007-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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
......@@ -22,6 +23,9 @@
#define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask))
/* threshold to re-enable Tx bundling for an AC*/
#define TX_RESUME_BUNDLE_THRESHOLD 1500
/* Functions for Tx credit handling */
static void ath6kl_credit_deposit(struct ath6kl_htc_credit_info *cred_info,
struct htc_endpoint_credit_dist *ep_dist,
......@@ -168,31 +172,29 @@ static void ath6kl_credit_reduce(struct ath6kl_htc_credit_info *cred_info,
static void ath6kl_credit_update(struct ath6kl_htc_credit_info *cred_info,
struct list_head *epdist_list)
{
struct htc_endpoint_credit_dist *cur_dist_list;
struct htc_endpoint_credit_dist *cur_list;
list_for_each_entry(cur_dist_list, epdist_list, list) {
if (cur_dist_list->endpoint == ENDPOINT_0)
list_for_each_entry(cur_list, epdist_list, list) {
if (cur_list->endpoint == ENDPOINT_0)
continue;
if (cur_dist_list->cred_to_dist > 0) {
cur_dist_list->credits +=
cur_dist_list->cred_to_dist;
cur_dist_list->cred_to_dist = 0;
if (cur_dist_list->credits >
cur_dist_list->cred_assngd)
if (cur_list->cred_to_dist > 0) {
cur_list->credits += cur_list->cred_to_dist;
cur_list->cred_to_dist = 0;
if (cur_list->credits > cur_list->cred_assngd)
ath6kl_credit_reduce(cred_info,
cur_dist_list,
cur_dist_list->cred_assngd);
cur_list,
cur_list->cred_assngd);
if (cur_dist_list->credits >
cur_dist_list->cred_norm)
ath6kl_credit_reduce(cred_info, cur_dist_list,
cur_dist_list->cred_norm);
if (cur_list->credits > cur_list->cred_norm)
ath6kl_credit_reduce(cred_info, cur_list,
cur_list->cred_norm);
if (!(cur_dist_list->dist_flags & HTC_EP_ACTIVE)) {
if (cur_dist_list->txq_depth == 0)
if (!(cur_list->dist_flags & HTC_EP_ACTIVE)) {
if (cur_list->txq_depth == 0)
ath6kl_credit_reduce(cred_info,
cur_dist_list, 0);
cur_list, 0);
}
}
}
......@@ -460,8 +462,8 @@ static void htc_async_tx_scat_complete(struct htc_target *target,
INIT_LIST_HEAD(&tx_compq);
ath6kl_dbg(ATH6KL_DBG_HTC,
"htc tx scat complete len %d entries %d\n",
scat_req->len, scat_req->scat_entries);
"htc tx scat complete len %d entries %d\n",
scat_req->len, scat_req->scat_entries);
if (scat_req->status)
ath6kl_err("send scatter req failed: %d\n", scat_req->status);
......@@ -599,8 +601,8 @@ static void ath6kl_htc_tx_pkts_get(struct htc_target *target,
list);
ath6kl_dbg(ATH6KL_DBG_HTC,
"htc tx got packet 0x%p queue depth %d\n",
packet, get_queue_depth(&endpoint->txq));
"htc tx got packet 0x%p queue depth %d\n",
packet, get_queue_depth(&endpoint->txq));
len = CALC_TXRX_PADDED_LEN(target,
packet->act_len + HTC_HDR_LENGTH);
......@@ -670,6 +672,7 @@ static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target,
struct htc_packet *packet;
int i, len, rem_scat, cred_pad;
int status = 0;
u8 flags;
rem_scat = target->max_tx_bndl_sz;
......@@ -696,9 +699,9 @@ static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target,
scat_req->scat_list[i].packet = packet;
/* prepare packet and flag message as part of a send bundle */
ath6kl_htc_tx_prep_pkt(packet,
packet->info.tx.flags | HTC_FLAGS_SEND_BUNDLE,
cred_pad, packet->info.tx.seqno);
flags = packet->info.tx.flags | HTC_FLAGS_SEND_BUNDLE;
ath6kl_htc_tx_prep_pkt(packet, flags,
cred_pad, packet->info.tx.seqno);
/* Make sure the buffer is 4-byte aligned */
ath6kl_htc_tx_buf_align(&packet->buf,
packet->act_len + HTC_HDR_LENGTH);
......@@ -744,6 +747,12 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
struct hif_scatter_req *scat_req = NULL;
int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0;
int status;
u32 txb_mask;
u8 ac = WMM_NUM_AC;
if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) ||
(WMI_CONTROL_SVC != endpoint->svc_id))
ac = target->dev->ar->ep2ac_map[endpoint->eid];
while (true) {
status = 0;
......@@ -759,10 +768,35 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
if (!scat_req) {
/* no scatter resources */
ath6kl_dbg(ATH6KL_DBG_HTC,
"htc tx no more scatter resources\n");
"htc tx no more scatter resources\n");
break;
}
if ((ac < WMM_NUM_AC) && (ac != WMM_AC_BK)) {
if (WMM_AC_BE == ac)
/*
* BE, BK have priorities and bit
* positions reversed
*/
txb_mask = (1 << WMM_AC_BK);
else
/*
* any AC with priority lower than
* itself
*/
txb_mask = ((1 << ac) - 1);
/*
* when the scatter request resources drop below a
* certain threshold, disable Tx bundling for all
* AC's with priority lower than the current requesting
* AC. Otherwise re-enable Tx bundling for them
*/
if (scat_req->scat_q_depth < ATH6KL_SCATTER_REQS)
target->tx_bndl_mask &= ~txb_mask;
else
target->tx_bndl_mask |= txb_mask;
}
ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx pkts to scatter: %d\n",
n_scat);
......@@ -806,6 +840,7 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
struct htc_packet *packet;
int bundle_sent;
int n_pkts_bundle;
u8 ac = WMM_NUM_AC;
spin_lock_bh(&target->tx_lock);
......@@ -823,6 +858,10 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
*/
INIT_LIST_HEAD(&txq);
if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) ||
(WMI_CONTROL_SVC != endpoint->svc_id))
ac = target->dev->ar->ep2ac_map[endpoint->eid];
while (true) {
if (list_empty(&endpoint->txq))
......@@ -840,15 +879,18 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
while (true) {
/* try to send a bundle on each pass */
if ((target->tx_bndl_enable) &&
if ((target->tx_bndl_mask) &&
(get_queue_depth(&txq) >=
HTC_MIN_HTC_MSGS_TO_BUNDLE)) {
int temp1 = 0, temp2 = 0;
ath6kl_htc_tx_bundle(endpoint, &txq,
&temp1, &temp2);
bundle_sent += temp1;
n_pkts_bundle += temp2;
/* check if bundling is enabled for an AC */
if (target->tx_bndl_mask & (1 << ac)) {
ath6kl_htc_tx_bundle(endpoint, &txq,
&temp1, &temp2);
bundle_sent += temp1;
n_pkts_bundle += temp2;
}
}
if (list_empty(&txq))
......@@ -867,6 +909,26 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
endpoint->ep_st.tx_bundles += bundle_sent;
endpoint->ep_st.tx_pkt_bundled += n_pkts_bundle;
/*
* if an AC has bundling disabled and no tx bundling
* has occured continously for a certain number of TX,
* enable tx bundling for this AC
*/
if (!bundle_sent) {
if (!(target->tx_bndl_mask & (1 << ac)) &&
(ac < WMM_NUM_AC)) {
if (++target->ac_tx_count[ac] >=
TX_RESUME_BUNDLE_THRESHOLD) {
target->ac_tx_count[ac] = 0;
target->tx_bndl_mask |= (1 << ac);
}
}
} else {
/* tx bundling will reset the counter */
if (ac < WMM_NUM_AC)
target->ac_tx_count[ac] = 0;
}
}
endpoint->tx_proc_cnt = 0;
......@@ -979,8 +1041,8 @@ static int htc_setup_tx_complete(struct htc_target *target)
memcpy(&setup_comp_ext->flags, &flags,
sizeof(setup_comp_ext->flags));
set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp_ext,
sizeof(struct htc_setup_comp_ext_msg),
ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
sizeof(struct htc_setup_comp_ext_msg),
ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
} else {
struct htc_setup_comp_msg *setup_comp;
......@@ -988,8 +1050,8 @@ static int htc_setup_tx_complete(struct htc_target *target)
memset(setup_comp, 0, sizeof(struct htc_setup_comp_msg));
setup_comp->msg_id = cpu_to_le16(HTC_MSG_SETUP_COMPLETE_ID);
set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp,
sizeof(struct htc_setup_comp_msg),
ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
sizeof(struct htc_setup_comp_msg),
ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
}
/* we want synchronous operation */
......@@ -1088,9 +1150,9 @@ void ath6kl_htc_flush_txep(struct htc_target *target,
packet->status = -ECANCELED;
list_del(&packet->list);
ath6kl_dbg(ATH6KL_DBG_HTC,
"htc tx flushing pkt 0x%p len %d ep %d tag 0x%x\n",
packet, packet->act_len,
packet->endpoint, packet->info.tx.tag);
"htc tx flushing pkt 0x%p len %d ep %d tag 0x%x\n",
packet, packet->act_len,
packet->endpoint, packet->info.tx.tag);
INIT_LIST_HEAD(&container);
list_add_tail(&packet->list, &container);
......@@ -1490,7 +1552,7 @@ static void htc_ctrl_rx(struct htc_target *context, struct htc_packet *packets)
if (packets->act_len > 0) {
ath6kl_err("htc_ctrl_rx, got message with len:%zu\n",
packets->act_len + HTC_HDR_LENGTH);
packets->act_len + HTC_HDR_LENGTH);
ath6kl_dbg_dump(ATH6KL_DBG_HTC,
"htc rx unexpected endpoint 0 message", "",
......@@ -1609,8 +1671,8 @@ static int htc_parse_trailer(struct htc_target *target,
}
lk_ahd = (struct htc_lookahead_report *) record_buf;
if ((lk_ahd->pre_valid == ((~lk_ahd->post_valid) & 0xFF))
&& next_lk_ahds) {
if ((lk_ahd->pre_valid == ((~lk_ahd->post_valid) & 0xFF)) &&
next_lk_ahds) {
ath6kl_dbg(ATH6KL_DBG_HTC,
"htc rx lk_ahd found pre_valid 0x%x post_valid 0x%x\n",
......@@ -2038,13 +2100,13 @@ static int ath6kl_htc_rx_fetch(struct htc_target *target,
list_for_each_entry_safe(packet, tmp_pkt, rx_pktq, list) {
list_del(&packet->list);
htc_reclaim_rxbuf(target, packet,
&target->endpoint[packet->endpoint]);
&target->endpoint[packet->endpoint]);
}
list_for_each_entry_safe(packet, tmp_pkt, &tmp_rxq, list) {
list_del(&packet->list);
htc_reclaim_rxbuf(target, packet,
&target->endpoint[packet->endpoint]);
&target->endpoint[packet->endpoint]);
}
return status;
......@@ -2176,11 +2238,11 @@ static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target)
u32 look_ahead;
if (ath6kl_hif_poll_mboxmsg_rx(target->dev, &look_ahead,
HTC_TARGET_RESPONSE_TIMEOUT))
HTC_TARGET_RESPONSE_TIMEOUT))
return NULL;
ath6kl_dbg(ATH6KL_DBG_HTC,
"htc rx wait ctrl look_ahead 0x%X\n", look_ahead);
"htc rx wait ctrl look_ahead 0x%X\n", look_ahead);
htc_hdr = (struct htc_frame_hdr *)&look_ahead;
......@@ -2245,7 +2307,7 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
depth = get_queue_depth(pkt_queue);
ath6kl_dbg(ATH6KL_DBG_HTC,
"htc rx add multiple ep id %d cnt %d len %d\n",
"htc rx add multiple ep id %d cnt %d len %d\n",
first_pkt->endpoint, depth, first_pkt->buf_len);
endpoint = &target->endpoint[first_pkt->endpoint];
......@@ -2271,8 +2333,8 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
if (target->rx_st_flags & HTC_RECV_WAIT_BUFFERS) {
if (target->ep_waiting == first_pkt->endpoint) {
ath6kl_dbg(ATH6KL_DBG_HTC,
"htc rx blocked on ep %d, unblocking\n",
target->ep_waiting);
"htc rx blocked on ep %d, unblocking\n",
target->ep_waiting);
target->rx_st_flags &= ~HTC_RECV_WAIT_BUFFERS;
target->ep_waiting = ENDPOINT_MAX;
rx_unblock = true;
......@@ -2309,7 +2371,21 @@ void ath6kl_htc_flush_rx_buf(struct htc_target *target)
"htc rx flush pkt 0x%p len %d ep %d\n",
packet, packet->buf_len,
packet->endpoint);
dev_kfree_skb(packet->pkt_cntxt);
/*
* packets in rx_bufq of endpoint 0 have originally
* been queued from target->free_ctrl_rxbuf where
* packet and packet->buf_start are allocated
* separately using kmalloc(). For other endpoint
* rx_bufq, it is allocated as skb where packet is
* skb->head. Take care of this difference while freeing
* the memory.
*/
if (packet->endpoint == ENDPOINT_0) {
kfree(packet->buf_start);
kfree(packet);
} else {
dev_kfree_skb(packet->pkt_cntxt);
}
spin_lock_bh(&target->rx_lock);
}
spin_unlock_bh(&target->rx_lock);
......@@ -2328,6 +2404,7 @@ int ath6kl_htc_conn_service(struct htc_target *target,
enum htc_endpoint_id assigned_ep = ENDPOINT_MAX;
unsigned int max_msg_sz = 0;
int status = 0;
u16 msg_id;
ath6kl_dbg(ATH6KL_DBG_HTC,
"htc connect service target 0x%p service id 0x%x\n",
......@@ -2371,9 +2448,10 @@ int ath6kl_htc_conn_service(struct htc_target *target,
}
resp_msg = (struct htc_conn_service_resp *)rx_pkt->buf;
msg_id = le16_to_cpu(resp_msg->msg_id);
if ((le16_to_cpu(resp_msg->msg_id) != HTC_MSG_CONN_SVC_RESP_ID)
|| (rx_pkt->act_len < sizeof(*resp_msg))) {
if ((msg_id != HTC_MSG_CONN_SVC_RESP_ID) ||
(rx_pkt->act_len < sizeof(*resp_msg))) {
status = -ENOMEM;
goto fail_tx;
}
......@@ -2420,6 +2498,15 @@ int ath6kl_htc_conn_service(struct htc_target *target,
endpoint->cred_dist.endpoint = assigned_ep;
endpoint->cred_dist.cred_sz = target->tgt_cred_sz;
switch (endpoint->svc_id) {
case WMI_DATA_BK_SVC:
endpoint->tx_drop_packet_threshold = MAX_DEF_COOKIE_NUM / 3;
break;
default:
endpoint->tx_drop_packet_threshold = MAX_HI_COOKIE_NUM;
break;
}
if (conn_req->max_rxmsg_sz) {
/*
* Override cred_per_msg calculation, this optimizes
......@@ -2517,7 +2604,8 @@ static void htc_setup_msg_bndl(struct htc_target *target)
target->max_rx_bndl_sz, target->max_tx_bndl_sz);
if (target->max_tx_bndl_sz)
target->tx_bndl_enable = true;
/* tx_bndl_mask is enabled per AC, each has 1 bit */
target->tx_bndl_mask = (1 << WMM_NUM_AC) - 1;
if (target->max_rx_bndl_sz)
target->rx_bndl_enable = true;
......@@ -2532,7 +2620,7 @@ static void htc_setup_msg_bndl(struct htc_target *target)
* padding will spill into the next credit buffer
* which is fatal.
*/
target->tx_bndl_enable = false;
target->tx_bndl_mask = 0;
}
}
......@@ -2589,8 +2677,8 @@ int ath6kl_htc_wait_target(struct htc_target *target)
}
ath6kl_dbg(ATH6KL_DBG_BOOT, "htc using protocol %s (%d)\n",
(target->htc_tgt_ver == HTC_VERSION_2P0) ? "2.0" : ">= 2.1",
target->htc_tgt_ver);
(target->htc_tgt_ver == HTC_VERSION_2P0) ? "2.0" : ">= 2.1",
target->htc_tgt_ver);
if (target->msg_per_bndl_max > 0)
htc_setup_msg_bndl(target);
......@@ -2784,14 +2872,14 @@ void ath6kl_htc_cleanup(struct htc_target *target)
ath6kl_hif_cleanup_scatter(target->dev->ar);
list_for_each_entry_safe(packet, tmp_packet,
&target->free_ctrl_txbuf, list) {
&target->free_ctrl_txbuf, list) {
list_del(&packet->list);
kfree(packet->buf_start);
kfree(packet);
}
list_for_each_entry_safe(packet, tmp_packet,
&target->free_ctrl_rxbuf, list) {
&target->free_ctrl_rxbuf, list) {
list_del(&packet->list);
kfree(packet->buf_start);
kfree(packet);
......
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011 Qualcomm Atheros, 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
......@@ -87,6 +88,8 @@
#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 4)
#define WMI_MAX_SERVICES 5
#define WMM_NUM_AC 4
/* reserved and used to flush ALL packets */
#define HTC_TX_PACKET_TAG_ALL 0
#define HTC_SERVICE_TX_PACKET_TAG 1
......@@ -498,6 +501,7 @@ struct htc_endpoint {
u8 seqno;
u32 conn_flags;
struct htc_endpoint_stats ep_st;
u16 tx_drop_packet_threshold;
};
struct htc_control_buffer {
......@@ -519,9 +523,16 @@ struct htc_target {
struct ath6kl_htc_credit_info *credit_info;
int tgt_creds;
unsigned int tgt_cred_sz;
/* protects free_ctrl_txbuf and free_ctrl_rxbuf */
spinlock_t htc_lock;
/* FIXME: does this protext rx_bufq and endpoint structures or what? */
spinlock_t rx_lock;
/* protects endpoint->txq */
spinlock_t tx_lock;
struct ath6kl_device *dev;
u32 htc_flags;
u32 rx_st_flags;
......@@ -531,7 +542,7 @@ struct htc_target {
/* max messages per bundle for HTC */
int msg_per_bndl_max;
bool tx_bndl_enable;
u32 tx_bndl_mask;
int rx_bndl_enable;
int max_rx_bndl_sz;
int max_tx_bndl_sz;
......@@ -543,6 +554,9 @@ struct htc_target {
int max_xfer_szper_scatreq;
int chk_irq_status_cnt;
/* counts the number of Tx without bundling continously per AC */
u32 ac_tx_count[WMM_NUM_AC];
};
void *ath6kl_htc_create(struct ath6kl *ar);
......
/*
* Copyright (c) 2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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
......@@ -74,7 +75,7 @@ static const struct ath6kl_hw hw_list[] = {
},
.fw_board = AR6003_HW_2_1_1_BOARD_DATA_FILE,
.fw_default_board = AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE,
.fw_default_board = AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE,
},
{
.id = AR6004_HW_1_0_VERSION,
......@@ -351,11 +352,7 @@ static int ath6kl_set_htc_params(struct ath6kl *ar, u32 mbox_isr_yield_val,
blk_size |= ((u32)htc_ctrl_buf) << 16;
/* set the host interest area for the block size */
status = ath6kl_bmi_write(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_mbox_io_block_sz)),
(u8 *)&blk_size,
4);
status = ath6kl_bmi_write_hi32(ar, hi_mbox_io_block_sz, blk_size);
if (status) {
ath6kl_err("bmi_write_memory for IO block size failed\n");
goto out;
......@@ -367,11 +364,8 @@ static int ath6kl_set_htc_params(struct ath6kl *ar, u32 mbox_isr_yield_val,
if (mbox_isr_yield_val) {
/* set the host interest area for the mbox ISR yield limit */
status = ath6kl_bmi_write(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_mbox_isr_yield_limit)),
(u8 *)&mbox_isr_yield_val,
4);
status = ath6kl_bmi_write_hi32(ar, hi_mbox_isr_yield_limit,
mbox_isr_yield_val);
if (status) {
ath6kl_err("bmi_write_memory for yield limit failed\n");
goto out;
......@@ -384,7 +378,6 @@ static int ath6kl_set_htc_params(struct ath6kl *ar, u32 mbox_isr_yield_val,
static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
{
int status = 0;
int ret;
/*
......@@ -392,43 +385,54 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
* default values. Required if checksum offload is needed. Set
* RxMetaVersion to 2.
*/
if (ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, idx,
ar->rx_meta_ver, 0, 0)) {
ath6kl_err("unable to set the rx frame format\n");
status = -EIO;
ret = ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, idx,
ar->rx_meta_ver, 0, 0);
if (ret) {
ath6kl_err("unable to set the rx frame format: %d\n", ret);
return ret;
}
if (ar->conf_flags & ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN)
if ((ath6kl_wmi_pmparams_cmd(ar->wmi, idx, 0, 1, 0, 0, 1,
IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) {
ath6kl_err("unable to set power save fail event policy\n");
status = -EIO;
if (ar->conf_flags & ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN) {
ret = ath6kl_wmi_pmparams_cmd(ar->wmi, idx, 0, 1, 0, 0, 1,
IGNORE_PS_FAIL_DURING_SCAN);
if (ret) {
ath6kl_err("unable to set power save fail event policy: %d\n",
ret);
return ret;
}
}
if (!(ar->conf_flags & ATH6KL_CONF_IGNORE_ERP_BARKER))
if ((ath6kl_wmi_set_lpreamble_cmd(ar->wmi, idx, 0,
WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) {
ath6kl_err("unable to set barker preamble policy\n");
status = -EIO;
if (!(ar->conf_flags & ATH6KL_CONF_IGNORE_ERP_BARKER)) {
ret = ath6kl_wmi_set_lpreamble_cmd(ar->wmi, idx, 0,
WMI_FOLLOW_BARKER_IN_ERP);
if (ret) {
ath6kl_err("unable to set barker preamble policy: %d\n",
ret);
return ret;
}
}
if (ath6kl_wmi_set_keepalive_cmd(ar->wmi, idx,
WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) {
ath6kl_err("unable to set keep alive interval\n");
status = -EIO;
ret = ath6kl_wmi_set_keepalive_cmd(ar->wmi, idx,
WLAN_CONFIG_KEEP_ALIVE_INTERVAL);
if (ret) {
ath6kl_err("unable to set keep alive interval: %d\n", ret);
return ret;
}
if (ath6kl_wmi_disctimeout_cmd(ar->wmi, idx,
WLAN_CONFIG_DISCONNECT_TIMEOUT)) {
ath6kl_err("unable to set disconnect timeout\n");
status = -EIO;
ret = ath6kl_wmi_disctimeout_cmd(ar->wmi, idx,
WLAN_CONFIG_DISCONNECT_TIMEOUT);
if (ret) {
ath6kl_err("unable to set disconnect timeout: %d\n", ret);
return ret;
}
if (!(ar->conf_flags & ATH6KL_CONF_ENABLE_TX_BURST))
if (ath6kl_wmi_set_wmm_txop(ar->wmi, idx, WMI_TXOP_DISABLED)) {
ath6kl_err("unable to set txop bursting\n");
status = -EIO;
if (!(ar->conf_flags & ATH6KL_CONF_ENABLE_TX_BURST)) {
ret = ath6kl_wmi_set_wmm_txop(ar->wmi, idx, WMI_TXOP_DISABLED);
if (ret) {
ath6kl_err("unable to set txop bursting: %d\n", ret);
return ret;
}
}
if (ar->p2p && (ar->vif_max == 1 || idx)) {
ret = ath6kl_wmi_info_req_cmd(ar->wmi, idx,
......@@ -452,7 +456,7 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
}
}
return status;
return ret;
}
int ath6kl_configure_target(struct ath6kl *ar)
......@@ -462,8 +466,7 @@ int ath6kl_configure_target(struct ath6kl *ar)
int i, status;
param = !!(ar->conf_flags & ATH6KL_CONF_UART_DEBUG);
if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_serial_enable)), (u8 *)&param, 4)) {
if (ath6kl_bmi_write_hi32(ar, hi_serial_enable, param)) {
ath6kl_err("bmi_write_memory for uart debug failed\n");
return -EIO;
}
......@@ -499,11 +502,8 @@ int ath6kl_configure_target(struct ath6kl *ar)
if (ar->p2p && ar->vif_max == 1)
fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV;
param = HTC_PROTOCOL_VERSION;
if (ath6kl_bmi_write(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_app_host_interest)),
(u8 *)&param, 4) != 0) {
if (ath6kl_bmi_write_hi32(ar, hi_app_host_interest,
HTC_PROTOCOL_VERSION) != 0) {
ath6kl_err("bmi_write_memory for htc version failed\n");
return -EIO;
}
......@@ -511,10 +511,7 @@ int ath6kl_configure_target(struct ath6kl *ar)
/* set the firmware mode to STA/IBSS/AP */
param = 0;
if (ath6kl_bmi_read(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_option_flag)),
(u8 *)&param, 4) != 0) {
if (ath6kl_bmi_read_hi32(ar, hi_option_flag, &param) != 0) {
ath6kl_err("bmi_read_memory for setting fwmode failed\n");
return -EIO;
}
......@@ -526,11 +523,7 @@ int ath6kl_configure_target(struct ath6kl *ar)
param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT);
param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT);
if (ath6kl_bmi_write(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_option_flag)),
(u8 *)&param,
4) != 0) {
if (ath6kl_bmi_write_hi32(ar, hi_option_flag, param) != 0) {
ath6kl_err("bmi_write_memory for setting fwmode failed\n");
return -EIO;
}
......@@ -549,16 +542,13 @@ int ath6kl_configure_target(struct ath6kl *ar)
param = ar->hw.board_ext_data_addr;
ram_reserved_size = ar->hw.reserved_ram_size;
if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_board_ext_data)),
(u8 *)&param, 4) != 0) {
if (ath6kl_bmi_write_hi32(ar, hi_board_ext_data, param) != 0) {
ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n");
return -EIO;
}
if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_end_ram_reserve_sz)),
(u8 *)&ram_reserved_size, 4) != 0) {
if (ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz,
ram_reserved_size) != 0) {
ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n");
return -EIO;
}
......@@ -569,20 +559,13 @@ int ath6kl_configure_target(struct ath6kl *ar)
return -EIO;
/* Configure GPIO AR600x UART */
param = ar->hw.uarttx_pin;
status = ath6kl_bmi_write(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_dbg_uart_txpin)),
(u8 *)&param, 4);
status = ath6kl_bmi_write_hi32(ar, hi_dbg_uart_txpin,
ar->hw.uarttx_pin);
if (status)
return status;
/* Configure target refclk_hz */
param = ar->hw.refclk_hz;
status = ath6kl_bmi_write(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_refclk_hz)),
(u8 *)&param, 4);
status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz, ar->hw.refclk_hz);
if (status)
return status;
......@@ -832,13 +815,13 @@ static int ath6kl_fetch_testscript_file(struct ath6kl *ar)
return 0;
snprintf(filename, sizeof(filename), "%s/%s",
ar->hw.fw.dir, ar->hw.fw.testscript);
ar->hw.fw.dir, ar->hw.fw.testscript);
ret = ath6kl_get_fw(ar, filename, &ar->fw_testscript,
&ar->fw_testscript_len);
if (ret) {
ath6kl_err("Failed to get testscript file %s: %d\n",
filename, ret);
filename, ret);
return ret;
}
......@@ -922,7 +905,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
switch (ie_id) {
case ATH6KL_FW_IE_OTP_IMAGE:
ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n",
ie_len);
ie_len);
ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL);
......@@ -935,7 +918,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
break;
case ATH6KL_FW_IE_FW_IMAGE:
ath6kl_dbg(ATH6KL_DBG_BOOT, "found fw image ie (%zd B)\n",
ie_len);
ie_len);
/* in testmode we already might have a fw file */
if (ar->fw != NULL)
......@@ -952,7 +935,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
break;
case ATH6KL_FW_IE_PATCH_IMAGE:
ath6kl_dbg(ATH6KL_DBG_BOOT, "found patch image ie (%zd B)\n",
ie_len);
ie_len);
ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL);
......@@ -1096,22 +1079,14 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
*/
if (ar->hw.board_addr != 0) {
board_address = ar->hw.board_addr;
ath6kl_bmi_write(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_board_data)),
(u8 *) &board_address, 4);
ath6kl_bmi_write_hi32(ar, hi_board_data,
board_address);
} else {
ath6kl_bmi_read(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_board_data)),
(u8 *) &board_address, 4);
ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address);
}
/* determine where in target ram to write extended board data */
ath6kl_bmi_read(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_board_ext_data)),
(u8 *) &board_ext_address, 4);
ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address);
if (ar->target_type == TARGET_TYPE_AR6003 &&
board_ext_address == 0) {
......@@ -1123,6 +1098,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
case TARGET_TYPE_AR6003:
board_data_size = AR6003_BOARD_DATA_SZ;
board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ;
if (ar->fw_board_len > (board_data_size + board_ext_data_size))
board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ_V2;
break;
case TARGET_TYPE_AR6004:
board_data_size = AR6004_BOARD_DATA_SZ;
......@@ -1154,10 +1131,7 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
/* record that extended board data is initialized */
param = (board_ext_data_size << 16) | 1;
ath6kl_bmi_write(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_board_ext_data_config)),
(unsigned char *) &param, 4);
ath6kl_bmi_write_hi32(ar, hi_board_ext_data_config, param);
}
if (ar->fw_board_len < board_data_size) {
......@@ -1178,11 +1152,7 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
}
/* record the fact that Board Data IS initialized */
param = 1;
ath6kl_bmi_write(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_board_data_initialized)),
(u8 *)&param, 4);
ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, 1);
return ret;
}
......@@ -1209,10 +1179,7 @@ static int ath6kl_upload_otp(struct ath6kl *ar)
}
/* read firmware start address */
ret = ath6kl_bmi_read(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_app_start)),
(u8 *) &address, sizeof(address));
ret = ath6kl_bmi_read_hi32(ar, hi_app_start, &address);
if (ret) {
ath6kl_err("Failed to read hi_app_start: %d\n", ret);
......@@ -1270,7 +1237,7 @@ static int ath6kl_upload_firmware(struct ath6kl *ar)
static int ath6kl_upload_patch(struct ath6kl *ar)
{
u32 address, param;
u32 address;
int ret;
if (ar->fw_patch == NULL)
......@@ -1287,18 +1254,14 @@ static int ath6kl_upload_patch(struct ath6kl *ar)
return ret;
}
param = address;
ath6kl_bmi_write(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_dset_list_head)),
(unsigned char *) &param, 4);
ath6kl_bmi_write_hi32(ar, hi_dset_list_head, address);
return 0;
}
static int ath6kl_upload_testscript(struct ath6kl *ar)
{
u32 address, param;
u32 address;
int ret;
if (ar->testmode != 2)
......@@ -1310,7 +1273,7 @@ static int ath6kl_upload_testscript(struct ath6kl *ar)
address = ar->hw.testscript_addr;
ath6kl_dbg(ATH6KL_DBG_BOOT, "writing testscript to 0x%x (%zd B)\n",
address, ar->fw_testscript_len);
address, ar->fw_testscript_len);
ret = ath6kl_bmi_write(ar, address, ar->fw_testscript,
ar->fw_testscript_len);
......@@ -1319,23 +1282,9 @@ static int ath6kl_upload_testscript(struct ath6kl *ar)
return ret;
}
param = address;
ath6kl_bmi_write(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_ota_testscript)),
(unsigned char *) &param, 4);
param = 4096;
ath6kl_bmi_write(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_end_ram_reserve_sz)),
(unsigned char *) &param, 4);
param = 1;
ath6kl_bmi_write(ar,
ath6kl_get_hi_item_addr(ar,
HI_ITEM(hi_test_apps_related)),
(unsigned char *) &param, 4);
ath6kl_bmi_write_hi32(ar, hi_ota_testscript, address);
ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096);
ath6kl_bmi_write_hi32(ar, hi_test_apps_related, 1);
return 0;
}
......@@ -1346,7 +1295,7 @@ static int ath6kl_init_upload(struct ath6kl *ar)
int status = 0;
if (ar->target_type != TARGET_TYPE_AR6003 &&
ar->target_type != TARGET_TYPE_AR6004)
ar->target_type != TARGET_TYPE_AR6004)
return -EINVAL;
/* temporarily disable system sleep */
......@@ -1403,7 +1352,8 @@ static int ath6kl_init_upload(struct ath6kl *ar)
return status;
/* WAR to avoid SDIO CRC err */
if (ar->version.target_ver == AR6003_HW_2_0_VERSION) {
if (ar->version.target_ver == AR6003_HW_2_0_VERSION ||
ar->version.target_ver == AR6003_HW_2_1_1_VERSION) {
ath6kl_err("temporary war to avoid sdio crc error\n");
param = 0x20;
......@@ -1726,9 +1676,11 @@ void ath6kl_stop_txrx(struct ath6kl *ar)
* configure NOT to reset the target during a debug session.
*/
ath6kl_dbg(ATH6KL_DBG_TRC,
"attempting to reset target on instance destroy\n");
"attempting to reset target on instance destroy\n");
ath6kl_reset_device(ar, ar->target_type, true, true);
clear_bit(WLAN_ENABLED, &ar->flag);
up(&ar->sem);
}
EXPORT_SYMBOL(ath6kl_stop_txrx);
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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
......@@ -80,11 +81,21 @@ static void ath6kl_add_new_sta(struct ath6kl_vif *vif, u8 *mac, u16 aid,
static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i)
{
struct ath6kl_sta *sta = &ar->sta_list[i];
struct ath6kl_mgmt_buff *entry, *tmp;
/* empty the queued pkts in the PS queue if any */
spin_lock_bh(&sta->psq_lock);
skb_queue_purge(&sta->psq);
skb_queue_purge(&sta->apsdq);
if (sta->mgmt_psq_len != 0) {
list_for_each_entry_safe(entry, tmp, &sta->mgmt_psq, list) {
kfree(entry);
}
INIT_LIST_HEAD(&sta->mgmt_psq);
sta->mgmt_psq_len = 0;
}
spin_unlock_bh(&sta->psq_lock);
memset(&ar->ap_stats.sta[sta->aid - 1], 0,
......@@ -339,7 +350,7 @@ void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
__le32 data;
if (target_type != TARGET_TYPE_AR6003 &&
target_type != TARGET_TYPE_AR6004)
target_type != TARGET_TYPE_AR6004)
return;
data = cold_reset ? cpu_to_le32(RESET_CONTROL_COLD_RST) :
......@@ -588,11 +599,9 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,
memcpy(vif->bssid, bssid, sizeof(vif->bssid));
vif->bss_ch = channel;
if ((vif->nw_type == INFRA_NETWORK)) {
ar->listen_intvl_b = listen_int;
if ((vif->nw_type == INFRA_NETWORK))
ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
0, ar->listen_intvl_b);
}
vif->listen_intvl_t, 0);
netif_wake_queue(vif->ndev);
......@@ -810,6 +819,7 @@ void ath6kl_pspoll_event(struct ath6kl_vif *vif, u8 aid)
struct sk_buff *skb;
bool psq_empty = false;
struct ath6kl *ar = vif->ar;
struct ath6kl_mgmt_buff *mgmt_buf;
conn = ath6kl_find_sta_by_aid(ar, aid);
......@@ -820,7 +830,7 @@ void ath6kl_pspoll_event(struct ath6kl_vif *vif, u8 aid)
* becomes empty update the PVB for this station.
*/
spin_lock_bh(&conn->psq_lock);
psq_empty = skb_queue_empty(&conn->psq);
psq_empty = skb_queue_empty(&conn->psq) && (conn->mgmt_psq_len == 0);
spin_unlock_bh(&conn->psq_lock);
if (psq_empty)
......@@ -828,15 +838,31 @@ void ath6kl_pspoll_event(struct ath6kl_vif *vif, u8 aid)
return;
spin_lock_bh(&conn->psq_lock);
skb = skb_dequeue(&conn->psq);
spin_unlock_bh(&conn->psq_lock);
if (conn->mgmt_psq_len > 0) {
mgmt_buf = list_first_entry(&conn->mgmt_psq,
struct ath6kl_mgmt_buff, list);
list_del(&mgmt_buf->list);
conn->mgmt_psq_len--;
spin_unlock_bh(&conn->psq_lock);
conn->sta_flags |= STA_PS_POLLED;
ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx,
mgmt_buf->id, mgmt_buf->freq,
mgmt_buf->wait, mgmt_buf->buf,
mgmt_buf->len, mgmt_buf->no_cck);
conn->sta_flags &= ~STA_PS_POLLED;
kfree(mgmt_buf);
} else {
skb = skb_dequeue(&conn->psq);
spin_unlock_bh(&conn->psq_lock);
conn->sta_flags |= STA_PS_POLLED;
ath6kl_data_tx(skb, vif->ndev);
conn->sta_flags &= ~STA_PS_POLLED;
conn->sta_flags |= STA_PS_POLLED;
ath6kl_data_tx(skb, vif->ndev);
conn->sta_flags &= ~STA_PS_POLLED;
}
spin_lock_bh(&conn->psq_lock);
psq_empty = skb_queue_empty(&conn->psq);
psq_empty = skb_queue_empty(&conn->psq) && (conn->mgmt_psq_len == 0);
spin_unlock_bh(&conn->psq_lock);
if (psq_empty)
......@@ -922,8 +948,8 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
}
ath6kl_cfg80211_disconnect_event(vif, reason, bssid,
assoc_resp_len, assoc_info,
prot_reason_status);
assoc_resp_len, assoc_info,
prot_reason_status);
aggr_reset_state(vif->aggr_cntxt->aggr_conn);
......@@ -943,9 +969,9 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
} else {
set_bit(CONNECT_PEND, &vif->flags);
if (((reason == ASSOC_FAILED) &&
(prot_reason_status == 0x11)) ||
((reason == ASSOC_FAILED) && (prot_reason_status == 0x0)
&& (vif->reconnect_flag == 1))) {
(prot_reason_status == 0x11)) ||
((reason == ASSOC_FAILED) && (prot_reason_status == 0x0) &&
(vif->reconnect_flag == 1))) {
set_bit(CONNECTED, &vif->flags);
return;
}
......@@ -1079,7 +1105,7 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
if (mc_all_on || mc_all_off) {
/* Enable/disable all multicast */
ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast filter\n",
mc_all_on ? "enabling" : "disabling");
mc_all_on ? "enabling" : "disabling");
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx,
mc_all_on);
if (ret)
......@@ -1092,7 +1118,7 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
found = false;
netdev_for_each_mc_addr(ha, ndev) {
if (memcmp(ha->addr, mc_filter->hw_addr,
ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) {
ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) {
found = true;
break;
}
......@@ -1111,7 +1137,7 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
false);
if (ret) {
ath6kl_warn("Failed to remove multicast filter:%pM\n",
mc_filter->hw_addr);
mc_filter->hw_addr);
return;
}
......@@ -1126,7 +1152,7 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
found = false;
list_for_each_entry(mc_filter, &vif->mc_filter, list) {
if (memcmp(ha->addr, mc_filter->hw_addr,
ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) {
ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) {
found = true;
break;
}
......@@ -1151,7 +1177,7 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
true);
if (ret) {
ath6kl_warn("Failed to add multicast filter :%pM\n",
mc_filter->hw_addr);
mc_filter->hw_addr);
kfree(mc_filter);
goto out;
}
......@@ -1184,5 +1210,7 @@ void init_netdev(struct net_device *dev)
sizeof(struct wmi_data_hdr) + HTC_HDR_LENGTH
+ WMI_MAX_TX_META_SZ + ATH6KL_HTC_ALIGN_BYTES;
dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
return;
}
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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
......@@ -31,6 +32,7 @@
struct ath6kl_sdio {
struct sdio_func *func;
/* protects access to bus_req_freeq */
spinlock_t lock;
/* free list */
......@@ -49,16 +51,20 @@ struct ath6kl_sdio {
/* scatter request list head */
struct list_head scat_req;
/* Avoids disabling irq while the interrupts being handled */
struct mutex mtx_irq;
atomic_t irq_handling;
wait_queue_head_t irq_wq;
/* protects access to scat_req */
spinlock_t scat_lock;
bool scatter_enabled;
bool is_disabled;
const struct sdio_device_id *id;
struct work_struct wr_async_work;
struct list_head wr_asyncq;
/* protects access to wr_asyncq */
spinlock_t wr_async_lock;
};
......@@ -404,7 +410,10 @@ static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
return -ENOMEM;
mutex_lock(&ar_sdio->dma_buffer_mutex);
tbuf = ar_sdio->dma_buffer;
memcpy(tbuf, buf, len);
if (request & HIF_WRITE)
memcpy(tbuf, buf, len);
bounced = true;
} else
tbuf = buf;
......@@ -462,7 +471,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func)
ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n");
ar_sdio = sdio_get_drvdata(func);
mutex_lock(&ar_sdio->mtx_irq);
atomic_set(&ar_sdio->irq_handling, 1);
/*
* Release the host during interrups so we can pick it back up when
* we process commands.
......@@ -471,7 +480,10 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func)
status = ath6kl_hif_intr_bh_handler(ar_sdio->ar);
sdio_claim_host(ar_sdio->func);
mutex_unlock(&ar_sdio->mtx_irq);
atomic_set(&ar_sdio->irq_handling, 0);
wake_up(&ar_sdio->irq_wq);
WARN_ON(status && status != -ECANCELED);
}
......@@ -572,6 +584,13 @@ static void ath6kl_sdio_irq_enable(struct ath6kl *ar)
sdio_release_host(ar_sdio->func);
}
static bool ath6kl_sdio_is_on_irq(struct ath6kl *ar)
{
struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
return !atomic_read(&ar_sdio->irq_handling);
}
static void ath6kl_sdio_irq_disable(struct ath6kl *ar)
{
struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
......@@ -579,14 +598,21 @@ static void ath6kl_sdio_irq_disable(struct ath6kl *ar)
sdio_claim_host(ar_sdio->func);
mutex_lock(&ar_sdio->mtx_irq);
if (atomic_read(&ar_sdio->irq_handling)) {
sdio_release_host(ar_sdio->func);
ret = wait_event_interruptible(ar_sdio->irq_wq,
ath6kl_sdio_is_on_irq(ar));
if (ret)
return;
sdio_claim_host(ar_sdio->func);
}
ret = sdio_release_irq(ar_sdio->func);
if (ret)
ath6kl_err("Failed to release sdio irq: %d\n", ret);
mutex_unlock(&ar_sdio->mtx_irq);
sdio_release_host(ar_sdio->func);
}
......@@ -601,6 +627,8 @@ static struct hif_scatter_req *ath6kl_sdio_scatter_req_get(struct ath6kl *ar)
node = list_first_entry(&ar_sdio->scat_req,
struct hif_scatter_req, list);
list_del(&node->list);
node->scat_q_depth = get_queue_depth(&ar_sdio->scat_req);
}
spin_unlock_bh(&ar_sdio->scat_lock);
......@@ -633,8 +661,8 @@ static int ath6kl_sdio_async_rw_scatter(struct ath6kl *ar,
return -EINVAL;
ath6kl_dbg(ATH6KL_DBG_SCATTER,
"hif-scatter: total len: %d scatter entries: %d\n",
scat_req->len, scat_req->scat_entries);
"hif-scatter: total len: %d scatter entries: %d\n",
scat_req->len, scat_req->scat_entries);
if (request & HIF_SYNCHRONOUS)
status = ath6kl_sdio_scat_rw(ar_sdio, scat_req->busrequest);
......@@ -813,6 +841,7 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
struct sdio_func *func = ar_sdio->func;
mmc_pm_flag_t flags;
bool try_deepsleep = false;
int ret;
if (ar->state == ATH6KL_STATE_SCHED_SCAN) {
......@@ -839,14 +868,22 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
goto cut_pwr;
ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_WOW, wow);
if (ret)
if (ret && ret != -ENOTCONN)
ath6kl_err("wow suspend failed: %d\n", ret);
if (ret &&
(!ar->wow_suspend_mode ||
ar->wow_suspend_mode == WLAN_POWER_STATE_DEEP_SLEEP))
try_deepsleep = true;
else if (ret &&
ar->wow_suspend_mode == WLAN_POWER_STATE_CUT_PWR)
goto cut_pwr;
return 0;
if (!ret)
return 0;
}
if (ar->suspend_mode == WLAN_POWER_STATE_DEEP_SLEEP ||
!ar->suspend_mode) {
!ar->suspend_mode || try_deepsleep) {
flags = sdio_get_host_pm_caps(func);
if (!(flags & MMC_PM_KEEP_POWER))
......@@ -901,8 +938,15 @@ static int ath6kl_sdio_resume(struct ath6kl *ar)
case ATH6KL_STATE_WOW:
break;
case ATH6KL_STATE_SCHED_SCAN:
break;
case ATH6KL_STATE_SUSPENDING:
break;
case ATH6KL_STATE_RESUMING:
break;
}
ath6kl_cfg80211_resume(ar);
......@@ -981,7 +1025,7 @@ static int ath6kl_sdio_diag_read32(struct ath6kl *ar, u32 address, u32 *data)
(u8 *)data, sizeof(u32), HIF_RD_SYNC_BYTE_INC);
if (status) {
ath6kl_err("%s: failed to read from window data addr\n",
__func__);
__func__);
return status;
}
......@@ -1285,7 +1329,6 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
spin_lock_init(&ar_sdio->scat_lock);
spin_lock_init(&ar_sdio->wr_async_lock);
mutex_init(&ar_sdio->dma_buffer_mutex);
mutex_init(&ar_sdio->mtx_irq);
INIT_LIST_HEAD(&ar_sdio->scat_req);
INIT_LIST_HEAD(&ar_sdio->bus_req_freeq);
......@@ -1293,6 +1336,8 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
INIT_WORK(&ar_sdio->wr_async_work, ath6kl_sdio_write_async_work);
init_waitqueue_head(&ar_sdio->irq_wq);
for (count = 0; count < BUS_REQUEST_MAX_NUM; count++)
ath6kl_sdio_free_bus_req(ar_sdio, &ar_sdio->bus_req[count]);
......
/*
* Copyright (c) 2004-2010 Atheros Communications Inc.
* Copyright (c) 2011 Qualcomm Atheros, 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
......@@ -19,6 +20,7 @@
#define AR6003_BOARD_DATA_SZ 1024
#define AR6003_BOARD_EXT_DATA_SZ 768
#define AR6003_BOARD_EXT_DATA_SZ_V2 1024
#define AR6004_BOARD_DATA_SZ 6144
#define AR6004_BOARD_EXT_DATA_SZ 0
......
/*
* Copyright (c) 2010-2011 Atheros Communications Inc.
* Copyright (c) 2011 Qualcomm Atheros, 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 (c) 2010-2011 Atheros Communications Inc.
* Copyright (c) 2011 Qualcomm Atheros, 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 (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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
......@@ -158,8 +159,8 @@ static bool ath6kl_process_uapsdq(struct ath6kl_sta *conn,
*/
if (is_apsdq_empty) {
ath6kl_wmi_set_apsd_bfrd_traf(ar->wmi,
vif->fw_vif_idx,
conn->aid, 1, 0);
vif->fw_vif_idx,
conn->aid, 1, 0);
}
*flags |= WMI_DATA_HDR_FLAGS_UAPSD;
......@@ -284,6 +285,9 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb,
int status = 0;
struct ath6kl_cookie *cookie = NULL;
if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW))
return -EACCES;
spin_lock_bh(&ar->lock);
ath6kl_dbg(ATH6KL_DBG_WLAN_TX,
......@@ -359,6 +363,11 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
return 0;
}
if (WARN_ON_ONCE(ar->state != ATH6KL_STATE_ON)) {
dev_kfree_skb(skb);
return 0;
}
if (!test_bit(WMI_READY, &ar->flag))
goto fail_tx;
......@@ -370,7 +379,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
if (test_bit(WMI_ENABLED, &ar->flag)) {
if ((dev->features & NETIF_F_IP_CSUM) &&
(csum == CHECKSUM_PARTIAL)) {
(csum == CHECKSUM_PARTIAL)) {
csum_start = skb->csum_start -
(skb_network_header(skb) - skb->head) +
sizeof(struct ath6kl_llc_snap_hdr);
......@@ -394,7 +403,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
}
if ((dev->features & NETIF_F_IP_CSUM) &&
(csum == CHECKSUM_PARTIAL)) {
(csum == CHECKSUM_PARTIAL)) {
meta_v2.csum_start = csum_start;
meta_v2.csum_dest = csum_dest;
......@@ -419,7 +428,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
}
if ((vif->nw_type == ADHOC_NETWORK) &&
ar->ibss_ps_enable && test_bit(CONNECTED, &vif->flags))
ar->ibss_ps_enable && test_bit(CONNECTED, &vif->flags))
chk_adhoc_ps_mapping = true;
else {
/* get the stream mapping */
......@@ -593,7 +602,8 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
*/
if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] <
ar->hiac_stream_active_pri &&
ar->cookie_count <= MAX_HI_COOKIE_NUM)
ar->cookie_count <=
target->endpoint[endpoint].tx_drop_packet_threshold)
/*
* Give preference to the highest priority stream by
* dropping the packets which overflowed.
......@@ -876,7 +886,7 @@ void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint)
if (!IS_ALIGNED((unsigned long) skb->data, 4))
skb->data = PTR_ALIGN(skb->data - 4, 4);
set_htc_rxpkt_info(packet, skb, skb->data,
ATH6KL_BUFFER_SIZE, endpoint);
ATH6KL_BUFFER_SIZE, endpoint);
list_add_tail(&packet->list, &queue);
}
......@@ -1256,8 +1266,8 @@ static void ath6kl_uapsd_trigger_frame_rx(struct ath6kl_vif *vif,
flags = 0;
ath6kl_wmi_set_apsd_bfrd_traf(ar->wmi,
vif->fw_vif_idx,
conn->aid, 0, flags);
vif->fw_vif_idx,
conn->aid, 0, flags);
}
return;
......@@ -1296,7 +1306,15 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
skb_put(skb, packet->act_len + HTC_HDR_LENGTH);
skb_pull(skb, HTC_HDR_LENGTH);
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ",
skb->data, skb->len);
if (ept == ar->ctrl_ep) {
if (test_bit(WMI_ENABLED, &ar->flag)) {
ath6kl_check_wow_status(ar);
ath6kl_wmi_control_rx(ar->wmi, skb);
return;
}
if_idx =
wmi_cmd_hdr_get_if_idx((struct wmi_cmd_hdr *) skb->data);
} else {
......@@ -1321,10 +1339,6 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
spin_unlock_bh(&vif->if_lock);
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ",
skb->data, skb->len);
skb->dev = vif->ndev;
if (!test_bit(WMI_ENABLED, &ar->flag)) {
......@@ -1336,11 +1350,6 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
ath6kl_check_wow_status(ar);
if (ept == ar->ctrl_ep) {
ath6kl_wmi_control_rx(ar->wmi, skb);
return;
}
min_hdr_len = sizeof(struct ethhdr) + sizeof(struct wmi_data_hdr) +
sizeof(struct ath6kl_llc_snap_hdr);
......@@ -1416,8 +1425,33 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
if (!(conn->sta_flags & STA_PS_SLEEP)) {
struct sk_buff *skbuff = NULL;
bool is_apsdq_empty;
struct ath6kl_mgmt_buff *mgmt;
u8 idx;
spin_lock_bh(&conn->psq_lock);
while (conn->mgmt_psq_len > 0) {
mgmt = list_first_entry(
&conn->mgmt_psq,
struct ath6kl_mgmt_buff,
list);
list_del(&mgmt->list);
conn->mgmt_psq_len--;
spin_unlock_bh(&conn->psq_lock);
idx = vif->fw_vif_idx;
ath6kl_wmi_send_mgmt_cmd(ar->wmi,
idx,
mgmt->id,
mgmt->freq,
mgmt->wait,
mgmt->buf,
mgmt->len,
mgmt->no_cck);
kfree(mgmt);
spin_lock_bh(&conn->psq_lock);
}
conn->mgmt_psq_len = 0;
while ((skbuff = skb_dequeue(&conn->psq))) {
spin_unlock_bh(&conn->psq_lock);
ath6kl_data_tx(skbuff, vif->ndev);
......@@ -1541,7 +1575,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
aggr_conn = vif->aggr_cntxt->aggr_conn;
if (aggr_process_recv_frm(aggr_conn, tid, seq_no,
is_amsdu, skb)) {
is_amsdu, skb)) {
/* aggregation code will handle the skb */
return;
}
......
/*
* Copyright (c) 2007-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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 (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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
......@@ -126,7 +127,7 @@ int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb)
if (!is_ethertype(be16_to_cpu(type))) {
ath6kl_dbg(ATH6KL_DBG_WMI,
"%s: pkt is already in 802.3 format\n", __func__);
"%s: pkt is already in 802.3 format\n", __func__);
return 0;
}
......@@ -827,8 +828,8 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len,
if (pie[1] > 3 && pie[2] == 0x00 && pie[3] == 0x50 &&
pie[4] == 0xf2 && pie[5] == WMM_OUI_TYPE) {
/* WMM OUT (00:50:F2) */
if (pie[1] > 5
&& pie[6] == WMM_PARAM_OUI_SUBTYPE)
if (pie[1] > 5 &&
pie[6] == WMM_PARAM_OUI_SUBTYPE)
wmi->is_wmm_enabled = true;
}
break;
......@@ -912,17 +913,17 @@ static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len)
regpair = ath6kl_get_regpair((u16) reg_code);
country = ath6kl_regd_find_country_by_rd((u16) reg_code);
ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n",
regpair->regDmnEnum);
regpair->regDmnEnum);
}
if (country) {
if (country && wmi->parent_dev->wiphy_registered) {
alpha2[0] = country->isoName[0];
alpha2[1] = country->isoName[1];
regulatory_hint(wmi->parent_dev->wiphy, alpha2);
ath6kl_dbg(ATH6KL_DBG_WMI, "Country alpha2 being used: %c%c\n",
alpha2[0], alpha2[1]);
alpha2[0], alpha2[1]);
}
}
......@@ -1033,8 +1034,9 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
if (len < 8 + 2 + 2)
return -EINVAL;
if (bih->frame_type == BEACON_FTYPE && test_bit(CONNECTED, &vif->flags)
&& memcmp(bih->bssid, vif->bssid, ETH_ALEN) == 0) {
if (bih->frame_type == BEACON_FTYPE &&
test_bit(CONNECTED, &vif->flags) &&
memcmp(bih->bssid, vif->bssid, ETH_ALEN) == 0) {
const u8 *tim;
tim = cfg80211_find_ie(WLAN_EID_TIM, buf + 8 + 2 + 2,
len - 8 - 2 - 2);
......@@ -1366,8 +1368,8 @@ static int ath6kl_wmi_rssi_threshold_event_rx(struct wmi *wmi, u8 *datap,
/* Upper threshold breached */
if (rssi < sq_thresh->upper_threshold[0]) {
ath6kl_dbg(ATH6KL_DBG_WMI,
"spurious upper rssi threshold event: %d\n",
rssi);
"spurious upper rssi threshold event: %d\n",
rssi);
} else if ((rssi < sq_thresh->upper_threshold[1]) &&
(rssi >= sq_thresh->upper_threshold[0])) {
new_threshold = WMI_RSSI_THRESHOLD1_ABOVE;
......@@ -1390,7 +1392,7 @@ static int ath6kl_wmi_rssi_threshold_event_rx(struct wmi *wmi, u8 *datap,
/* Lower threshold breached */
if (rssi > sq_thresh->lower_threshold[0]) {
ath6kl_dbg(ATH6KL_DBG_WMI,
"spurious lower rssi threshold event: %d %d\n",
"spurious lower rssi threshold event: %d %d\n",
rssi, sq_thresh->lower_threshold[0]);
} else if ((rssi > sq_thresh->lower_threshold[1]) &&
(rssi <= sq_thresh->lower_threshold[0])) {
......@@ -1551,8 +1553,8 @@ static int ath6kl_wmi_snr_threshold_event_rx(struct wmi *wmi, u8 *datap,
/* Upper threshold breached */
if (snr < sq_thresh->upper_threshold[0]) {
ath6kl_dbg(ATH6KL_DBG_WMI,
"spurious upper snr threshold event: %d\n",
snr);
"spurious upper snr threshold event: %d\n",
snr);
} else if ((snr < sq_thresh->upper_threshold[1]) &&
(snr >= sq_thresh->upper_threshold[0])) {
new_threshold = WMI_SNR_THRESHOLD1_ABOVE;
......@@ -1569,8 +1571,8 @@ static int ath6kl_wmi_snr_threshold_event_rx(struct wmi *wmi, u8 *datap,
/* Lower threshold breached */
if (snr > sq_thresh->lower_threshold[0]) {
ath6kl_dbg(ATH6KL_DBG_WMI,
"spurious lower snr threshold event: %d\n",
sq_thresh->lower_threshold[0]);
"spurious lower snr threshold event: %d\n",
sq_thresh->lower_threshold[0]);
} else if ((snr > sq_thresh->lower_threshold[1]) &&
(snr <= sq_thresh->lower_threshold[0])) {
new_threshold = WMI_SNR_THRESHOLD4_BELOW;
......@@ -2028,6 +2030,26 @@ int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u8 if_idx,
return ret;
}
int ath6kl_wmi_bmisstime_cmd(struct wmi *wmi, u8 if_idx,
u16 bmiss_time, u16 num_beacons)
{
struct sk_buff *skb;
struct wmi_bmiss_time_cmd *cmd;
int ret;
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
if (!skb)
return -ENOMEM;
cmd = (struct wmi_bmiss_time_cmd *) skb->data;
cmd->bmiss_time = cpu_to_le16(bmiss_time);
cmd->num_beacons = cpu_to_le16(num_beacons);
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_BMISS_TIME_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 if_idx, u8 pwr_mode)
{
struct sk_buff *skb;
......@@ -2613,7 +2635,7 @@ int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
int ret;
if ((wow_mode != ATH6KL_WOW_MODE_ENABLE) &&
wow_mode != ATH6KL_WOW_MODE_DISABLE) {
wow_mode != ATH6KL_WOW_MODE_DISABLE) {
ath6kl_err("invalid wow mode: %d\n", wow_mode);
return -EINVAL;
}
......@@ -3014,6 +3036,22 @@ int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 if_idx, u8 cmd, const u8 *mac,
NO_SYNC_WMIFLAG);
}
int ath6kl_wmi_ap_hidden_ssid(struct wmi *wmi, u8 if_idx, bool enable)
{
struct sk_buff *skb;
struct wmi_ap_hidden_ssid_cmd *cmd;
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
if (!skb)
return -ENOMEM;
cmd = (struct wmi_ap_hidden_ssid_cmd *) skb->data;
cmd->hidden_ssid = enable ? 1 : 0;
return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_AP_HIDDEN_SSID_CMDID,
NO_SYNC_WMIFLAG);
}
/* This command will be used to enable/disable AP uAPSD feature */
int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable)
{
......@@ -3183,8 +3221,9 @@ int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq, u32 dur)
* ath6kl_wmi_send_mgmt_cmd instead. The new function supports P2P
* mgmt operations using station interface.
*/
int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
u32 wait, const u8 *data, u16 data_len)
static int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id,
u32 freq, u32 wait, const u8 *data,
u16 data_len)
{
struct sk_buff *skb;
struct wmi_send_action_cmd *p;
......@@ -3220,9 +3259,9 @@ int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
NO_SYNC_WMIFLAG);
}
int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
u32 wait, const u8 *data, u16 data_len,
u32 no_cck)
static int __ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id,
u32 freq, u32 wait, const u8 *data,
u16 data_len, u32 no_cck)
{
struct sk_buff *skb;
struct wmi_send_mgmt_cmd *p;
......@@ -3259,6 +3298,32 @@ int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
NO_SYNC_WMIFLAG);
}
int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
u32 wait, const u8 *data, u16 data_len,
u32 no_cck)
{
int status;
struct ath6kl *ar = wmi->parent_dev;
if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
ar->fw_capabilities)) {
/*
* If capable of doing P2P mgmt operations using
* station interface, send additional information like
* supported rates to advertise and xmit rates for
* probe requests
*/
status = __ath6kl_wmi_send_mgmt_cmd(ar->wmi, if_idx, id, freq,
wait, data, data_len,
no_cck);
} else {
status = ath6kl_wmi_send_action_cmd(ar->wmi, if_idx, id, freq,
wait, data, data_len);
}
return status;
}
int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq,
const u8 *dst, const u8 *data,
u16 data_len)
......@@ -3370,32 +3435,101 @@ static int ath6kl_wmi_roam_tbl_event_rx(struct wmi *wmi, u8 *datap, int len)
return ath6kl_debug_roam_tbl_event(wmi->parent_dev, datap, len);
}
/* Control Path */
int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
/* Process interface specific wmi events, caller would free the datap */
static int ath6kl_wmi_proc_events_vif(struct wmi *wmi, u16 if_idx, u16 cmd_id,
u8 *datap, u32 len)
{
struct wmi_cmd_hdr *cmd;
struct ath6kl_vif *vif;
u32 len;
u16 id;
u8 if_idx;
u8 *datap;
int ret = 0;
if (WARN_ON(skb == NULL))
vif = ath6kl_get_vif_by_index(wmi->parent_dev, if_idx);
if (!vif) {
ath6kl_dbg(ATH6KL_DBG_WMI,
"Wmi event for unavailable vif, vif_index:%d\n",
if_idx);
return -EINVAL;
}
if (skb->len < sizeof(struct wmi_cmd_hdr)) {
ath6kl_err("bad packet 1\n");
dev_kfree_skb(skb);
switch (cmd_id) {
case WMI_CONNECT_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CONNECT_EVENTID\n");
return ath6kl_wmi_connect_event_rx(wmi, datap, len, vif);
case WMI_DISCONNECT_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DISCONNECT_EVENTID\n");
return ath6kl_wmi_disconnect_event_rx(wmi, datap, len, vif);
case WMI_TKIP_MICERR_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TKIP_MICERR_EVENTID\n");
return ath6kl_wmi_tkip_micerr_event_rx(wmi, datap, len, vif);
case WMI_BSSINFO_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n");
return ath6kl_wmi_bssinfo_event_rx(wmi, datap, len, vif);
case WMI_NEIGHBOR_REPORT_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n");
return ath6kl_wmi_neighbor_report_event_rx(wmi, datap, len,
vif);
case WMI_SCAN_COMPLETE_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n");
return ath6kl_wmi_scan_complete_rx(wmi, datap, len, vif);
case WMI_REPORT_STATISTICS_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_STATISTICS_EVENTID\n");
return ath6kl_wmi_stats_event_rx(wmi, datap, len, vif);
case WMI_CAC_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CAC_EVENTID\n");
return ath6kl_wmi_cac_event_rx(wmi, datap, len, vif);
case WMI_PSPOLL_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSPOLL_EVENTID\n");
return ath6kl_wmi_pspoll_event_rx(wmi, datap, len, vif);
case WMI_DTIMEXPIRY_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DTIMEXPIRY_EVENTID\n");
return ath6kl_wmi_dtimexpiry_event_rx(wmi, datap, len, vif);
case WMI_ADDBA_REQ_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_REQ_EVENTID\n");
return ath6kl_wmi_addba_req_event_rx(wmi, datap, len, vif);
case WMI_DELBA_REQ_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DELBA_REQ_EVENTID\n");
return ath6kl_wmi_delba_req_event_rx(wmi, datap, len, vif);
case WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI,
"WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID");
return ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx(wmi, vif);
case WMI_REMAIN_ON_CHNL_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n");
return ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len, vif);
case WMI_CANCEL_REMAIN_ON_CHNL_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI,
"WMI_CANCEL_REMAIN_ON_CHNL_EVENTID\n");
return ath6kl_wmi_cancel_remain_on_chnl_event_rx(wmi, datap,
len, vif);
case WMI_TX_STATUS_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_STATUS_EVENTID\n");
return ath6kl_wmi_tx_status_event_rx(wmi, datap, len, vif);
case WMI_RX_PROBE_REQ_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_PROBE_REQ_EVENTID\n");
return ath6kl_wmi_rx_probe_req_event_rx(wmi, datap, len, vif);
case WMI_RX_ACTION_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n");
return ath6kl_wmi_rx_action_event_rx(wmi, datap, len, vif);
default:
ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", cmd_id);
return -EINVAL;
}
return 0;
}
static int ath6kl_wmi_proc_events(struct wmi *wmi, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd;
int ret = 0;
u32 len;
u16 id;
u8 if_idx;
u8 *datap;
cmd = (struct wmi_cmd_hdr *) skb->data;
id = le16_to_cpu(cmd->cmd_id);
if_idx = le16_to_cpu(cmd->info1) & WMI_CMD_HDR_IF_ID_MASK;
skb_pull(skb, sizeof(struct wmi_cmd_hdr));
datap = skb->data;
len = skb->len;
......@@ -3403,15 +3537,6 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
ath6kl_dbg_dump(ATH6KL_DBG_WMI_DUMP, NULL, "wmi rx ",
datap, len);
vif = ath6kl_get_vif_by_index(wmi->parent_dev, if_idx);
if (!vif) {
ath6kl_dbg(ATH6KL_DBG_WMI,
"Wmi event for unavailable vif, vif_index:%d\n",
if_idx);
dev_kfree_skb(skb);
return -EINVAL;
}
switch (id) {
case WMI_GET_BITRATE_CMDID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_BITRATE_CMDID\n");
......@@ -3429,26 +3554,10 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_READY_EVENTID\n");
ret = ath6kl_wmi_ready_event_rx(wmi, datap, len);
break;
case WMI_CONNECT_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CONNECT_EVENTID\n");
ret = ath6kl_wmi_connect_event_rx(wmi, datap, len, vif);
break;
case WMI_DISCONNECT_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DISCONNECT_EVENTID\n");
ret = ath6kl_wmi_disconnect_event_rx(wmi, datap, len, vif);
break;
case WMI_PEER_NODE_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PEER_NODE_EVENTID\n");
ret = ath6kl_wmi_peer_node_event_rx(wmi, datap, len);
break;
case WMI_TKIP_MICERR_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TKIP_MICERR_EVENTID\n");
ret = ath6kl_wmi_tkip_micerr_event_rx(wmi, datap, len, vif);
break;
case WMI_BSSINFO_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n");
ret = ath6kl_wmi_bssinfo_event_rx(wmi, datap, len, vif);
break;
case WMI_REGDOMAIN_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REGDOMAIN_EVENTID\n");
ath6kl_wmi_regdomain_event(wmi, datap, len);
......@@ -3457,23 +3566,10 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSTREAM_TIMEOUT_EVENTID\n");
ret = ath6kl_wmi_pstream_timeout_event_rx(wmi, datap, len);
break;
case WMI_NEIGHBOR_REPORT_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n");
ret = ath6kl_wmi_neighbor_report_event_rx(wmi, datap, len,
vif);
break;
case WMI_SCAN_COMPLETE_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n");
ret = ath6kl_wmi_scan_complete_rx(wmi, datap, len, vif);
break;
case WMI_CMDERROR_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CMDERROR_EVENTID\n");
ret = ath6kl_wmi_error_event_rx(wmi, datap, len);
break;
case WMI_REPORT_STATISTICS_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_STATISTICS_EVENTID\n");
ret = ath6kl_wmi_stats_event_rx(wmi, datap, len, vif);
break;
case WMI_RSSI_THRESHOLD_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RSSI_THRESHOLD_EVENTID\n");
ret = ath6kl_wmi_rssi_threshold_event_rx(wmi, datap, len);
......@@ -3493,10 +3589,6 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_EXTENSION_EVENTID\n");
ret = ath6kl_wmi_control_rx_xtnd(wmi, skb);
break;
case WMI_CAC_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CAC_EVENTID\n");
ret = ath6kl_wmi_cac_event_rx(wmi, datap, len, vif);
break;
case WMI_CHANNEL_CHANGE_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CHANNEL_CHANGE_EVENTID\n");
break;
......@@ -3536,28 +3628,12 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_PMKID_LIST_EVENTID\n");
ret = ath6kl_wmi_get_pmkid_list_event_rx(wmi, datap, len);
break;
case WMI_PSPOLL_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSPOLL_EVENTID\n");
ret = ath6kl_wmi_pspoll_event_rx(wmi, datap, len, vif);
break;
case WMI_DTIMEXPIRY_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DTIMEXPIRY_EVENTID\n");
ret = ath6kl_wmi_dtimexpiry_event_rx(wmi, datap, len, vif);
break;
case WMI_SET_PARAMS_REPLY_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SET_PARAMS_REPLY_EVENTID\n");
break;
case WMI_ADDBA_REQ_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_REQ_EVENTID\n");
ret = ath6kl_wmi_addba_req_event_rx(wmi, datap, len, vif);
break;
case WMI_ADDBA_RESP_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_RESP_EVENTID\n");
break;
case WMI_DELBA_REQ_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DELBA_REQ_EVENTID\n");
ret = ath6kl_wmi_delba_req_event_rx(wmi, datap, len, vif);
break;
case WMI_REPORT_BTCOEX_CONFIG_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI,
"WMI_REPORT_BTCOEX_CONFIG_EVENTID\n");
......@@ -3570,52 +3646,39 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n");
ret = ath6kl_wmi_tx_complete_event_rx(datap, len);
break;
case WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI,
"WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID");
ret = ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx(wmi, vif);
break;
case WMI_REMAIN_ON_CHNL_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n");
ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len, vif);
break;
case WMI_CANCEL_REMAIN_ON_CHNL_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI,
"WMI_CANCEL_REMAIN_ON_CHNL_EVENTID\n");
ret = ath6kl_wmi_cancel_remain_on_chnl_event_rx(wmi, datap,
len, vif);
break;
case WMI_TX_STATUS_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_STATUS_EVENTID\n");
ret = ath6kl_wmi_tx_status_event_rx(wmi, datap, len, vif);
break;
case WMI_RX_PROBE_REQ_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_PROBE_REQ_EVENTID\n");
ret = ath6kl_wmi_rx_probe_req_event_rx(wmi, datap, len, vif);
break;
case WMI_P2P_CAPABILITIES_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_CAPABILITIES_EVENTID\n");
ret = ath6kl_wmi_p2p_capabilities_event_rx(datap, len);
break;
case WMI_RX_ACTION_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n");
ret = ath6kl_wmi_rx_action_event_rx(wmi, datap, len, vif);
break;
case WMI_P2P_INFO_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_INFO_EVENTID\n");
ret = ath6kl_wmi_p2p_info_event_rx(datap, len);
break;
default:
ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", id);
ret = -EINVAL;
/* may be the event is interface specific */
ret = ath6kl_wmi_proc_events_vif(wmi, if_idx, id, datap, len);
break;
}
dev_kfree_skb(skb);
return ret;
}
/* Control Path */
int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
{
if (WARN_ON(skb == NULL))
return -EINVAL;
if (skb->len < sizeof(struct wmi_cmd_hdr)) {
ath6kl_err("bad packet 1\n");
dev_kfree_skb(skb);
return -EINVAL;
}
return ath6kl_wmi_proc_events(wmi, skb);
}
void ath6kl_wmi_reset(struct wmi *wmi)
{
spin_lock_bh(&wmi->lock);
......
/*
* Copyright (c) 2010-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, 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
......@@ -110,6 +111,8 @@ struct wmi {
u8 fat_pipe_exist;
struct ath6kl *parent_dev;
u8 pwr_mode;
/* protects fat_pipe_exist and stream_exist_for_ac */
spinlock_t lock;
enum htc_endpoint_id ep_id;
struct sq_threshold_params
......@@ -997,6 +1000,12 @@ struct wmi_listen_int_cmd {
__le16 num_beacons;
} __packed;
/* WMI_SET_BMISS_TIME_CMDID */
struct wmi_bmiss_time_cmd {
__le16 bmiss_time;
__le16 num_beacons;
};
/* WMI_SET_POWER_MODE_CMDID */
enum wmi_power_mode {
REC_POWER = 0x01,
......@@ -1014,7 +1023,7 @@ struct wmi_power_mode_cmd {
*/
enum power_save_fail_event_policy {
SEND_POWER_SAVE_FAIL_EVENT_ALWAYS = 1,
IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN = 2,
IGNORE_PS_FAIL_DURING_SCAN = 2,
};
struct wmi_power_params_cmd {
......@@ -1212,7 +1221,7 @@ struct wmi_snr_threshold_params_cmd {
enum wmi_preamble_policy {
WMI_IGNORE_BARKER_IN_ERP = 0,
WMI_DONOT_IGNORE_BARKER_IN_ERP
WMI_FOLLOW_BARKER_IN_ERP,
};
struct wmi_set_lpreamble_cmd {
......@@ -2128,6 +2137,10 @@ struct wmi_rx_frame_format_cmd {
u8 reserved[1];
} __packed;
struct wmi_ap_hidden_ssid_cmd {
u8 hidden_ssid;
} __packed;
/* AP mode events */
struct wmi_ap_set_apsd_cmd {
u8 enable;
......@@ -2413,6 +2426,8 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag,
int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u8 if_idx,
u16 listen_interval,
u16 listen_beacons);
int ath6kl_wmi_bmisstime_cmd(struct wmi *wmi, u8 if_idx,
u16 bmiss_time, u16 num_beacons);
int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 if_idx, u8 pwr_mode);
int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u8 if_idx, u16 idle_period,
u16 ps_poll_num, u16 dtim_policy,
......@@ -2484,6 +2499,7 @@ u8 ath6kl_wmi_get_traffic_class(u8 user_priority);
u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri);
/* AP mode */
int ath6kl_wmi_ap_hidden_ssid(struct wmi *wmi, u8 if_idx, bool enable);
int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx,
struct wmi_connect_cmd *p);
......@@ -2505,9 +2521,6 @@ int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable);
int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq,
u32 dur);
int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
u32 wait, const u8 *data, u16 data_len);
int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
u32 wait, const u8 *data, u16 data_len,
u32 no_cck);
......
......@@ -834,9 +834,10 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
AR_SREV_9287_11_OR_LATER(ah))
REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
if (AR_SREV_9271_10(ah))
REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only,
modesIndex, regWrites);
if (AR_SREV_9271_10(ah)) {
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENA);
REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_ADC_ON, 0xa);
}
ENABLE_REGWRITE_BUFFER(ah);
......@@ -858,21 +859,11 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
REGWRITE_BUFFER_FLUSH(ah);
if (AR_SREV_9271(ah)) {
if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1)
REG_WRITE_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
modesIndex, regWrites);
else
REG_WRITE_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
modesIndex, regWrites);
}
REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites);
if (IS_CHAN_A_FAST_CLOCK(ah, chan)) {
REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex,
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
REG_WRITE_ARRAY(&ah->iniModesFastClock, modesIndex,
regWrites);
}
ar5008_hw_override_ini(ah, chan);
ar5008_hw_set_channel_regs(ah, chan);
......
......@@ -34,23 +34,8 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar9271Modes_9271), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
ARRAY_SIZE(ar9271Common_9271), 2);
INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271,
ar9287Common_normal_cck_fir_coeff_9287_1_1,
ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_9287_1_1), 2);
INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271,
ar9287Common_japan_2484_cck_fir_coeff_9287_1_1,
ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_9287_1_1), 2);
INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only,
ar9271Modes_9271_1_0_only,
ARRAY_SIZE(ar9271Modes_9271_1_0_only), 5);
INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 5);
INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
ar9271Modes_high_power_tx_gain_9271,
ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 5);
INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
ar9271Modes_normal_power_tx_gain_9271,
ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 5);
return;
}
......@@ -79,7 +64,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
ARRAY_SIZE(ar9280Common_9280_2), 2);
INIT_INI_ARRAY(&ah->iniModesAdditional,
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9280Modes_fast_clock_9280_2,
ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
} else if (AR_SREV_9160_10_OR_LATER(ah)) {
......@@ -160,11 +145,6 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
INI_RA(addac, 31,1) = 0;
}
}
}
/* Support for Japan ch.14 (2484) spread */
void ar9002_hw_cck_chan14_spread(struct ath_hw *ah)
{
if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniCckfirNormal,
ar9287Common_normal_cck_fir_coeff_9287_1_1,
......@@ -204,14 +184,10 @@ static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
}
}
static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah)
static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
{
u32 txgain_type;
if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
AR5416_EEP_MINOR_VER_19) {
txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_high_power_tx_gain_9280_2,
......@@ -227,8 +203,22 @@ static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah)
}
}
static void ar9271_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
{
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9271Modes_high_power_tx_gain_9271,
ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9271Modes_normal_power_tx_gain_9271,
ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 5);
}
static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
{
u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
if (AR_SREV_9287_11_OR_LATER(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9287Modes_rx_gain_9287_1_1,
......@@ -236,15 +226,15 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
else if (AR_SREV_9280_20(ah))
ar9280_20_hw_init_rxgain_ini(ah);
if (AR_SREV_9287_11_OR_LATER(ah)) {
if (AR_SREV_9271(ah)) {
ar9271_hw_init_txgain_ini(ah, txgain_type);
} else if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9287Modes_tx_gain_9287_1_1,
ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 5);
} else if (AR_SREV_9280_20(ah)) {
ar9280_20_hw_init_txgain_ini(ah);
ar9280_20_hw_init_txgain_ini(ah, txgain_type);
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
/* txgain table */
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
if (AR_SREV_9285E_20(ah)) {
......
......@@ -3092,12 +3092,6 @@ static const u32 ar9271Common_9271[][2] = {
{0x0000d384, 0xf3307ff0},
};
static const u32 ar9271Modes_9271_1_0_only[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311},
{0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
};
static const u32 ar9271Modes_9271_ANI_reg[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
......
......@@ -347,15 +347,12 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags)
{
struct ar5416_desc *ads = AR5416DESC(ds);
struct ath9k_hw_capabilities *pCap = &ah->caps;
ads->ds_ctl1 = size & AR_BufLen;
if (flags & ATH9K_RXDESC_INTREQ)
ads->ds_ctl1 |= AR_RxIntrReq;
ads->ds_rxstatus8 &= ~AR_RxDone;
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
memset(&(ads->u), 0, sizeof(ads->u));
memset(&ads->u.rx, 0, sizeof(ads->u.rx));
}
EXPORT_SYMBOL(ath9k_hw_setuprxdesc);
......
......@@ -60,6 +60,8 @@
#define AR_PHY_RF_CTL3 0x9828
#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000
#define AR_PHY_TX_END_TO_A2_RX_ON_S 16
#define AR_PHY_TX_END_TO_ADC_ON 0xFF000000
#define AR_PHY_TX_END_TO_ADC_ON_S 24
#define AR_PHY_ADC_CTL 0x982C
#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003
......
......@@ -295,266 +295,6 @@ static const u32 ar9300_2p2_radio_core[][2] = {
{0x00016bd4, 0x00000000},
};
static const u32 ar9300Common_rx_gain_table_merlin_2p2[][2] = {
/* Addr allmodes */
{0x0000a000, 0x02000101},
{0x0000a004, 0x02000102},
{0x0000a008, 0x02000103},
{0x0000a00c, 0x02000104},
{0x0000a010, 0x02000200},
{0x0000a014, 0x02000201},
{0x0000a018, 0x02000202},
{0x0000a01c, 0x02000203},
{0x0000a020, 0x02000204},
{0x0000a024, 0x02000205},
{0x0000a028, 0x02000208},
{0x0000a02c, 0x02000302},
{0x0000a030, 0x02000303},
{0x0000a034, 0x02000304},
{0x0000a038, 0x02000400},
{0x0000a03c, 0x02010300},
{0x0000a040, 0x02010301},
{0x0000a044, 0x02010302},
{0x0000a048, 0x02000500},
{0x0000a04c, 0x02010400},
{0x0000a050, 0x02020300},
{0x0000a054, 0x02020301},
{0x0000a058, 0x02020302},
{0x0000a05c, 0x02020303},
{0x0000a060, 0x02020400},
{0x0000a064, 0x02030300},
{0x0000a068, 0x02030301},
{0x0000a06c, 0x02030302},
{0x0000a070, 0x02030303},
{0x0000a074, 0x02030400},
{0x0000a078, 0x02040300},
{0x0000a07c, 0x02040301},
{0x0000a080, 0x02040302},
{0x0000a084, 0x02040303},
{0x0000a088, 0x02030500},
{0x0000a08c, 0x02040400},
{0x0000a090, 0x02050203},
{0x0000a094, 0x02050204},
{0x0000a098, 0x02050205},
{0x0000a09c, 0x02040500},
{0x0000a0a0, 0x02050301},
{0x0000a0a4, 0x02050302},
{0x0000a0a8, 0x02050303},
{0x0000a0ac, 0x02050400},
{0x0000a0b0, 0x02050401},
{0x0000a0b4, 0x02050402},
{0x0000a0b8, 0x02050403},
{0x0000a0bc, 0x02050500},
{0x0000a0c0, 0x02050501},
{0x0000a0c4, 0x02050502},
{0x0000a0c8, 0x02050503},
{0x0000a0cc, 0x02050504},
{0x0000a0d0, 0x02050600},
{0x0000a0d4, 0x02050601},
{0x0000a0d8, 0x02050602},
{0x0000a0dc, 0x02050603},
{0x0000a0e0, 0x02050604},
{0x0000a0e4, 0x02050700},
{0x0000a0e8, 0x02050701},
{0x0000a0ec, 0x02050702},
{0x0000a0f0, 0x02050703},
{0x0000a0f4, 0x02050704},
{0x0000a0f8, 0x02050705},
{0x0000a0fc, 0x02050708},
{0x0000a100, 0x02050709},
{0x0000a104, 0x0205070a},
{0x0000a108, 0x0205070b},
{0x0000a10c, 0x0205070c},
{0x0000a110, 0x0205070d},
{0x0000a114, 0x02050710},
{0x0000a118, 0x02050711},
{0x0000a11c, 0x02050712},
{0x0000a120, 0x02050713},
{0x0000a124, 0x02050714},
{0x0000a128, 0x02050715},
{0x0000a12c, 0x02050730},
{0x0000a130, 0x02050731},
{0x0000a134, 0x02050732},
{0x0000a138, 0x02050733},
{0x0000a13c, 0x02050734},
{0x0000a140, 0x02050735},
{0x0000a144, 0x02050750},
{0x0000a148, 0x02050751},
{0x0000a14c, 0x02050752},
{0x0000a150, 0x02050753},
{0x0000a154, 0x02050754},
{0x0000a158, 0x02050755},
{0x0000a15c, 0x02050770},
{0x0000a160, 0x02050771},
{0x0000a164, 0x02050772},
{0x0000a168, 0x02050773},
{0x0000a16c, 0x02050774},
{0x0000a170, 0x02050775},
{0x0000a174, 0x00000776},
{0x0000a178, 0x00000776},
{0x0000a17c, 0x00000776},
{0x0000a180, 0x00000776},
{0x0000a184, 0x00000776},
{0x0000a188, 0x00000776},
{0x0000a18c, 0x00000776},
{0x0000a190, 0x00000776},
{0x0000a194, 0x00000776},
{0x0000a198, 0x00000776},
{0x0000a19c, 0x00000776},
{0x0000a1a0, 0x00000776},
{0x0000a1a4, 0x00000776},
{0x0000a1a8, 0x00000776},
{0x0000a1ac, 0x00000776},
{0x0000a1b0, 0x00000776},
{0x0000a1b4, 0x00000776},
{0x0000a1b8, 0x00000776},
{0x0000a1bc, 0x00000776},
{0x0000a1c0, 0x00000776},
{0x0000a1c4, 0x00000776},
{0x0000a1c8, 0x00000776},
{0x0000a1cc, 0x00000776},
{0x0000a1d0, 0x00000776},
{0x0000a1d4, 0x00000776},
{0x0000a1d8, 0x00000776},
{0x0000a1dc, 0x00000776},
{0x0000a1e0, 0x00000776},
{0x0000a1e4, 0x00000776},
{0x0000a1e8, 0x00000776},
{0x0000a1ec, 0x00000776},
{0x0000a1f0, 0x00000776},
{0x0000a1f4, 0x00000776},
{0x0000a1f8, 0x00000776},
{0x0000a1fc, 0x00000776},
{0x0000b000, 0x02000101},
{0x0000b004, 0x02000102},
{0x0000b008, 0x02000103},
{0x0000b00c, 0x02000104},
{0x0000b010, 0x02000200},
{0x0000b014, 0x02000201},
{0x0000b018, 0x02000202},
{0x0000b01c, 0x02000203},
{0x0000b020, 0x02000204},
{0x0000b024, 0x02000205},
{0x0000b028, 0x02000208},
{0x0000b02c, 0x02000302},
{0x0000b030, 0x02000303},
{0x0000b034, 0x02000304},
{0x0000b038, 0x02000400},
{0x0000b03c, 0x02010300},
{0x0000b040, 0x02010301},
{0x0000b044, 0x02010302},
{0x0000b048, 0x02000500},
{0x0000b04c, 0x02010400},
{0x0000b050, 0x02020300},
{0x0000b054, 0x02020301},
{0x0000b058, 0x02020302},
{0x0000b05c, 0x02020303},
{0x0000b060, 0x02020400},
{0x0000b064, 0x02030300},
{0x0000b068, 0x02030301},
{0x0000b06c, 0x02030302},
{0x0000b070, 0x02030303},
{0x0000b074, 0x02030400},
{0x0000b078, 0x02040300},
{0x0000b07c, 0x02040301},
{0x0000b080, 0x02040302},
{0x0000b084, 0x02040303},
{0x0000b088, 0x02030500},
{0x0000b08c, 0x02040400},
{0x0000b090, 0x02050203},
{0x0000b094, 0x02050204},
{0x0000b098, 0x02050205},
{0x0000b09c, 0x02040500},
{0x0000b0a0, 0x02050301},
{0x0000b0a4, 0x02050302},
{0x0000b0a8, 0x02050303},
{0x0000b0ac, 0x02050400},
{0x0000b0b0, 0x02050401},
{0x0000b0b4, 0x02050402},
{0x0000b0b8, 0x02050403},
{0x0000b0bc, 0x02050500},
{0x0000b0c0, 0x02050501},
{0x0000b0c4, 0x02050502},
{0x0000b0c8, 0x02050503},
{0x0000b0cc, 0x02050504},
{0x0000b0d0, 0x02050600},
{0x0000b0d4, 0x02050601},
{0x0000b0d8, 0x02050602},
{0x0000b0dc, 0x02050603},
{0x0000b0e0, 0x02050604},
{0x0000b0e4, 0x02050700},
{0x0000b0e8, 0x02050701},
{0x0000b0ec, 0x02050702},
{0x0000b0f0, 0x02050703},
{0x0000b0f4, 0x02050704},
{0x0000b0f8, 0x02050705},
{0x0000b0fc, 0x02050708},
{0x0000b100, 0x02050709},
{0x0000b104, 0x0205070a},
{0x0000b108, 0x0205070b},
{0x0000b10c, 0x0205070c},
{0x0000b110, 0x0205070d},
{0x0000b114, 0x02050710},
{0x0000b118, 0x02050711},
{0x0000b11c, 0x02050712},
{0x0000b120, 0x02050713},
{0x0000b124, 0x02050714},
{0x0000b128, 0x02050715},
{0x0000b12c, 0x02050730},
{0x0000b130, 0x02050731},
{0x0000b134, 0x02050732},
{0x0000b138, 0x02050733},
{0x0000b13c, 0x02050734},
{0x0000b140, 0x02050735},
{0x0000b144, 0x02050750},
{0x0000b148, 0x02050751},
{0x0000b14c, 0x02050752},
{0x0000b150, 0x02050753},
{0x0000b154, 0x02050754},
{0x0000b158, 0x02050755},
{0x0000b15c, 0x02050770},
{0x0000b160, 0x02050771},
{0x0000b164, 0x02050772},
{0x0000b168, 0x02050773},
{0x0000b16c, 0x02050774},
{0x0000b170, 0x02050775},
{0x0000b174, 0x00000776},
{0x0000b178, 0x00000776},
{0x0000b17c, 0x00000776},
{0x0000b180, 0x00000776},
{0x0000b184, 0x00000776},
{0x0000b188, 0x00000776},
{0x0000b18c, 0x00000776},
{0x0000b190, 0x00000776},
{0x0000b194, 0x00000776},
{0x0000b198, 0x00000776},
{0x0000b19c, 0x00000776},
{0x0000b1a0, 0x00000776},
{0x0000b1a4, 0x00000776},
{0x0000b1a8, 0x00000776},
{0x0000b1ac, 0x00000776},
{0x0000b1b0, 0x00000776},
{0x0000b1b4, 0x00000776},
{0x0000b1b8, 0x00000776},
{0x0000b1bc, 0x00000776},
{0x0000b1c0, 0x00000776},
{0x0000b1c4, 0x00000776},
{0x0000b1c8, 0x00000776},
{0x0000b1cc, 0x00000776},
{0x0000b1d0, 0x00000776},
{0x0000b1d4, 0x00000776},
{0x0000b1d8, 0x00000776},
{0x0000b1dc, 0x00000776},
{0x0000b1e0, 0x00000776},
{0x0000b1e4, 0x00000776},
{0x0000b1e8, 0x00000776},
{0x0000b1ec, 0x00000776},
{0x0000b1f0, 0x00000776},
{0x0000b1f4, 0x00000776},
{0x0000b1f8, 0x00000776},
{0x0000b1fc, 0x00000776},
};
static const u32 ar9300_2p2_mac_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
......@@ -572,48 +312,6 @@ static const u32 ar9300_2p2_soc_postamble[][5] = {
{0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
};
static const u32 ar9200_merlin_2p2_radio_core[][2] = {
/* Addr allmodes */
{0x00007800, 0x00040000},
{0x00007804, 0xdb005012},
{0x00007808, 0x04924914},
{0x0000780c, 0x21084210},
{0x00007810, 0x6d801300},
{0x00007814, 0x0019beff},
{0x00007818, 0x07e41000},
{0x0000781c, 0x00392000},
{0x00007820, 0x92592480},
{0x00007824, 0x00040000},
{0x00007828, 0xdb005012},
{0x0000782c, 0x04924914},
{0x00007830, 0x21084210},
{0x00007834, 0x6d801300},
{0x00007838, 0x0019beff},
{0x0000783c, 0x07e40000},
{0x00007840, 0x00392000},
{0x00007844, 0x92592480},
{0x00007848, 0x00100000},
{0x0000784c, 0x773f0567},
{0x00007850, 0x54214514},
{0x00007854, 0x12035828},
{0x00007858, 0x92592692},
{0x0000785c, 0x00000000},
{0x00007860, 0x56400000},
{0x00007864, 0x0a8e370e},
{0x00007868, 0xc0102850},
{0x0000786c, 0x812d4000},
{0x00007870, 0x807ec400},
{0x00007874, 0x001b6db0},
{0x00007878, 0x00376b63},
{0x0000787c, 0x06db6db6},
{0x00007880, 0x006d8000},
{0x00007884, 0xffeffffe},
{0x00007888, 0xffeffffe},
{0x0000788c, 0x00010000},
{0x00007890, 0x02060aeb},
{0x00007894, 0x5a108000},
};
static const u32 ar9300_2p2_baseband_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
......
......@@ -87,11 +87,11 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
/* additional clock settings */
if (ah->is_clk_25mhz)
INIT_INI_ARRAY(&ah->iniModesAdditional,
INIT_INI_ARRAY(&ah->iniAdditional,
ar9331_1p1_xtal_25M,
ARRAY_SIZE(ar9331_1p1_xtal_25M), 2);
else
INIT_INI_ARRAY(&ah->iniModesAdditional,
INIT_INI_ARRAY(&ah->iniAdditional,
ar9331_1p1_xtal_40M,
ARRAY_SIZE(ar9331_1p1_xtal_40M), 2);
} else if (AR_SREV_9330_12(ah)) {
......@@ -140,11 +140,11 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
/* additional clock settings */
if (ah->is_clk_25mhz)
INIT_INI_ARRAY(&ah->iniModesAdditional,
INIT_INI_ARRAY(&ah->iniAdditional,
ar9331_1p2_xtal_25M,
ARRAY_SIZE(ar9331_1p2_xtal_25M), 2);
else
INIT_INI_ARRAY(&ah->iniModesAdditional,
INIT_INI_ARRAY(&ah->iniAdditional,
ar9331_1p2_xtal_40M,
ARRAY_SIZE(ar9331_1p2_xtal_40M), 2);
} else if (AR_SREV_9340(ah)) {
......@@ -194,15 +194,16 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar9340Modes_high_ob_db_tx_gain_table_1p0),
5);
INIT_INI_ARRAY(&ah->iniModesAdditional,
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9340Modes_fast_clock_1p0,
ARRAY_SIZE(ar9340Modes_fast_clock_1p0),
3);
INIT_INI_ARRAY(&ah->iniModesAdditional_40M,
ar9340_1p0_radio_core_40M,
ARRAY_SIZE(ar9340_1p0_radio_core_40M),
2);
if (!ah->is_clk_25mhz)
INIT_INI_ARRAY(&ah->iniAdditional,
ar9340_1p0_radio_core_40M,
ARRAY_SIZE(ar9340_1p0_radio_core_40M),
2);
} else if (AR_SREV_9485_11(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
......@@ -321,7 +322,7 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
2);
/* Fast clock modal settings */
INIT_INI_ARRAY(&ah->iniModesAdditional,
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9462_modes_fast_clock_2p0,
ARRAY_SIZE(ar9462_modes_fast_clock_2p0), 3);
......@@ -378,7 +379,7 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
5);
INIT_INI_ARRAY(&ah->iniModesAdditional,
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9580_1p0_modes_fast_clock,
ARRAY_SIZE(ar9580_1p0_modes_fast_clock),
3);
......@@ -445,7 +446,7 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
2);
/* Fast clock modal settings */
INIT_INI_ARRAY(&ah->iniModesAdditional,
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9300Modes_fast_clock_2p2,
ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
3);
......
......@@ -679,18 +679,17 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
* different modal values.
*/
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
REG_WRITE_ARRAY(&ah->iniModesAdditional,
REG_WRITE_ARRAY(&ah->iniModesFastClock,
modesIndex, regWrites);
if (AR_SREV_9330(ah))
REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
if (AR_SREV_9462(ah))
ar9003_hw_prog_ini(ah, &ah->ini_BTCOEX_MAX_TXPWR, 1);
if (chan->channel == 2484)
ar9003_hw_prog_ini(ah, &ah->ini_japan2484, 1);
ah->modes_index = modesIndex;
ar9003_hw_override_ini(ah);
ar9003_hw_set_channel_regs(ah, chan);
......@@ -1320,13 +1319,9 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
* different modal values.
*/
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, regWrites);
if (AR_SREV_9330(ah))
REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
REG_WRITE_ARRAY(&ah->iniModesFastClock, modesIndex, regWrites);
if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
ah->modes_index = modesIndex;
*ini_reloaded = true;
......
......@@ -583,19 +583,13 @@ struct ath_ant_comb {
#define SC_OP_INVALID BIT(0)
#define SC_OP_BEACONS BIT(1)
#define SC_OP_RXAGGR BIT(2)
#define SC_OP_TXAGGR BIT(3)
#define SC_OP_OFFCHANNEL BIT(4)
#define SC_OP_PREAMBLE_SHORT BIT(5)
#define SC_OP_PROTECT_ENABLE BIT(6)
#define SC_OP_RXFLUSH BIT(7)
#define SC_OP_LED_ASSOCIATED BIT(8)
#define SC_OP_LED_ON BIT(9)
#define SC_OP_TSF_RESET BIT(11)
#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
#define SC_OP_BT_SCAN BIT(13)
#define SC_OP_ANI_RUN BIT(14)
#define SC_OP_PRIM_STA_VIF BIT(15)
#define SC_OP_OFFCHANNEL BIT(2)
#define SC_OP_RXFLUSH BIT(3)
#define SC_OP_TSF_RESET BIT(4)
#define SC_OP_BT_PRIORITY_DETECTED BIT(5)
#define SC_OP_BT_SCAN BIT(6)
#define SC_OP_ANI_RUN BIT(7)
#define SC_OP_PRIM_STA_VIF BIT(8)
/* Powersave flags */
#define PS_WAIT_FOR_BEACON BIT(0)
......@@ -617,15 +611,12 @@ struct ath9k_vif_iter_data {
int nstations; /* number of station vifs */
int nwds; /* number of WDS vifs */
int nadhocs; /* number of adhoc vifs */
int nothers; /* number of vifs not specified above. */
};
struct ath_softc {
struct ieee80211_hw *hw;
struct device *dev;
int chan_idx;
int chan_is_ht;
struct survey_info *cur_survey;
struct survey_info survey[ATH9K_NUM_CHANNELS];
......
......@@ -67,7 +67,7 @@ int ath_beaconq_config(struct ath_softc *sc)
* up rate codes, and channel flags. Beacons are always sent out at the
* lowest rate, and are not retried.
*/
static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
static void ath_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
struct ath_buf *bf, int rateidx)
{
struct sk_buff *skb = bf->bf_mpdu;
......@@ -82,7 +82,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
sband = &sc->sbands[common->hw->conf.channel->band];
rate = sband->bitrates[rateidx].hw_value;
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
if (vif->bss_conf.use_short_preamble)
rate |= sband->bitrates[rateidx].hw_value_short;
memset(&info, 0, sizeof(info));
......@@ -209,7 +209,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
}
}
ath_beacon_setup(sc, avp, bf, info->control.rates[0].idx);
ath_beacon_setup(sc, vif, bf, info->control.rates[0].idx);
while (skb) {
ath_tx_cabq(hw, skb);
......
......@@ -738,9 +738,9 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
len += snprintf(buf + len, sizeof(buf) - len,
"VIF-COUNTS: AP: %i STA: %i MESH: %i WDS: %i"
" ADHOC: %i OTHER: %i TOTAL: %hi BEACON-VIF: %hi\n",
" ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
iter_data.naps, iter_data.nstations, iter_data.nmeshes,
iter_data.nwds, iter_data.nadhocs, iter_data.nothers,
iter_data.nwds, iter_data.nadhocs,
sc->nvifs, sc->nbcnvifs);
if (len > sizeof(buf))
......
......@@ -362,7 +362,8 @@ void ath9k_stop_btcoex(struct ath_softc *sc)
ath9k_hw_btcoex_disable(ah);
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
ath9k_btcoex_timer_pause(sc);
ath_mci_flush_profile(&sc->btcoex.mci);
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_MCI)
ath_mci_flush_profile(&sc->btcoex.mci);
}
}
......
......@@ -919,7 +919,6 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
/* setup initial channel */
init_channel = ath9k_cmn_get_curchannel(hw, ah);
ath9k_hw_htc_resetinit(ah);
ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
if (ret) {
ath_err(common,
......
......@@ -449,6 +449,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
ah->slottime = ATH9K_SLOT_TIME_9;
ah->globaltxtimeout = (u32) -1;
ah->power_mode = ATH9K_PM_UNDEFINED;
ah->htc_reset_init = true;
}
static int ath9k_hw_init_macaddr(struct ath_hw *ah)
......@@ -555,7 +556,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
return -EIO;
}
if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
((AR_SREV_9160(ah) || AR_SREV_9280(ah)) &&
!ah->is_pciexpress)) {
......@@ -619,9 +620,6 @@ static int __ath9k_hw_init(struct ath_hw *ah)
if (!ah->is_pciexpress)
ath9k_hw_disablepcie(ah);
if (!AR_SREV_9300_20_OR_LATER(ah))
ar9002_hw_cck_chan14_spread(ah);
r = ath9k_hw_post_init(ah);
if (r)
return r;
......@@ -1521,17 +1519,81 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_check_alive);
/*
* Fast channel change:
* (Change synthesizer based on channel freq without resetting chip)
*
* Don't do FCC when
* - Flag is not set
* - Chip is just coming out of full sleep
* - Channel to be set is same as current channel
* - Channel flags are different, (eg.,moving from 2GHz to 5GHz channel)
*/
static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
int ret;
if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI)
goto fail;
if (ah->chip_fullsleep)
goto fail;
if (!ah->curchan)
goto fail;
if (chan->channel == ah->curchan->channel)
goto fail;
if ((chan->channelFlags & CHANNEL_ALL) !=
(ah->curchan->channelFlags & CHANNEL_ALL))
goto fail;
if (!ath9k_hw_check_alive(ah))
goto fail;
/*
* For AR9462, make sure that calibration data for
* re-using are present.
*/
if (AR_SREV_9462(ah) && (!ah->caldata ||
!ah->caldata->done_txiqcal_once ||
!ah->caldata->done_txclcal_once ||
!ah->caldata->rtt_hist.num_readings))
goto fail;
ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n",
ah->curchan->channel, chan->channel);
ret = ath9k_hw_channel_change(ah, chan);
if (!ret)
goto fail;
ath9k_hw_loadnf(ah, ah->curchan);
ath9k_hw_start_nfcal(ah, true);
if ((ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && ar9003_mci_is_ready(ah))
ar9003_mci_2g5g_switch(ah, true);
if (AR_SREV_9271(ah))
ar9002_hw_load_ani_reg(ah, chan);
return 0;
fail:
return -EINVAL;
}
int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
struct ath9k_hw_cal_data *caldata, bool bChannelChange)
struct ath9k_hw_cal_data *caldata, bool fastcc)
{
struct ath_common *common = ath9k_hw_common(ah);
u32 saveLedState;
struct ath9k_channel *curchan = ah->curchan;
u32 saveDefAntenna;
u32 macStaId1;
u64 tsf = 0;
int i, r;
bool allow_fbs = false, start_mci_reset = false;
bool start_mci_reset = false;
bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI);
bool save_fullsleep = ah->chip_fullsleep;
......@@ -1544,8 +1606,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
return -EIO;
if (curchan && !ah->chip_fullsleep)
ath9k_hw_getnf(ah, curchan);
if (ah->curchan && !ah->chip_fullsleep)
ath9k_hw_getnf(ah, ah->curchan);
ah->caldata = caldata;
if (caldata &&
......@@ -1558,32 +1620,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
}
ah->noise = ath9k_hw_getchan_noise(ah, chan);
if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI)
bChannelChange = false;
if (caldata &&
caldata->done_txiqcal_once &&
caldata->done_txclcal_once &&
caldata->rtt_hist.num_readings)
allow_fbs = true;
if (bChannelChange &&
(!ah->chip_fullsleep) &&
(ah->curchan != NULL) &&
(chan->channel != ah->curchan->channel) &&
(allow_fbs ||
((chan->channelFlags & CHANNEL_ALL) ==
(ah->curchan->channelFlags & CHANNEL_ALL)))) {
if (ath9k_hw_channel_change(ah, chan)) {
ath9k_hw_loadnf(ah, ah->curchan);
ath9k_hw_start_nfcal(ah, true);
if (mci && ar9003_mci_is_ready(ah))
ar9003_mci_2g5g_switch(ah, true);
if (AR_SREV_9271(ah))
ar9002_hw_load_ani_reg(ah, chan);
return 0;
}
if (fastcc) {
r = ath9k_hw_do_fastcc(ah, chan);
if (!r)
return r;
}
if (mci)
......@@ -2389,8 +2429,17 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (AR_SREV_9485_OR_LATER(ah))
ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
}
if (AR_SREV_9462(ah))
pCap->hw_caps |= ATH9K_HW_CAP_RTT | ATH9K_HW_CAP_MCI;
if (AR_SREV_9462(ah)) {
if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE))
pCap->hw_caps |= ATH9K_HW_CAP_MCI;
if (AR_SREV_9462_20(ah))
pCap->hw_caps |= ATH9K_HW_CAP_RTT;
}
return 0;
}
......@@ -2516,12 +2565,6 @@ void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
}
EXPORT_SYMBOL(ath9k_hw_set_gpio);
u32 ath9k_hw_getdefantenna(struct ath_hw *ah)
{
return REG_READ(ah, AR_DEF_ANTENNA) & 0x7;
}
EXPORT_SYMBOL(ath9k_hw_getdefantenna);
void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna)
{
REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
......@@ -2579,6 +2622,7 @@ bool ath9k_hw_phy_disable(struct ath_hw *ah)
return false;
ath9k_hw_init_pll(ah, NULL);
ah->htc_reset_init = true;
return true;
}
EXPORT_SYMBOL(ath9k_hw_phy_disable);
......@@ -2939,12 +2983,6 @@ EXPORT_SYMBOL(ath_gen_timer_isr);
/* HTC */
/********/
void ath9k_hw_htc_resetinit(struct ath_hw *ah)
{
ah->htc_reset_init = true;
}
EXPORT_SYMBOL(ath9k_hw_htc_resetinit);
static struct {
u32 version;
const char * name;
......
......@@ -827,19 +827,14 @@ struct ath_hw {
struct ar5416IniArray iniAddac;
struct ar5416IniArray iniPcieSerdes;
struct ar5416IniArray iniPcieSerdesLowPower;
struct ar5416IniArray iniModesAdditional;
struct ar5416IniArray iniModesAdditional_40M;
struct ar5416IniArray iniModesFastClock;
struct ar5416IniArray iniAdditional;
struct ar5416IniArray iniModesRxGain;
struct ar5416IniArray iniModesTxGain;
struct ar5416IniArray iniModes_9271_1_0_only;
struct ar5416IniArray iniCckfirNormal;
struct ar5416IniArray iniCckfirJapan2484;
struct ar5416IniArray ini_japan2484;
struct ar5416IniArray iniCommon_normal_cck_fir_coeff_9271;
struct ar5416IniArray iniCommon_japan_2484_cck_fir_coeff_9271;
struct ar5416IniArray iniModes_9271_ANI_reg;
struct ar5416IniArray iniModes_high_power_tx_gain_9271;
struct ar5416IniArray iniModes_normal_power_tx_gain_9271;
struct ar5416IniArray ini_radio_post_sys2ant;
struct ar5416IniArray ini_BTCOEX_MAX_TXPWR;
......@@ -924,7 +919,7 @@ const char *ath9k_hw_probe(u16 vendorid, u16 devid);
void ath9k_hw_deinit(struct ath_hw *ah);
int ath9k_hw_init(struct ath_hw *ah);
int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
struct ath9k_hw_cal_data *caldata, bool bChannelChange);
struct ath9k_hw_cal_data *caldata, bool fastcc);
int ath9k_hw_fill_cap_info(struct ath_hw *ah);
u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
......@@ -934,7 +929,6 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio);
void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
u32 ah_signal_type);
void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
u32 ath9k_hw_getdefantenna(struct ath_hw *ah);
void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
/* General Operation */
......@@ -988,9 +982,6 @@ void ath_gen_timer_isr(struct ath_hw *hw);
void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
/* HTC */
void ath9k_hw_htc_resetinit(struct ath_hw *ah);
/* PHY */
void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
u32 *coef_mantissa, u32 *coef_exponent);
......@@ -1000,7 +991,6 @@ void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan);
* Code Specific to AR5008, AR9001 or AR9002,
* we stuff these here to avoid callbacks for AR9003.
*/
void ar9002_hw_cck_chan14_spread(struct ath_hw *ah);
int ar9002_hw_rf_claim(struct ath_hw *ah);
void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
......
......@@ -172,7 +172,7 @@ static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
struct ath_common *common = ath9k_hw_common(ah);
struct ath_softc *sc = (struct ath_softc *) common->priv;
if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
unsigned long flags;
spin_lock_irqsave(&sc->sc_serial_rw, flags);
iowrite32(val, sc->mem + reg_offset);
......@@ -188,7 +188,7 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
struct ath_softc *sc = (struct ath_softc *) common->priv;
u32 val;
if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
unsigned long flags;
spin_lock_irqsave(&sc->sc_serial_rw, flags);
val = ioread32(sc->mem + reg_offset);
......@@ -219,7 +219,7 @@ static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 cl
unsigned long uninitialized_var(flags);
u32 val;
if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
spin_lock_irqsave(&sc->sc_serial_rw, flags);
val = __ath9k_reg_rmw(sc, reg_offset, set, clr);
spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
......@@ -484,19 +484,11 @@ static void ath9k_init_misc(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int i = 0;
setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
sc->config.txpowlimit = ATH_TXPOWER_MAX;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
sc->sc_flags |= SC_OP_TXAGGR;
sc->sc_flags |= SC_OP_RXAGGR;
}
sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
sc->beacon.slottime = ATH9K_SLOT_TIME_9;
for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
......
......@@ -185,13 +185,6 @@ bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)
}
EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);
void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
{
*txqs &= ah->intr_txqs;
ah->intr_txqs &= ~(*txqs);
}
EXPORT_SYMBOL(ath9k_hw_gettxintrtxqs);
bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
const struct ath9k_tx_queue_info *qinfo)
{
......@@ -340,6 +333,15 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
}
EXPORT_SYMBOL(ath9k_hw_setuptxqueue);
static void ath9k_hw_clear_queue_interrupts(struct ath_hw *ah, u32 q)
{
ah->txok_interrupt_mask &= ~(1 << q);
ah->txerr_interrupt_mask &= ~(1 << q);
ah->txdesc_interrupt_mask &= ~(1 << q);
ah->txeol_interrupt_mask &= ~(1 << q);
ah->txurn_interrupt_mask &= ~(1 << q);
}
bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
{
struct ath_common *common = ath9k_hw_common(ah);
......@@ -354,11 +356,7 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
ath_dbg(common, QUEUE, "Release TX queue: %u\n", q);
qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
ah->txok_interrupt_mask &= ~(1 << q);
ah->txerr_interrupt_mask &= ~(1 << q);
ah->txdesc_interrupt_mask &= ~(1 << q);
ah->txeol_interrupt_mask &= ~(1 << q);
ah->txurn_interrupt_mask &= ~(1 << q);
ath9k_hw_clear_queue_interrupts(ah, q);
ath9k_hw_set_txq_interrupts(ah, qi);
return true;
......@@ -510,26 +508,17 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
if (AR_SREV_9300_20_OR_LATER(ah))
REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN);
if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
ath9k_hw_clear_queue_interrupts(ah, q);
if (qi->tqi_qflags & TXQ_FLAG_TXINT_ENABLE) {
ah->txok_interrupt_mask |= 1 << q;
else
ah->txok_interrupt_mask &= ~(1 << q);
if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
ah->txerr_interrupt_mask |= 1 << q;
else
ah->txerr_interrupt_mask &= ~(1 << q);
}
if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
ah->txdesc_interrupt_mask |= 1 << q;
else
ah->txdesc_interrupt_mask &= ~(1 << q);
if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
ah->txeol_interrupt_mask |= 1 << q;
else
ah->txeol_interrupt_mask &= ~(1 << q);
if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
ah->txurn_interrupt_mask |= 1 << q;
else
ah->txurn_interrupt_mask &= ~(1 << q);
ath9k_hw_set_txq_interrupts(ah, qi);
return true;
......@@ -747,8 +736,7 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah)
qi.tqi_cwmax = 0;
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
qi.tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE |
TXQ_FLAG_TXERRINT_ENABLE;
qi.tqi_qflags = TXQ_FLAG_TXINT_ENABLE;
return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
}
......
......@@ -583,8 +583,7 @@ enum ath9k_tx_queue {
#define ATH9K_WME_UPSD 4
enum ath9k_tx_queue_flags {
TXQ_FLAG_TXOKINT_ENABLE = 0x0001,
TXQ_FLAG_TXERRINT_ENABLE = 0x0001,
TXQ_FLAG_TXINT_ENABLE = 0x0001,
TXQ_FLAG_TXDESCINT_ENABLE = 0x0002,
TXQ_FLAG_TXEOLINT_ENABLE = 0x0004,
TXQ_FLAG_TXURNINT_ENABLE = 0x0008,
......@@ -714,7 +713,6 @@ u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
const struct ath9k_tx_queue_info *qinfo);
bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
......
......@@ -118,13 +118,15 @@ void ath9k_ps_restore(struct ath_softc *sc)
if (--sc->ps_usecount != 0)
goto unlock;
if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK))
if (sc->ps_flags & PS_WAIT_FOR_TX_ACK)
goto unlock;
if (sc->ps_idle)
mode = ATH9K_PM_FULL_SLEEP;
else if (sc->ps_enabled &&
!(sc->ps_flags & (PS_WAIT_FOR_BEACON |
PS_WAIT_FOR_CAB |
PS_WAIT_FOR_PSPOLL_DATA |
PS_WAIT_FOR_TX_ACK)))
PS_WAIT_FOR_PSPOLL_DATA)))
mode = ATH9K_PM_NETWORK_SLEEP;
else
goto unlock;
......@@ -332,10 +334,6 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
hchan = ah->curchan;
}
if (fastcc && (ah->chip_fullsleep ||
!ath9k_hw_check_alive(ah)))
fastcc = false;
if (!ath_prepare_reset(sc, retry_tx, flush))
fastcc = false;
......@@ -641,7 +639,8 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
#endif
an->sta = sta;
an->vif = vif;
if (sc->sc_flags & SC_OP_TXAGGR) {
if (sta->ht_cap.ht_supported) {
ath_tx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor);
......@@ -660,7 +659,7 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
an->sta = NULL;
#endif
if (sc->sc_flags & SC_OP_TXAGGR)
if (sta->ht_cap.ht_supported)
ath_tx_node_cleanup(sc, an);
}
......@@ -993,12 +992,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
curchan->center_freq);
ath9k_ps_wakeup(sc);
mutex_lock(&sc->mutex);
/* setup initial channel */
sc->chan_idx = curchan->hw_value;
init_channel = ath9k_cmn_get_curchannel(hw, ah);
/* Reset SERDES registers */
......@@ -1047,9 +1042,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
sc->sc_flags &= ~SC_OP_INVALID;
sc->sc_ah->is_monitoring = false;
/* Disable BMISS interrupt when we're not associated */
ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
if (!ath_complete_reset(sc, false)) {
r = -EIO;
spin_unlock_bh(&sc->sc_pcu_lock);
......@@ -1277,7 +1269,6 @@ static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
iter_data->nwds++;
break;
default:
iter_data->nothers++;
break;
}
}
......@@ -1761,7 +1752,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
struct ath_softc *sc = hw->priv;
struct ath_node *an = (struct ath_node *) sta->drv_priv;
if (!(sc->sc_flags & SC_OP_TXAGGR))
if (!sta->ht_cap.ht_supported)
return;
switch (cmd) {
......@@ -1973,7 +1964,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
ath9k_ps_wakeup(sc);
mutex_lock(&sc->mutex);
if (changed & BSS_CHANGED_BSSID) {
if (changed & BSS_CHANGED_ASSOC) {
ath9k_config_bss(sc, vif);
ath_dbg(common, CONFIG, "BSSID: %pM aid: 0x%x\n",
......@@ -2053,25 +2044,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
ath_beacon_config(sc, vif);
}
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
ath_dbg(common, CONFIG, "BSS Changed PREAMBLE %d\n",
bss_conf->use_short_preamble);
if (bss_conf->use_short_preamble)
sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
else
sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT;
}
if (changed & BSS_CHANGED_ERP_CTS_PROT) {
ath_dbg(common, 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)
sc->sc_flags |= SC_OP_PROTECT_ENABLE;
else
sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
}
mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
}
......@@ -2129,15 +2101,10 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
switch (action) {
case IEEE80211_AMPDU_RX_START:
if (!(sc->sc_flags & SC_OP_RXAGGR))
ret = -ENOTSUPP;
break;
case IEEE80211_AMPDU_RX_STOP:
break;
case IEEE80211_AMPDU_TX_START:
if (!(sc->sc_flags & SC_OP_TXAGGR))
return -EOPNOTSUPP;
ath9k_ps_wakeup(sc);
ret = ath_tx_aggr_start(sc, sta, tid, ssn);
if (!ret)
......
此差异已折叠。
......@@ -982,8 +982,6 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
{
struct ath_hw *ah = common->ah;
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
/*
* everything but the rate is checked here, the rate check is done
* separately to avoid doing two lookups for a rate for each frame.
......@@ -1841,6 +1839,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
if (sc->sc_flags & SC_OP_RXFLUSH)
goto requeue_drop_frag;
memset(rxs, 0, sizeof(struct ieee80211_rx_status));
rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
if (rs.rs_tstamp > tsf_lower &&
unlikely(rs.rs_tstamp - tsf_lower > 0x10000000))
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册