summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-03-06 15:46:08 -0500
committerDavid S. Miller <davem@davemloft.net>2015-03-06 15:46:08 -0500
commit28c0f02ffe8a614bc7e1aa57319a62e7ce700d04 (patch)
tree078ee8553662a5f6d82d31859c160ceab866c2d6 /drivers/net/wireless/ath
parent89650ad0047f039b3c3bc0f6a5823bb9c9738152 (diff)
parent1ca2760fb2c13959fcba794695cd5b306cbfa6a4 (diff)
downloadop-kernel-dev-28c0f02ffe8a614bc7e1aa57319a62e7ce700d04.zip
op-kernel-dev-28c0f02ffe8a614bc7e1aa57319a62e7ce700d04.tar.gz
Merge tag 'wireless-drivers-next-for-davem-2015-03-06' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Major changes: brcmfmac: * sdio improvements * add a debugfs file so users can provide us all the revinfo we could ask for iwlwifi: * add triggers for firmware dump collection * remove support for -9.ucode * new statitics API * rate control improvements ath9k: * add per-vif TX power capability * BT coexistance fixes ath10k: * qca6174: enable STA transmit beamforming (TxBF) support * disable multi-vif power save by default bcma: * enable support for PCIe Gen 2 host devices Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.h2
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c8
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h27
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c101
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c164
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c4
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-ops.h7
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c132
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.h15
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c27
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h18
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mci.c158
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mci.h61
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_wow.c61
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.c43
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/gpio.c95
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c52
-rw-r--r--drivers/net/wireless/ath/ath9k/mci.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h275
-rw-r--r--drivers/net/wireless/ath/ath9k/reg_mci.h310
-rw-r--r--drivers/net/wireless/ath/ath9k/reg_wow.h10
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c42
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c32
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c28
-rw-r--r--drivers/net/wireless/ath/wil6210/ethtool.c34
-rw-r--r--drivers/net/wireless/ath/wil6210/fw.c3
-rw-r--r--drivers/net/wireless/ath/wil6210/fw_inc.c4
-rw-r--r--drivers/net/wireless/ath/wil6210/interrupt.c70
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c166
-rw-r--r--drivers/net/wireless/ath/wil6210/pcie_bus.c22
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c123
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h34
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c9
39 files changed, 1411 insertions, 742 deletions
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index c18647b..0eddb20 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -39,7 +39,7 @@ struct ath10k_ce_pipe;
#define CE_DESC_FLAGS_GATHER (1 << 0)
#define CE_DESC_FLAGS_BYTE_SWAP (1 << 1)
#define CE_DESC_FLAGS_META_DATA_MASK 0xFFFC
-#define CE_DESC_FLAGS_META_DATA_LSB 3
+#define CE_DESC_FLAGS_META_DATA_LSB 2
struct ce_desc {
__le32 addr;
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 310e12b..c0e454b 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -436,16 +436,16 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
static void ath10k_core_free_firmware_files(struct ath10k *ar)
{
- if (ar->board && !IS_ERR(ar->board))
+ if (!IS_ERR(ar->board))
release_firmware(ar->board);
- if (ar->otp && !IS_ERR(ar->otp))
+ if (!IS_ERR(ar->otp))
release_firmware(ar->otp);
- if (ar->firmware && !IS_ERR(ar->firmware))
+ if (!IS_ERR(ar->firmware))
release_firmware(ar->firmware);
- if (ar->cal_file && !IS_ERR(ar->cal_file))
+ if (!IS_ERR(ar->cal_file))
release_firmware(ar->cal_file);
ar->board = NULL;
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index d60e46f..f65310c3 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -159,6 +159,25 @@ struct ath10k_fw_stats_peer {
u32 peer_rx_rate; /* 10x only */
};
+struct ath10k_fw_stats_vdev {
+ struct list_head list;
+
+ u32 vdev_id;
+ u32 beacon_snr;
+ u32 data_snr;
+ u32 num_tx_frames[4];
+ u32 num_rx_frames;
+ u32 num_tx_frames_retries[4];
+ u32 num_tx_frames_failures[4];
+ u32 num_rts_fail;
+ u32 num_rts_success;
+ u32 num_rx_err;
+ u32 num_rx_discard;
+ u32 num_tx_not_acked;
+ u32 tx_rate_history[10];
+ u32 beacon_rssi_history[10];
+};
+
struct ath10k_fw_stats_pdev {
struct list_head list;
@@ -220,6 +239,7 @@ struct ath10k_fw_stats_pdev {
struct ath10k_fw_stats {
struct list_head pdevs;
+ struct list_head vdevs;
struct list_head peers;
};
@@ -288,6 +308,7 @@ struct ath10k_vif {
bool is_started;
bool is_up;
bool spectral_enabled;
+ bool ps;
u32 aid;
u8 bssid[ETH_ALEN];
@@ -413,6 +434,12 @@ enum ath10k_fw_features {
*/
ATH10K_FW_FEATURE_WMI_10_2 = 4,
+ /* Some firmware revisions lack proper multi-interface client powersave
+ * implementation. Enabling PS could result in connection drops,
+ * traffic stalls, etc.
+ */
+ ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT = 5,
+
/* keep last */
ATH10K_FW_FEATURE_COUNT,
};
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index d2281e5..301081d 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -243,6 +243,16 @@ static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head)
}
}
+static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head)
+{
+ struct ath10k_fw_stats_vdev *i, *tmp;
+
+ list_for_each_entry_safe(i, tmp, head, list) {
+ list_del(&i->list);
+ kfree(i);
+ }
+}
+
static void ath10k_debug_fw_stats_peers_free(struct list_head *head)
{
struct ath10k_fw_stats_peer *i, *tmp;
@@ -258,6 +268,7 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
spin_lock_bh(&ar->data_lock);
ar->debug.fw_stats_done = false;
ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
+ ath10k_debug_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers);
spin_unlock_bh(&ar->data_lock);
}
@@ -273,14 +284,27 @@ static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head)
return num;
}
+static size_t ath10k_debug_fw_stats_num_vdevs(struct list_head *head)
+{
+ struct ath10k_fw_stats_vdev *i;
+ size_t num = 0;
+
+ list_for_each_entry(i, head, list)
+ ++num;
+
+ return num;
+}
+
void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
{
struct ath10k_fw_stats stats = {};
bool is_start, is_started, is_end;
size_t num_peers;
+ size_t num_vdevs;
int ret;
INIT_LIST_HEAD(&stats.pdevs);
+ INIT_LIST_HEAD(&stats.vdevs);
INIT_LIST_HEAD(&stats.peers);
spin_lock_bh(&ar->data_lock);
@@ -308,6 +332,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
}
num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers);
+ num_vdevs = ath10k_debug_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
!list_empty(&stats.pdevs));
is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
@@ -330,7 +355,13 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
goto free;
}
+ if (num_vdevs >= BITS_PER_LONG) {
+ ath10k_warn(ar, "dropping fw vdev stats\n");
+ goto free;
+ }
+
list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
+ list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
}
complete(&ar->debug.fw_stats_complete);
@@ -340,6 +371,7 @@ free:
* resources if that is not the case.
*/
ath10k_debug_fw_stats_pdevs_free(&stats.pdevs);
+ ath10k_debug_fw_stats_vdevs_free(&stats.vdevs);
ath10k_debug_fw_stats_peers_free(&stats.peers);
unlock:
@@ -363,7 +395,10 @@ static int ath10k_debug_fw_stats_request(struct ath10k *ar)
reinit_completion(&ar->debug.fw_stats_complete);
- ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
+ ret = ath10k_wmi_request_stats(ar,
+ WMI_STAT_PDEV |
+ WMI_STAT_VDEV |
+ WMI_STAT_PEER);
if (ret) {
ath10k_warn(ar, "could not request stats (%d)\n", ret);
return ret;
@@ -395,8 +430,11 @@ static void ath10k_fw_stats_fill(struct ath10k *ar,
unsigned int len = 0;
unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
const struct ath10k_fw_stats_pdev *pdev;
+ const struct ath10k_fw_stats_vdev *vdev;
const struct ath10k_fw_stats_peer *peer;
size_t num_peers;
+ size_t num_vdevs;
+ int i;
spin_lock_bh(&ar->data_lock);
@@ -408,6 +446,7 @@ static void ath10k_fw_stats_fill(struct ath10k *ar,
}
num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers);
+ num_vdevs = ath10k_debug_fw_stats_num_vdevs(&fw_stats->vdevs);
len += scnprintf(buf + len, buf_len - len, "\n");
len += scnprintf(buf + len, buf_len - len, "%30s\n",
@@ -531,6 +570,65 @@ static void ath10k_fw_stats_fill(struct ath10k *ar,
len += scnprintf(buf + len, buf_len - len, "\n");
len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
+ "ath10k VDEV stats", num_vdevs);
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
+ "=================");
+
+ list_for_each_entry(vdev, &fw_stats->vdevs, list) {
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "vdev id", vdev->vdev_id);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "beacon snr", vdev->beacon_snr);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "data snr", vdev->data_snr);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rx frames", vdev->num_rx_frames);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rts fail", vdev->num_rts_fail);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rts success", vdev->num_rts_success);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rx err", vdev->num_rx_err);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rx discard", vdev->num_rx_discard);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num tx not acked", vdev->num_tx_not_acked);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] %u\n",
+ "num tx frames", i,
+ vdev->num_tx_frames[i]);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_retries); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] %u\n",
+ "num tx frames retries", i,
+ vdev->num_tx_frames_retries[i]);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_failures); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] %u\n",
+ "num tx frames failures", i,
+ vdev->num_tx_frames_failures[i]);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->tx_rate_history); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] 0x%08x\n",
+ "tx rate history", i,
+ vdev->tx_rate_history[i]);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->beacon_rssi_history); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] %u\n",
+ "beacon rssi history", i,
+ vdev->beacon_rssi_history[i]);
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
"ath10k PEER stats", num_peers);
len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
"=================");
@@ -1900,6 +1998,7 @@ int ath10k_debug_create(struct ath10k *ar)
return -ENOMEM;
INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
+ INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
return 0;
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index c1da44f..01a2b38 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -176,7 +176,7 @@ static void ath10k_htt_rx_msdu_buff_replenish(struct ath10k_htt *htt)
* automatically balances load wrt to CPU power.
*
* This probably comes at a cost of lower maximum throughput but
- * improves the avarage and stability. */
+ * improves the average and stability. */
spin_lock_bh(&htt->rx_ring.lock);
num_deficit = htt->rx_ring.fill_level - htt->rx_ring.fill_cnt;
num_to_fill = min(ATH10K_HTT_MAX_NUM_REFILL, num_deficit);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 6c364bb..5d2db06 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -611,7 +611,7 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
ret = ath10k_vdev_setup_sync(ar);
if (ret) {
- ath10k_warn(ar, "failed to synchronize setup for monitor vdev %i: %d\n",
+ ath10k_warn(ar, "failed to synchronize setup for monitor vdev %i start: %d\n",
vdev_id, ret);
return ret;
}
@@ -658,7 +658,7 @@ static int ath10k_monitor_vdev_stop(struct ath10k *ar)
ret = ath10k_vdev_setup_sync(ar);
if (ret)
- ath10k_warn(ar, "failed to synchronise monitor vdev %i: %d\n",
+ ath10k_warn(ar, "failed to synchronize monitor vdev %i stop: %d\n",
ar->monitor_vdev_id, ret);
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %i stopped\n",
@@ -927,8 +927,9 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, bool restart)
ret = ath10k_vdev_setup_sync(ar);
if (ret) {
- ath10k_warn(ar, "failed to synchronise setup for vdev %i: %d\n",
- arg.vdev_id, ret);
+ ath10k_warn(ar,
+ "failed to synchronize setup for vdev %i restart %d: %d\n",
+ arg.vdev_id, restart, ret);
return ret;
}
@@ -966,7 +967,7 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif)
ret = ath10k_vdev_setup_sync(ar);
if (ret) {
- ath10k_warn(ar, "failed to syncronise setup for vdev %i: %d\n",
+ ath10k_warn(ar, "failed to synchronize setup for vdev %i stop: %d\n",
arvif->vdev_id, ret);
return ret;
}
@@ -1253,6 +1254,20 @@ static int ath10k_mac_vif_recalc_ps_poll_count(struct ath10k_vif *arvif)
return 0;
}
+static int ath10k_mac_ps_vif_count(struct ath10k *ar)
+{
+ struct ath10k_vif *arvif;
+ int num = 0;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ list_for_each_entry(arvif, &ar->arvifs, list)
+ if (arvif->ps)
+ num++;
+
+ return num;
+}
+
static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
@@ -1262,13 +1277,24 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
enum wmi_sta_ps_mode psmode;
int ret;
int ps_timeout;
+ bool enable_ps;
lockdep_assert_held(&arvif->ar->conf_mutex);
if (arvif->vif->type != NL80211_IFTYPE_STATION)
return 0;
- if (vif->bss_conf.ps) {
+ enable_ps = arvif->ps;
+
+ if (enable_ps && ath10k_mac_ps_vif_count(ar) > 1 &&
+ !test_bit(ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT,
+ ar->fw_features)) {
+ ath10k_warn(ar, "refusing to enable ps on vdev %i: not supported by fw\n",
+ arvif->vdev_id);
+ enable_ps = false;
+ }
+
+ if (enable_ps) {
psmode = WMI_STA_PS_MODE_ENABLED;
param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
@@ -1781,6 +1807,68 @@ static int ath10k_setup_peer_smps(struct ath10k *ar, struct ath10k_vif *arvif,
ath10k_smps_map[smps]);
}
+static int ath10k_mac_vif_recalc_txbf(struct ath10k *ar,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta_vht_cap vht_cap)
+{
+ struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ int ret;
+ u32 param;
+ u32 value;
+
+ if (!(ar->vht_cap_info &
+ (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
+ IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
+ IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
+ IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)))
+ return 0;
+
+ param = ar->wmi.vdev_param->txbf;
+ value = 0;
+
+ if (WARN_ON(param == WMI_VDEV_PARAM_UNSUPPORTED))
+ return 0;
+
+ /* The following logic is correct. If a remote STA advertises support
+ * for being a beamformer then we should enable us being a beamformee.
+ */
+
+ if (ar->vht_cap_info &
+ (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
+ IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
+ if (vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)
+ value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
+
+ if (vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)
+ value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFEE;
+ }
+
+ if (ar->vht_cap_info &
+ (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
+ IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
+ if (vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)
+ value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
+
+ if (vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)
+ value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFER;
+ }
+
+ if (value & WMI_VDEV_PARAM_TXBF_MU_TX_BFEE)
+ value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
+
+ if (value & WMI_VDEV_PARAM_TXBF_MU_TX_BFER)
+ value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
+
+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param, value);
+ if (ret) {
+ ath10k_warn(ar, "failed to submit vdev param txbf 0x%x: %d\n",
+ value, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
/* can be called only in mac80211 callbacks due to `key_count` usage */
static void ath10k_bss_assoc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -1789,6 +1877,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
struct ieee80211_sta_ht_cap ht_cap;
+ struct ieee80211_sta_vht_cap vht_cap;
struct wmi_peer_assoc_complete_arg peer_arg;
struct ieee80211_sta *ap_sta;
int ret;
@@ -1811,6 +1900,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
/* ap_sta must be accessed only within rcu section which must be left
* before calling ath10k_setup_peer_smps() which might sleep. */
ht_cap = ap_sta->ht_cap;
+ vht_cap = ap_sta->vht_cap;
ret = ath10k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg);
if (ret) {
@@ -1836,6 +1926,13 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
return;
}
+ ret = ath10k_mac_vif_recalc_txbf(ar, vif, vht_cap);
+ if (ret) {
+ ath10k_warn(ar, "failed to recalc txbf for vdev %i on bss %pM: %d\n",
+ arvif->vdev_id, bss_conf->bssid, ret);
+ return;
+ }
+
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac vdev %d up (associated) bssid %pM aid %d\n",
arvif->vdev_id, bss_conf->bssid, bss_conf->aid);
@@ -1853,6 +1950,18 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
}
arvif->is_up = true;
+
+ /* Workaround: Some firmware revisions (tested with qca6174
+ * WLAN.RM.2.0-00073) have buggy powersave state machine and must be
+ * poked with peer param command.
+ */
+ ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, arvif->bssid,
+ WMI_PEER_DUMMY_VAR, 1);
+ if (ret) {
+ ath10k_warn(ar, "failed to poke peer %pM param for ps workaround on vdev %i: %d\n",
+ arvif->bssid, arvif->vdev_id, ret);
+ return;
+ }
}
static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
@@ -1860,6 +1969,7 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
{
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ieee80211_sta_vht_cap vht_cap = {};
int ret;
lockdep_assert_held(&ar->conf_mutex);
@@ -1874,6 +1984,13 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
arvif->def_wep_key_idx = -1;
+ ret = ath10k_mac_vif_recalc_txbf(ar, vif, vht_cap);
+ if (ret) {
+ ath10k_warn(ar, "failed to recalc txbf for vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ return;
+ }
+
arvif->is_up = false;
}
@@ -2554,6 +2671,17 @@ static int ath10k_start_scan(struct ath10k *ar,
return -ETIMEDOUT;
}
+ /* If we failed to start the scan, return error code at
+ * this point. This is probably due to some issue in the
+ * firmware, but no need to wedge the driver due to that...
+ */
+ spin_lock_bh(&ar->data_lock);
+ if (ar->scan.state == ATH10K_SCAN_IDLE) {
+ spin_unlock_bh(&ar->data_lock);
+ return -EINVAL;
+ }
+ spin_unlock_bh(&ar->data_lock);
+
/* Add a 200ms margin to account for event/command processing */
ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
msecs_to_jiffies(arg->max_scan_time+200));
@@ -3323,9 +3451,10 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
list_del(&arvif->list);
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
- ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, vif->addr);
+ ret = ath10k_wmi_peer_delete(arvif->ar, arvif->vdev_id,
+ vif->addr);
if (ret)
- ath10k_warn(ar, "failed to remove peer for AP vdev %i: %d\n",
+ ath10k_warn(ar, "failed to submit AP self-peer removal on vdev %i: %d\n",
arvif->vdev_id, ret);
kfree(arvif->u.ap.noa_data);
@@ -3339,6 +3468,21 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
ath10k_warn(ar, "failed to delete WMI vdev %i: %d\n",
arvif->vdev_id, ret);
+ /* Some firmware revisions don't notify host about self-peer removal
+ * until after associated vdev is deleted.
+ */
+ if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
+ ret = ath10k_wait_for_peer_deleted(ar, arvif->vdev_id,
+ vif->addr);
+ if (ret)
+ ath10k_warn(ar, "failed to remove AP self-peer on vdev %i: %d\n",
+ arvif->vdev_id, ret);
+
+ spin_lock_bh(&ar->data_lock);
+ ar->num_peers--;
+ spin_unlock_bh(&ar->data_lock);
+ }
+
ath10k_peer_cleanup(ar, arvif->vdev_id);
mutex_unlock(&ar->conf_mutex);
@@ -3534,7 +3678,9 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_PS) {
- ret = ath10k_mac_vif_setup_ps(arvif);
+ arvif->ps = vif->bss_conf.ps;
+
+ ret = ath10k_config_ps(ar);
if (ret)
ath10k_warn(ar, "failed to setup ps on vdev %i: %d\n",
arvif->vdev_id, ret);
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index e6972b0..7681237 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -104,7 +104,7 @@ static const struct ce_attr host_ce_config_wlan[] = {
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
- .src_sz_max = 512,
+ .src_sz_max = 2048,
.dest_nentries = 512,
},
@@ -174,7 +174,7 @@ static const struct ce_pipe_config target_ce_config_wlan[] = {
.pipenum = __cpu_to_le32(1),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(512),
+ .nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
index 04dc4b9..c8b64e7 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
@@ -110,8 +110,7 @@ struct wmi_ops {
bool deliver_cab);
struct sk_buff *(*gen_pdev_set_wmm)(struct ath10k *ar,
const struct wmi_wmm_params_all_arg *arg);
- struct sk_buff *(*gen_request_stats)(struct ath10k *ar,
- enum wmi_stats_id stats_id);
+ struct sk_buff *(*gen_request_stats)(struct ath10k *ar, u32 stats_mask);
struct sk_buff *(*gen_force_fw_hang)(struct ath10k *ar,
enum wmi_force_fw_hang_type type,
u32 delay_ms);
@@ -816,14 +815,14 @@ ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
}
static inline int
-ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id)
+ath10k_wmi_request_stats(struct ath10k *ar, u32 stats_mask)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_request_stats)
return -EOPNOTSUPP;
- skb = ar->wmi.ops->gen_request_stats(ar, stats_id);
+ skb = ar->wmi.ops->gen_request_stats(ar, stats_mask);
if (IS_ERR(skb))
return PTR_ERR(skb);
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 71614ba..ee0c5f6 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -869,16 +869,57 @@ static int ath10k_wmi_tlv_op_pull_rdy_ev(struct ath10k *ar,
return 0;
}
+static void ath10k_wmi_tlv_pull_vdev_stats(const struct wmi_tlv_vdev_stats *src,
+ struct ath10k_fw_stats_vdev *dst)
+{
+ int i;
+
+ dst->vdev_id = __le32_to_cpu(src->vdev_id);
+ dst->beacon_snr = __le32_to_cpu(src->beacon_snr);
+ dst->data_snr = __le32_to_cpu(src->data_snr);
+ dst->num_rx_frames = __le32_to_cpu(src->num_rx_frames);
+ dst->num_rts_fail = __le32_to_cpu(src->num_rts_fail);
+ dst->num_rts_success = __le32_to_cpu(src->num_rts_success);
+ dst->num_rx_err = __le32_to_cpu(src->num_rx_err);
+ dst->num_rx_discard = __le32_to_cpu(src->num_rx_discard);
+ dst->num_tx_not_acked = __le32_to_cpu(src->num_tx_not_acked);
+
+ for (i = 0; i < ARRAY_SIZE(src->num_tx_frames); i++)
+ dst->num_tx_frames[i] =
+ __le32_to_cpu(src->num_tx_frames[i]);
+
+ for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_retries); i++)
+ dst->num_tx_frames_retries[i] =
+ __le32_to_cpu(src->num_tx_frames_retries[i]);
+
+ for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_failures); i++)
+ dst->num_tx_frames_failures[i] =
+ __le32_to_cpu(src->num_tx_frames_failures[i]);
+
+ for (i = 0; i < ARRAY_SIZE(src->tx_rate_history); i++)
+ dst->tx_rate_history[i] =
+ __le32_to_cpu(src->tx_rate_history[i]);
+
+ for (i = 0; i < ARRAY_SIZE(src->beacon_rssi_history); i++)
+ dst->beacon_rssi_history[i] =
+ __le32_to_cpu(src->beacon_rssi_history[i]);
+}
+
static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
struct sk_buff *skb,
struct ath10k_fw_stats *stats)
{
const void **tb;
- const struct wmi_stats_event *ev;
+ const struct wmi_tlv_stats_ev *ev;
const void *data;
- u32 num_pdev_stats, num_vdev_stats, num_peer_stats;
+ u32 num_pdev_stats;
+ u32 num_vdev_stats;
+ u32 num_peer_stats;
+ u32 num_bcnflt_stats;
+ u32 num_chan_stats;
size_t data_len;
int ret;
+ int i;
tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
if (IS_ERR(tb)) {
@@ -899,8 +940,73 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
+ num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats);
+ num_chan_stats = __le32_to_cpu(ev->num_chan_stats);
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i\n",
+ num_pdev_stats, num_vdev_stats, num_peer_stats,
+ num_bcnflt_stats, num_chan_stats);
+
+ for (i = 0; i < num_pdev_stats; i++) {
+ const struct wmi_pdev_stats *src;
+ struct ath10k_fw_stats_pdev *dst;
+
+ src = data;
+ if (data_len < sizeof(*src))
+ return -EPROTO;
+
+ data += sizeof(*src);
+ data_len -= sizeof(*src);
+
+ dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ if (!dst)
+ continue;
+
+ ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
+ ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst);
+ ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
+ list_add_tail(&dst->list, &stats->pdevs);
+ }
+
+ for (i = 0; i < num_vdev_stats; i++) {
+ const struct wmi_tlv_vdev_stats *src;
+ struct ath10k_fw_stats_vdev *dst;
+
+ src = data;
+ if (data_len < sizeof(*src))
+ return -EPROTO;
+
+ data += sizeof(*src);
+ data_len -= sizeof(*src);
+
+ dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ if (!dst)
+ continue;
- WARN_ON(1); /* FIXME: not implemented yet */
+ ath10k_wmi_tlv_pull_vdev_stats(src, dst);
+ list_add_tail(&dst->list, &stats->vdevs);
+ }
+
+ for (i = 0; i < num_peer_stats; i++) {
+ const struct wmi_10x_peer_stats *src;
+ struct ath10k_fw_stats_peer *dst;
+
+ src = data;
+ if (data_len < sizeof(*src))
+ return -EPROTO;
+
+ data += sizeof(*src);
+ data_len -= sizeof(*src);
+
+ dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ if (!dst)
+ continue;
+
+ ath10k_wmi_pull_peer_stats(&src->old, dst);
+ dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
+ list_add_tail(&dst->list, &stats->peers);
+ }
kfree(tb);
return 0;
@@ -1604,14 +1710,12 @@ ath10k_wmi_tlv_op_gen_vdev_wmm_conf(struct ath10k *ar, u32 vdev_id,
const struct wmi_wmm_params_all_arg *arg)
{
struct wmi_tlv_vdev_set_wmm_cmd *cmd;
- struct wmi_wmm_params *wmm;
struct wmi_tlv *tlv;
struct sk_buff *skb;
size_t len;
void *ptr;
- len = (sizeof(*tlv) + sizeof(*cmd)) +
- (4 * (sizeof(*tlv) + sizeof(*wmm)));
+ len = sizeof(*tlv) + sizeof(*cmd);
skb = ath10k_wmi_alloc_skb(ar, len);
if (!skb)
return ERR_PTR(-ENOMEM);
@@ -1623,13 +1727,10 @@ ath10k_wmi_tlv_op_gen_vdev_wmm_conf(struct ath10k *ar, u32 vdev_id,
cmd = (void *)tlv->value;
cmd->vdev_id = __cpu_to_le32(vdev_id);
- ptr += sizeof(*tlv);
- ptr += sizeof(*cmd);
-
- ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_be);
- ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_bk);
- ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vi);
- ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vo);
+ ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[0].params, &arg->ac_be);
+ ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[1].params, &arg->ac_bk);
+ ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[2].params, &arg->ac_vi);
+ ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[3].params, &arg->ac_vo);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev wmm conf\n");
return skb;
@@ -2080,8 +2181,7 @@ ath10k_wmi_tlv_op_gen_pdev_set_wmm(struct ath10k *ar,
}
static struct sk_buff *
-ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar,
- enum wmi_stats_id stats_id)
+ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar, u32 stats_mask)
{
struct wmi_request_stats_cmd *cmd;
struct wmi_tlv *tlv;
@@ -2095,7 +2195,7 @@ ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar,
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_REQUEST_STATS_CMD);
tlv->len = __cpu_to_le16(sizeof(*cmd));
cmd = (void *)tlv->value;
- cmd->stats_id = __cpu_to_le32(stats_id);
+ cmd->stats_id = __cpu_to_le32(stats_mask);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request stats\n");
return skb;
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index de68fe7..a6c8280 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -1302,8 +1302,14 @@ struct wmi_tlv_pdev_set_wmm_cmd {
__le32 dg_type; /* no idea.. */
} __packed;
+struct wmi_tlv_vdev_wmm_params {
+ __le32 dummy;
+ struct wmi_wmm_params params;
+} __packed;
+
struct wmi_tlv_vdev_set_wmm_cmd {
__le32 vdev_id;
+ struct wmi_tlv_vdev_wmm_params vdev_wmm_params[4];
} __packed;
struct wmi_tlv_phyerr_ev {
@@ -1439,6 +1445,15 @@ struct wmi_tlv_sta_keepalive_cmd {
__le32 interval; /* in seconds */
} __packed;
+struct wmi_tlv_stats_ev {
+ __le32 stats_id; /* WMI_STAT_ */
+ __le32 num_pdev_stats;
+ __le32 num_vdev_stats;
+ __le32 num_peer_stats;
+ __le32 num_bcnflt_stats;
+ __le32 num_chan_stats;
+} __packed;
+
void ath10k_wmi_tlv_attach(struct ath10k *ar);
#endif
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index aeea1c7..c7ea77e 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1125,6 +1125,25 @@ static void ath10k_wmi_event_scan_started(struct ath10k *ar)
}
}
+static void ath10k_wmi_event_scan_start_failed(struct ath10k *ar)
+{
+ lockdep_assert_held(&ar->data_lock);
+
+ switch (ar->scan.state) {
+ case ATH10K_SCAN_IDLE:
+ case ATH10K_SCAN_RUNNING:
+ case ATH10K_SCAN_ABORTING:
+ ath10k_warn(ar, "received scan start failed event in an invalid scan state: %s (%d)\n",
+ ath10k_scan_state_str(ar->scan.state),
+ ar->scan.state);
+ break;
+ case ATH10K_SCAN_STARTING:
+ complete(&ar->scan.started);
+ __ath10k_scan_finish(ar);
+ break;
+ }
+}
+
static void ath10k_wmi_event_scan_completed(struct ath10k *ar)
{
lockdep_assert_held(&ar->data_lock);
@@ -1292,6 +1311,7 @@ int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
break;
case WMI_SCAN_EVENT_START_FAILED:
ath10k_warn(ar, "received scan start failure event\n");
+ ath10k_wmi_event_scan_start_failed(ar);
break;
case WMI_SCAN_EVENT_DEQUEUED:
case WMI_SCAN_EVENT_PREEMPTED:
@@ -4954,7 +4974,7 @@ ath10k_wmi_op_gen_pdev_set_wmm(struct ath10k *ar,
}
static struct sk_buff *
-ath10k_wmi_op_gen_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id)
+ath10k_wmi_op_gen_request_stats(struct ath10k *ar, u32 stats_mask)
{
struct wmi_request_stats_cmd *cmd;
struct sk_buff *skb;
@@ -4964,9 +4984,10 @@ ath10k_wmi_op_gen_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id)
return ERR_PTR(-ENOMEM);
cmd = (struct wmi_request_stats_cmd *)skb->data;
- cmd->stats_id = __cpu_to_le32(stats_id);
+ cmd->stats_id = __cpu_to_le32(stats_mask);
- ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi request stats %d\n", (int)stats_id);
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi request stats 0x%08x\n",
+ stats_mask);
return skb;
}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 20ce360..adf935b 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -3057,8 +3057,12 @@ struct wmi_pdev_stats_peer {
} __packed;
enum wmi_stats_id {
- WMI_REQUEST_PEER_STAT = 0x01,
- WMI_REQUEST_AP_STAT = 0x02
+ WMI_STAT_PEER = BIT(0),
+ WMI_STAT_AP = BIT(1),
+ WMI_STAT_PDEV = BIT(2),
+ WMI_STAT_VDEV = BIT(3),
+ WMI_STAT_BCNFLT = BIT(4),
+ WMI_STAT_VDEV_RATE = BIT(5),
};
struct wlan_inst_rssi_args {
@@ -3093,7 +3097,7 @@ struct wmi_pdev_suspend_cmd {
} __packed;
struct wmi_stats_event {
- __le32 stats_id; /* %WMI_REQUEST_ */
+ __le32 stats_id; /* WMI_STAT_ */
/*
* number of pdev stats event structures
* (wmi_pdev_stats) 0 or 1
@@ -3745,6 +3749,11 @@ enum wmi_10x_vdev_param {
WMI_10X_VDEV_PARAM_VHT80_RATEMASK,
};
+#define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0)
+#define WMI_VDEV_PARAM_TXBF_MU_TX_BFEE BIT(1)
+#define WMI_VDEV_PARAM_TXBF_SU_TX_BFER BIT(2)
+#define WMI_VDEV_PARAM_TXBF_MU_TX_BFER BIT(3)
+
/* slot time long */
#define WMI_VDEV_SLOT_TIME_LONG 0x1
/* slot time short */
@@ -4436,7 +4445,8 @@ enum wmi_peer_param {
WMI_PEER_AUTHORIZE = 0x3,
WMI_PEER_CHAN_WIDTH = 0x4,
WMI_PEER_NSS = 0x5,
- WMI_PEER_USE_4ADDR = 0x6
+ WMI_PEER_USE_4ADDR = 0x6,
+ WMI_PEER_DUMMY_VAR = 0xff, /* dummy parameter for STA PS workaround */
};
struct wmi_peer_set_param_cmd {
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
index 7b94a6c..bd169fa 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
@@ -284,12 +284,12 @@ static void ar9003_mci_prep_interface(struct ath_hw *ah)
AR_MCI_INTERRUPT_RX_MSG_CONT_RST);
REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI);
- if (mci->is_2g) {
+ if (mci->is_2g && MCI_ANT_ARCH_PA_LNA_SHARED(mci)) {
ar9003_mci_send_lna_transfer(ah, true);
udelay(5);
}
- if ((mci->is_2g && !mci->update_2g5g)) {
+ if (mci->is_2g && !mci->update_2g5g && MCI_ANT_ARCH_PA_LNA_SHARED(mci)) {
if (ar9003_mci_wait_for_interrupt(ah,
AR_MCI_INTERRUPT_RX_MSG_RAW,
AR_MCI_INTERRUPT_RX_MSG_LNA_INFO,
@@ -593,7 +593,7 @@ static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
if (!time_out)
break;
- offset = ar9003_mci_get_next_gpm_offset(ah, false, &more_data);
+ offset = ar9003_mci_get_next_gpm_offset(ah, &more_data);
if (offset == MCI_GPM_INVALID)
continue;
@@ -657,7 +657,7 @@ static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
time_out = 0;
while (more_data == MCI_GPM_MORE) {
- offset = ar9003_mci_get_next_gpm_offset(ah, false, &more_data);
+ offset = ar9003_mci_get_next_gpm_offset(ah, &more_data);
if (offset == MCI_GPM_INVALID)
break;
@@ -771,8 +771,14 @@ exit:
static void ar9003_mci_mute_bt(struct ath_hw *ah)
{
+ struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+
/* disable all MCI messages */
REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000);
+ REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff);
+ REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xffffffff);
+ REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xffffffff);
+ REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xffffffff);
REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
/* wait pending HW messages to flush out */
@@ -783,9 +789,10 @@ static void ar9003_mci_mute_bt(struct ath_hw *ah)
* 1. reset not after resuming from full sleep
* 2. before reset MCI RX, to quiet BT and avoid MCI RX misalignment
*/
- ar9003_mci_send_lna_take(ah, true);
-
- udelay(5);
+ if (MCI_ANT_ARCH_PA_LNA_SHARED(mci)) {
+ ar9003_mci_send_lna_take(ah, true);
+ udelay(5);
+ }
ar9003_mci_send_sys_sleeping(ah, true);
}
@@ -821,6 +828,80 @@ static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable)
AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1);
}
+static void ar9003_mci_stat_setup(struct ath_hw *ah)
+{
+ struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+
+ if (!AR_SREV_9565(ah))
+ return;
+
+ if (mci->config & ATH_MCI_CONFIG_MCI_STAT_DBG) {
+ REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL,
+ AR_MCI_DBG_CNT_CTRL_ENABLE, 1);
+ REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL,
+ AR_MCI_DBG_CNT_CTRL_BT_LINKID,
+ MCI_STAT_ALL_BT_LINKID);
+ } else {
+ REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL,
+ AR_MCI_DBG_CNT_CTRL_ENABLE, 0);
+ }
+}
+
+static void ar9003_mci_set_btcoex_ctrl_9565_1ANT(struct ath_hw *ah)
+{
+ u32 regval;
+
+ regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) |
+ SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
+ SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
+ SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
+ SM(1, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
+ SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
+ SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
+ SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
+ SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
+
+ REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
+ AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x1);
+ REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
+}
+
+static void ar9003_mci_set_btcoex_ctrl_9565_2ANT(struct ath_hw *ah)
+{
+ u32 regval;
+
+ regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) |
+ SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
+ SM(0, AR_BTCOEX_CTRL_PA_SHARED) |
+ SM(0, AR_BTCOEX_CTRL_LNA_SHARED) |
+ SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
+ SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
+ SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
+ SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
+ SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
+
+ REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
+ AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x0);
+ REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
+}
+
+static void ar9003_mci_set_btcoex_ctrl_9462(struct ath_hw *ah)
+{
+ u32 regval;
+
+ regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) |
+ SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
+ SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
+ SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
+ SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
+ SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
+ SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
+ SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
+ SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
+
+ REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
+}
+
int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
bool is_full_sleep)
{
@@ -831,11 +912,6 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
ath_dbg(common, MCI, "MCI Reset (full_sleep = %d, is_2g = %d)\n",
is_full_sleep, is_2g);
- if (!mci->gpm_addr && !mci->sched_addr) {
- ath_err(common, "MCI GPM and schedule buffers are not allocated\n");
- return -ENOMEM;
- }
-
if (REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) {
ath_err(common, "BTCOEX control register is dead\n");
return -EINVAL;
@@ -850,26 +926,17 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
* To avoid MCI state machine be affected by incoming remote MCI msgs,
* MCI mode will be enabled later, right before reset the MCI TX and RX.
*/
-
- regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) |
- SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
- SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
- SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
- SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
- SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
- SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
if (AR_SREV_9565(ah)) {
- regval |= SM(1, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
- SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK);
- REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
- AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x1);
+ u8 ant = MS(mci->config, ATH_MCI_CONFIG_ANT_ARCH);
+
+ if (ant == ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_SHARED)
+ ar9003_mci_set_btcoex_ctrl_9565_1ANT(ah);
+ else
+ ar9003_mci_set_btcoex_ctrl_9565_2ANT(ah);
} else {
- regval |= SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
- SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK);
+ ar9003_mci_set_btcoex_ctrl_9462(ah);
}
- REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
-
if (is_2g && !(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
ar9003_mci_osla_setup(ah, true);
else
@@ -926,23 +993,26 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX);
REG_WRITE(ah, AR_MCI_COMMAND2, regval);
- ar9003_mci_get_next_gpm_offset(ah, true, NULL);
+ /* Init GPM offset after MCI Reset Rx */
+ ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET);
REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE,
(SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) |
SM(0x0000, AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM)));
- REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
- AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
+ if (MCI_ANT_ARCH_PA_LNA_SHARED(mci))
+ REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
+ AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
+ else
+ REG_SET_BIT(ah, AR_MCI_TX_CTRL,
+ AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
ar9003_mci_observation_set_up(ah);
mci->ready = true;
ar9003_mci_prep_interface(ah);
+ ar9003_mci_stat_setup(ah);
- if (AR_SREV_9565(ah))
- REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL,
- AR_MCI_DBG_CNT_CTRL_ENABLE, 0);
if (en_int)
ar9003_mci_enable_interrupt(ah);
@@ -1218,6 +1288,14 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)
}
value &= AR_BTCOEX_CTRL_MCI_MODE_EN;
break;
+ case MCI_STATE_INIT_GPM_OFFSET:
+ value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
+
+ if (value < mci->gpm_len)
+ mci->gpm_idx = value;
+ else
+ mci->gpm_idx = 0;
+ break;
case MCI_STATE_LAST_SCHD_MSG_OFFSET:
value = MS(REG_READ(ah, AR_MCI_RX_STATUS),
AR_MCI_RX_LAST_SCHD_MSG_INDEX);
@@ -1364,21 +1442,11 @@ void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
mci->gpm_idx = 0;
}
-u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more)
+u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, u32 *more)
{
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
u32 offset, more_gpm = 0, gpm_ptr;
- if (first) {
- gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
-
- if (gpm_ptr >= mci->gpm_len)
- gpm_ptr = 0;
-
- mci->gpm_idx = gpm_ptr;
- return gpm_ptr;
- }
-
/*
* This could be useful to avoid new GPM message interrupt which
* may lead to spurious interrupt after power sleep, or multiple
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/drivers/net/wireless/ath/ath9k/ar9003_mci.h
index 66d7ab9..e288611 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.h
@@ -92,14 +92,36 @@ enum mci_gpm_coex_bt_update_flags_op {
#define ATH_MCI_CONFIG_CLK_DIV 0x00003000
#define ATH_MCI_CONFIG_CLK_DIV_S 12
#define ATH_MCI_CONFIG_DISABLE_TUNING 0x00004000
+#define ATH_MCI_CONFIG_DISABLE_AIC 0x00008000
+#define ATH_MCI_CONFIG_AIC_CAL_NUM_CHAN 0x007f0000
+#define ATH_MCI_CONFIG_AIC_CAL_NUM_CHAN_S 16
+#define ATH_MCI_CONFIG_NO_QUIET_ACK 0x00800000
+#define ATH_MCI_CONFIG_NO_QUIET_ACK_S 23
+#define ATH_MCI_CONFIG_ANT_ARCH 0x07000000
+#define ATH_MCI_CONFIG_ANT_ARCH_S 24
+#define ATH_MCI_CONFIG_FORCE_QUIET_ACK 0x08000000
+#define ATH_MCI_CONFIG_FORCE_QUIET_ACK_S 27
+#define ATH_MCI_CONFIG_FORCE_2CHAIN_ACK 0x10000000
+#define ATH_MCI_CONFIG_MCI_STAT_DBG 0x20000000
#define ATH_MCI_CONFIG_MCI_WEIGHT_DBG 0x40000000
#define ATH_MCI_CONFIG_DISABLE_MCI 0x80000000
#define ATH_MCI_CONFIG_MCI_OBS_MASK (ATH_MCI_CONFIG_MCI_OBS_MCI | \
ATH_MCI_CONFIG_MCI_OBS_TXRX | \
ATH_MCI_CONFIG_MCI_OBS_BT)
+
#define ATH_MCI_CONFIG_MCI_OBS_GPIO 0x0000002F
+#define ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_NON_SHARED 0x00
+#define ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_SHARED 0x01
+#define ATH_MCI_ANT_ARCH_2_ANT_PA_LNA_NON_SHARED 0x02
+#define ATH_MCI_ANT_ARCH_2_ANT_PA_LNA_SHARED 0x03
+#define ATH_MCI_ANT_ARCH_3_ANT 0x04
+
+#define MCI_ANT_ARCH_PA_LNA_SHARED(mci) \
+ ((MS(mci->config, ATH_MCI_CONFIG_ANT_ARCH) == ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_SHARED) || \
+ (MS(mci->config, ATH_MCI_CONFIG_ANT_ARCH) == ATH_MCI_ANT_ARCH_2_ANT_PA_LNA_SHARED))
+
enum mci_message_header { /* length of payload */
MCI_LNA_CTRL = 0x10, /* len = 0 */
MCI_CONT_NACK = 0x20, /* len = 0 */
@@ -188,20 +210,55 @@ enum mci_bt_state {
MCI_BT_CAL
};
+enum mci_ps_state {
+ MCI_PS_DISABLE,
+ MCI_PS_ENABLE,
+ MCI_PS_ENABLE_OFF,
+ MCI_PS_ENABLE_ON
+};
+
/* Type of state query */
enum mci_state_type {
MCI_STATE_ENABLE,
+ MCI_STATE_INIT_GPM_OFFSET,
+ MCI_STATE_CHECK_GPM_OFFSET,
+ MCI_STATE_NEXT_GPM_OFFSET,
+ MCI_STATE_LAST_GPM_OFFSET,
+ MCI_STATE_BT,
+ MCI_STATE_SET_BT_SLEEP,
MCI_STATE_SET_BT_AWAKE,
+ MCI_STATE_SET_BT_CAL_START,
+ MCI_STATE_SET_BT_CAL,
MCI_STATE_LAST_SCHD_MSG_OFFSET,
MCI_STATE_REMOTE_SLEEP,
+ MCI_STATE_CONT_STATUS,
MCI_STATE_RESET_REQ_WAKE,
MCI_STATE_SEND_WLAN_COEX_VERSION,
+ MCI_STATE_SET_BT_COEX_VERSION,
+ MCI_STATE_SEND_WLAN_CHANNELS,
MCI_STATE_SEND_VERSION_QUERY,
MCI_STATE_SEND_STATUS_QUERY,
+ MCI_STATE_NEED_FLUSH_BT_INFO,
+ MCI_STATE_SET_CONCUR_TX_PRI,
MCI_STATE_RECOVER_RX,
MCI_STATE_NEED_FTP_STOMP,
+ MCI_STATE_NEED_TUNING,
+ MCI_STATE_NEED_STAT_DEBUG,
+ MCI_STATE_SHARED_CHAIN_CONCUR_TX,
+ MCI_STATE_AIC_CAL,
+ MCI_STATE_AIC_START,
+ MCI_STATE_AIC_CAL_RESET,
+ MCI_STATE_AIC_CAL_SINGLE,
+ MCI_STATE_IS_AR9462,
+ MCI_STATE_IS_AR9565_1ANT,
+ MCI_STATE_IS_AR9565_2ANT,
+ MCI_STATE_WLAN_WEAK_SIGNAL,
+ MCI_STATE_SET_WLAN_PS_STATE,
+ MCI_STATE_GET_WLAN_PS_STATE,
MCI_STATE_DEBUG,
- MCI_STATE_NEED_FLUSH_BT_INFO,
+ MCI_STATE_STAT_DEBUG,
+ MCI_STATE_ALLOW_FCS,
+ MCI_STATE_SET_2G_CONTENTION,
MCI_STATE_MAX
};
@@ -255,7 +312,7 @@ int ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf,
void ar9003_mci_cleanup(struct ath_hw *ah);
void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
u32 *rx_msg_intr);
-u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more);
+u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, u32 *more);
void ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor);
void ar9003_mci_send_wlan_channels(struct ath_hw *ah);
/*
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_wow.c b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
index 86bfc96..bea41df9 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_wow.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
@@ -20,11 +20,25 @@
#include "reg_wow.h"
#include "hw-ops.h"
+static void ath9k_hw_set_sta_powersave(struct ath_hw *ah)
+{
+ if (!ath9k_hw_mci_is_enabled(ah))
+ goto set;
+ /*
+ * If MCI is being used, set PWR_SAV only when MCI's
+ * PS state is disabled.
+ */
+ if (ar9003_mci_state(ah, MCI_STATE_GET_WLAN_PS_STATE) != MCI_PS_DISABLE)
+ return;
+set:
+ REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+}
+
static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
- REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+ ath9k_hw_set_sta_powersave(ah);
/* set rx disable bit */
REG_WRITE(ah, AR_CR, AR_CR_RXD);
@@ -44,6 +58,9 @@ static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah)
REG_CLR_BIT(ah, AR_DIRECT_CONNECT, AR_DC_TSF2_ENABLE);
}
+ if (ath9k_hw_mci_is_enabled(ah))
+ REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
+
REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT);
}
@@ -74,8 +91,6 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah)
for (i = 0; i < KAL_NUM_DESC_WORDS; i++)
REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]);
- REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]);
-
data_word[0] = (KAL_FRAME_TYPE << 2) | (KAL_FRAME_SUB_TYPE << 4) |
(KAL_TO_DS << 8) | (KAL_DURATION_ID << 16);
data_word[1] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) |
@@ -88,9 +103,11 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah)
(ap_mac_addr[1] << 8) | (ap_mac_addr[0]);
data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]);
- if (AR_SREV_9462_20(ah)) {
- /* AR9462 2.0 has an extra descriptor word (time based
- * discard) compared to other chips */
+ if (AR_SREV_9462_20_OR_LATER(ah) || AR_SREV_9565(ah)) {
+ /*
+ * AR9462 2.0 and AR9565 have an extra descriptor word
+ * (time based discard) compared to other chips.
+ */
REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0);
wow_ka_data_word0 = AR_WOW_TXBUF(13);
} else {
@@ -99,7 +116,6 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah)
for (i = 0; i < KAL_NUM_DATA_WORDS; i++)
REG_WRITE(ah, (wow_ka_data_word0 + i*4), data_word[i]);
-
}
int ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern,
@@ -170,18 +186,17 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah)
u32 val = 0, rval;
/*
- * read the WoW status register to know
- * the wakeup reason
+ * Read the WoW status register to know
+ * the wakeup reason.
*/
rval = REG_READ(ah, AR_WOW_PATTERN);
val = AR_WOW_STATUS(rval);
/*
- * mask only the WoW events that we have enabled. Sometimes
+ * Mask only the WoW events that we have enabled. Sometimes
* we have spurious WoW events from the AR_WOW_PATTERN
* register. This mask will clean it up.
*/
-
val &= ah->wow.wow_event_mask;
if (val) {
@@ -195,6 +210,15 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah)
wow_status |= AH_WOW_BEACON_MISS;
}
+ rval = REG_READ(ah, AR_MAC_PCU_WOW4);
+ val = AR_WOW_STATUS2(rval);
+ val &= ah->wow.wow_event_mask2;
+
+ if (val) {
+ if (AR_WOW2_PATTERN_FOUND(val))
+ wow_status |= AH_WOW_USER_PATTERN_EN;
+ }
+
/*
* set and clear WOW_PME_CLEAR registers for the chip to
* generate next wow signal.
@@ -206,10 +230,12 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah)
AR_PMCTRL_PWR_STATE_D1D3);
/*
- * clear all events
+ * Clear all events.
*/
REG_WRITE(ah, AR_WOW_PATTERN,
AR_WOW_CLEAR_EVENTS(REG_READ(ah, AR_WOW_PATTERN)));
+ REG_WRITE(ah, AR_MAC_PCU_WOW4,
+ AR_WOW_CLEAR_EVENTS2(REG_READ(ah, AR_MAC_PCU_WOW4)));
/*
* restore the beacon threshold to init value
@@ -226,7 +252,15 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah)
if (ah->is_pciexpress)
ath9k_hw_configpcipowersave(ah, false);
+ if (AR_SREV_9462(ah) || AR_SREV_9565(ah) || AR_SREV_9485(ah)) {
+ u32 dc = REG_READ(ah, AR_DIRECT_CONNECT);
+
+ if (!(dc & AR_DC_TSF2_ENABLE))
+ ath9k_hw_gen_timer_start_tsf2(ah);
+ }
+
ah->wow.wow_event_mask = 0;
+ ah->wow.wow_event_mask2 = 0;
return wow_status;
}
@@ -408,6 +442,9 @@ void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable)
ath9k_hw_wow_set_arwr_reg(ah);
+ if (ath9k_hw_mci_is_enabled(ah))
+ REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
+
/* HW WoW */
REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, BIT(5));
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 0f8e946..7e89236 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -645,6 +645,7 @@ void ath9k_calculate_iter_data(struct ath_softc *sc,
struct ath9k_vif_iter_data *iter_data);
void ath9k_calculate_summary_state(struct ath_softc *sc,
struct ath_chanctx *ctx);
+void ath9k_set_txpower(struct ath_softc *sc, struct ieee80211_vif *vif);
/*******************/
/* Beacon Handling */
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index 3dfc2c7..5a084d9 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -103,7 +103,9 @@ void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah)
return;
}
- if (AR_SREV_9300_20_OR_LATER(ah)) {
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) {
+ btcoex_hw->scheme = ATH_BTCOEX_CFG_MCI;
+ } else if (AR_SREV_9300_20_OR_LATER(ah)) {
btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE;
btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9300;
btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9300;
@@ -307,6 +309,18 @@ static void ath9k_hw_btcoex_enable_mci(struct ath_hw *ah)
btcoex->enabled = true;
}
+static void ath9k_hw_btcoex_disable_mci(struct ath_hw *ah)
+{
+ struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+ int i;
+
+ ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
+
+ for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
+ REG_WRITE(ah, AR_MCI_COEX_WL_WEIGHTS(i),
+ btcoex_hw->wlan_weight[i]);
+}
+
void ath9k_hw_btcoex_enable(struct ath_hw *ah)
{
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
@@ -318,17 +332,18 @@ void ath9k_hw_btcoex_enable(struct ath_hw *ah)
ath9k_hw_btcoex_enable_2wire(ah);
break;
case ATH_BTCOEX_CFG_3WIRE:
- if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
- ath9k_hw_btcoex_enable_mci(ah);
- return;
- }
ath9k_hw_btcoex_enable_3wire(ah);
break;
+ case ATH_BTCOEX_CFG_MCI:
+ ath9k_hw_btcoex_enable_mci(ah);
+ break;
}
- REG_RMW(ah, AR_GPIO_PDPU,
- (0x2 << (btcoex_hw->btactive_gpio * 2)),
- (0x3 << (btcoex_hw->btactive_gpio * 2)));
+ if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_MCI) {
+ REG_RMW(ah, AR_GPIO_PDPU,
+ (0x2 << (btcoex_hw->btactive_gpio * 2)),
+ (0x3 << (btcoex_hw->btactive_gpio * 2)));
+ }
ah->btcoex_hw.enabled = true;
}
@@ -340,14 +355,14 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah)
int i;
btcoex_hw->enabled = false;
- if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
- ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
- for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
- REG_WRITE(ah, AR_MCI_COEX_WL_WEIGHTS(i),
- btcoex_hw->wlan_weight[i]);
+
+ if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_MCI) {
+ ath9k_hw_btcoex_disable_mci(ah);
return;
}
- ath9k_hw_set_gpio(ah, btcoex_hw->wlanactive_gpio, 0);
+
+ if (!AR_SREV_9300_20_OR_LATER(ah))
+ ath9k_hw_set_gpio(ah, btcoex_hw->wlanactive_gpio, 0);
ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h
index 6de26ea..5fe62ff 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.h
+++ b/drivers/net/wireless/ath/ath9k/btcoex.h
@@ -58,6 +58,7 @@ enum ath_btcoex_scheme {
ATH_BTCOEX_CFG_NONE,
ATH_BTCOEX_CFG_2WIRE,
ATH_BTCOEX_CFG_3WIRE,
+ ATH_BTCOEX_CFG_MCI,
};
struct ath9k_hw_mci {
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 50a2e0a..dbf8f49 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1156,7 +1156,10 @@ static ssize_t write_file_tpc(struct file *file, const char __user *user_buf,
if (tpc_enabled != ah->tpc_enabled) {
ah->tpc_enabled = tpc_enabled;
- ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false);
+
+ mutex_lock(&sc->mutex);
+ ath9k_set_txpower(sc, NULL);
+ mutex_unlock(&sc->mutex);
}
return count;
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index da344b2..86d46c1 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -202,17 +202,16 @@ static void ath_btcoex_period_timer(unsigned long data)
}
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
- ath9k_mci_update_rssi(sc);
-
ath9k_ps_wakeup(sc);
+ spin_lock_bh(&btcoex->btcoex_lock);
- if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
- ath_detect_bt_priority(sc);
-
- if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) {
+ ath9k_mci_update_rssi(sc);
ath_mci_ftp_adjust(sc);
+ }
- spin_lock_bh(&btcoex->btcoex_lock);
+ if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
+ ath_detect_bt_priority(sc);
stomp_type = btcoex->bt_stomp_type;
timer_period = btcoex->btcoex_no_stomp;
@@ -252,9 +251,6 @@ static void ath_btcoex_no_stomp_timer(unsigned long arg)
struct ath_softc *sc = (struct ath_softc *)arg;
struct ath_hw *ah = sc->sc_ah;
struct ath_btcoex *btcoex = &sc->btcoex;
- struct ath_common *common = ath9k_hw_common(ah);
-
- ath_dbg(common, BTCOEX, "no stomp timer running\n");
ath9k_ps_wakeup(sc);
spin_lock_bh(&btcoex->btcoex_lock);
@@ -271,7 +267,7 @@ static void ath_btcoex_no_stomp_timer(unsigned long arg)
ath9k_ps_restore(sc);
}
-static int ath_init_btcoex_timer(struct ath_softc *sc)
+static void ath_init_btcoex_timer(struct ath_softc *sc)
{
struct ath_btcoex *btcoex = &sc->btcoex;
@@ -280,6 +276,7 @@ static int ath_init_btcoex_timer(struct ath_softc *sc)
btcoex->btcoex_period / 100;
btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
btcoex->btcoex_period / 100;
+ btcoex->bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
(unsigned long) sc);
@@ -287,8 +284,6 @@ static int ath_init_btcoex_timer(struct ath_softc *sc)
(unsigned long) sc);
spin_lock_init(&btcoex->btcoex_lock);
-
- return 0;
}
/*
@@ -299,6 +294,10 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc)
struct ath_btcoex *btcoex = &sc->btcoex;
struct ath_hw *ah = sc->sc_ah;
+ if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_3WIRE &&
+ ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_MCI)
+ return;
+
ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n");
/* make sure duty cycle timer is also stopped when resuming */
@@ -312,13 +311,19 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc)
mod_timer(&btcoex->period_timer, jiffies);
}
-
/*
* Pause btcoex timer and bt duty cycle timer
*/
void ath9k_btcoex_timer_pause(struct ath_softc *sc)
{
struct ath_btcoex *btcoex = &sc->btcoex;
+ struct ath_hw *ah = sc->sc_ah;
+
+ if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_3WIRE &&
+ ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_MCI)
+ return;
+
+ ath_dbg(ath9k_hw_common(ah), BTCOEX, "Stopping btcoex timers\n");
del_timer_sync(&btcoex->period_timer);
del_timer_sync(&btcoex->no_stomp_timer);
@@ -356,33 +361,33 @@ void ath9k_start_btcoex(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
- if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) &&
- !ah->btcoex_hw.enabled) {
- if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
- ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
- AR_STOMP_LOW_WLAN_WGHT, 0);
- else
- ath9k_hw_btcoex_set_weight(ah, 0, 0,
- ATH_BTCOEX_STOMP_NONE);
- ath9k_hw_btcoex_enable(ah);
+ if (ah->btcoex_hw.enabled ||
+ ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
+ return;
- if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
- ath9k_btcoex_timer_resume(sc);
- }
+ if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
+ ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+ AR_STOMP_LOW_WLAN_WGHT, 0);
+ else
+ ath9k_hw_btcoex_set_weight(ah, 0, 0,
+ ATH_BTCOEX_STOMP_NONE);
+ ath9k_hw_btcoex_enable(ah);
+ ath9k_btcoex_timer_resume(sc);
}
void ath9k_stop_btcoex(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
- if (ah->btcoex_hw.enabled &&
- ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
- if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
- ath9k_btcoex_timer_pause(sc);
- ath9k_hw_btcoex_disable(ah);
- if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
- ath_mci_flush_profile(&sc->btcoex.mci);
- }
+ if (!ah->btcoex_hw.enabled ||
+ ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
+ return;
+
+ ath9k_btcoex_timer_pause(sc);
+ ath9k_hw_btcoex_disable(ah);
+
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
+ ath_mci_flush_profile(&sc->btcoex.mci);
}
void ath9k_deinit_btcoex(struct ath_softc *sc)
@@ -409,22 +414,20 @@ int ath9k_init_btcoex(struct ath_softc *sc)
break;
case ATH_BTCOEX_CFG_3WIRE:
ath9k_hw_btcoex_init_3wire(sc->sc_ah);
- r = ath_init_btcoex_timer(sc);
- if (r)
- return -1;
+ ath_init_btcoex_timer(sc);
txq = sc->tx.txq_map[IEEE80211_AC_BE];
ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
- sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
- if (ath9k_hw_mci_is_enabled(ah)) {
- sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE;
- INIT_LIST_HEAD(&sc->btcoex.mci.info);
+ break;
+ case ATH_BTCOEX_CFG_MCI:
+ ath_init_btcoex_timer(sc);
- r = ath_mci_setup(sc);
- if (r)
- return r;
+ sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE;
+ INIT_LIST_HEAD(&sc->btcoex.mci.info);
+ ath9k_hw_btcoex_init_mci(ah);
- ath9k_hw_btcoex_init_mci(ah);
- }
+ r = ath_mci_setup(sc);
+ if (r)
+ return r;
break;
default:
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 8e7153b..10c02f5 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -40,6 +40,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
{ USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */
{ USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */
{ USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */
+ { USB_DEVICE(0x0471, 0x209e) }, /* Philips (or NXP) PTA01 */
{ USB_DEVICE(0x0cf3, 0x7015),
.driver_info = AR9287_USB }, /* Atheros */
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index e82e570..29a25d9 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -27,6 +27,7 @@
#include "eeprom.h"
#include "calib.h"
#include "reg.h"
+#include "reg_mci.h"
#include "phy.h"
#include "btcoex.h"
#include "dynack.h"
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 93ed99a7..b0badef 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1172,6 +1172,38 @@ void ath9k_calculate_summary_state(struct ath_softc *sc,
ath9k_ps_restore(sc);
}
+static void ath9k_tpc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+ int *power = (int *)data;
+
+ if (*power < vif->bss_conf.txpower)
+ *power = vif->bss_conf.txpower;
+}
+
+/* Called with sc->mutex held. */
+void ath9k_set_txpower(struct ath_softc *sc, struct ieee80211_vif *vif)
+{
+ int power;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+
+ ath9k_ps_wakeup(sc);
+ if (ah->tpc_enabled) {
+ power = (vif) ? vif->bss_conf.txpower : -1;
+ ieee80211_iterate_active_interfaces_atomic(
+ sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ ath9k_tpc_vif_iter, &power);
+ if (power == -1)
+ power = sc->hw->conf.power_level;
+ } else {
+ power = sc->hw->conf.power_level;
+ }
+ sc->cur_chan->txpower = 2 * power;
+ ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false);
+ sc->cur_chan->cur_txpower = reg->max_power_level;
+ ath9k_ps_restore(sc);
+}
+
static void ath9k_assign_hw_queues(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
@@ -1225,6 +1257,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
ath9k_assign_hw_queues(hw, vif);
+ ath9k_set_txpower(sc, vif);
+
an->sc = sc;
an->sta = NULL;
an->vif = vif;
@@ -1265,6 +1299,8 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
ath9k_assign_hw_queues(hw, vif);
ath9k_calculate_summary_state(sc, avp->chanctx);
+ ath9k_set_txpower(sc, vif);
+
mutex_unlock(&sc->mutex);
return 0;
}
@@ -1294,6 +1330,8 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
ath9k_calculate_summary_state(sc, avp->chanctx);
+ ath9k_set_txpower(sc, NULL);
+
mutex_unlock(&sc->mutex);
}
@@ -1397,14 +1435,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
ath_chanctx_set_channel(sc, ctx, &hw->conf.chandef);
}
- if (changed & IEEE80211_CONF_CHANGE_POWER) {
- ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
- sc->cur_chan->txpower = 2 * conf->power_level;
- ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower,
- sc->cur_chan->txpower,
- &sc->cur_chan->cur_txpower);
- }
-
mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
@@ -1764,6 +1794,12 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
if (changed & CHECK_ANI)
ath_check_ani(sc);
+ if (changed & BSS_CHANGED_TXPOWER) {
+ ath_dbg(common, CONFIG, "vif %pM power %d dbm power_type %d\n",
+ vif->addr, bss_conf->txpower, bss_conf->txpower_type);
+ ath9k_set_txpower(sc, vif);
+ }
+
mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c
index 3f7a11e..66596b9 100644
--- a/drivers/net/wireless/ath/ath9k/mci.c
+++ b/drivers/net/wireless/ath/ath9k/mci.c
@@ -495,7 +495,7 @@ void ath_mci_intr(struct ath_softc *sc)
ar9003_mci_get_interrupt(sc->sc_ah, &mci_int, &mci_int_rxmsg);
if (ar9003_mci_state(ah, MCI_STATE_ENABLE) == 0) {
- ar9003_mci_get_next_gpm_offset(ah, true, NULL);
+ ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET);
return;
}
@@ -559,8 +559,7 @@ void ath_mci_intr(struct ath_softc *sc)
return;
pgpm = mci->gpm_buf.bf_addr;
- offset = ar9003_mci_get_next_gpm_offset(ah, false,
- &more_data);
+ offset = ar9003_mci_get_next_gpm_offset(ah, &more_data);
if (offset == MCI_GPM_INVALID)
break;
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 9587ec6..1234399 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -2044,279 +2044,4 @@ enum {
#define AR_PHY_AGC_CONTROL_YCOK_MAX 0x000003c0
#define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6
-/* MCI Registers */
-
-#define AR_MCI_COMMAND0 0x1800
-#define AR_MCI_COMMAND0_HEADER 0xFF
-#define AR_MCI_COMMAND0_HEADER_S 0
-#define AR_MCI_COMMAND0_LEN 0x1f00
-#define AR_MCI_COMMAND0_LEN_S 8
-#define AR_MCI_COMMAND0_DISABLE_TIMESTAMP 0x2000
-#define AR_MCI_COMMAND0_DISABLE_TIMESTAMP_S 13
-
-#define AR_MCI_COMMAND1 0x1804
-
-#define AR_MCI_COMMAND2 0x1808
-#define AR_MCI_COMMAND2_RESET_TX 0x01
-#define AR_MCI_COMMAND2_RESET_TX_S 0
-#define AR_MCI_COMMAND2_RESET_RX 0x02
-#define AR_MCI_COMMAND2_RESET_RX_S 1
-#define AR_MCI_COMMAND2_RESET_RX_NUM_CYCLES 0x3FC
-#define AR_MCI_COMMAND2_RESET_RX_NUM_CYCLES_S 2
-#define AR_MCI_COMMAND2_RESET_REQ_WAKEUP 0x400
-#define AR_MCI_COMMAND2_RESET_REQ_WAKEUP_S 10
-
-#define AR_MCI_RX_CTRL 0x180c
-
-#define AR_MCI_TX_CTRL 0x1810
-/* 0 = no division, 1 = divide by 2, 2 = divide by 4, 3 = divide by 8 */
-#define AR_MCI_TX_CTRL_CLK_DIV 0x03
-#define AR_MCI_TX_CTRL_CLK_DIV_S 0
-#define AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE 0x04
-#define AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE_S 2
-#define AR_MCI_TX_CTRL_GAIN_UPDATE_FREQ 0xFFFFF8
-#define AR_MCI_TX_CTRL_GAIN_UPDATE_FREQ_S 3
-#define AR_MCI_TX_CTRL_GAIN_UPDATE_NUM 0xF000000
-#define AR_MCI_TX_CTRL_GAIN_UPDATE_NUM_S 24
-
-#define AR_MCI_MSG_ATTRIBUTES_TABLE 0x1814
-#define AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM 0xFFFF
-#define AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM_S 0
-#define AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR 0xFFFF0000
-#define AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR_S 16
-
-#define AR_MCI_SCHD_TABLE_0 0x1818
-#define AR_MCI_SCHD_TABLE_1 0x181c
-#define AR_MCI_GPM_0 0x1820
-#define AR_MCI_GPM_1 0x1824
-#define AR_MCI_GPM_WRITE_PTR 0xFFFF0000
-#define AR_MCI_GPM_WRITE_PTR_S 16
-#define AR_MCI_GPM_BUF_LEN 0x0000FFFF
-#define AR_MCI_GPM_BUF_LEN_S 0
-
-#define AR_MCI_INTERRUPT_RAW 0x1828
-#define AR_MCI_INTERRUPT_EN 0x182c
-#define AR_MCI_INTERRUPT_SW_MSG_DONE 0x00000001
-#define AR_MCI_INTERRUPT_SW_MSG_DONE_S 0
-#define AR_MCI_INTERRUPT_CPU_INT_MSG 0x00000002
-#define AR_MCI_INTERRUPT_CPU_INT_MSG_S 1
-#define AR_MCI_INTERRUPT_RX_CKSUM_FAIL 0x00000004
-#define AR_MCI_INTERRUPT_RX_CKSUM_FAIL_S 2
-#define AR_MCI_INTERRUPT_RX_INVALID_HDR 0x00000008
-#define AR_MCI_INTERRUPT_RX_INVALID_HDR_S 3
-#define AR_MCI_INTERRUPT_RX_HW_MSG_FAIL 0x00000010
-#define AR_MCI_INTERRUPT_RX_HW_MSG_FAIL_S 4
-#define AR_MCI_INTERRUPT_RX_SW_MSG_FAIL 0x00000020
-#define AR_MCI_INTERRUPT_RX_SW_MSG_FAIL_S 5
-#define AR_MCI_INTERRUPT_TX_HW_MSG_FAIL 0x00000080
-#define AR_MCI_INTERRUPT_TX_HW_MSG_FAIL_S 7
-#define AR_MCI_INTERRUPT_TX_SW_MSG_FAIL 0x00000100
-#define AR_MCI_INTERRUPT_TX_SW_MSG_FAIL_S 8
-#define AR_MCI_INTERRUPT_RX_MSG 0x00000200
-#define AR_MCI_INTERRUPT_RX_MSG_S 9
-#define AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE 0x00000400
-#define AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE_S 10
-#define AR_MCI_INTERRUPT_BT_PRI 0x07fff800
-#define AR_MCI_INTERRUPT_BT_PRI_S 11
-#define AR_MCI_INTERRUPT_BT_PRI_THRESH 0x08000000
-#define AR_MCI_INTERRUPT_BT_PRI_THRESH_S 27
-#define AR_MCI_INTERRUPT_BT_FREQ 0x10000000
-#define AR_MCI_INTERRUPT_BT_FREQ_S 28
-#define AR_MCI_INTERRUPT_BT_STOMP 0x20000000
-#define AR_MCI_INTERRUPT_BT_STOMP_S 29
-#define AR_MCI_INTERRUPT_BB_AIC_IRQ 0x40000000
-#define AR_MCI_INTERRUPT_BB_AIC_IRQ_S 30
-#define AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT 0x80000000
-#define AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT_S 31
-
-#define AR_MCI_INTERRUPT_DEFAULT (AR_MCI_INTERRUPT_SW_MSG_DONE | \
- AR_MCI_INTERRUPT_RX_INVALID_HDR | \
- AR_MCI_INTERRUPT_RX_HW_MSG_FAIL | \
- AR_MCI_INTERRUPT_RX_SW_MSG_FAIL | \
- AR_MCI_INTERRUPT_TX_HW_MSG_FAIL | \
- AR_MCI_INTERRUPT_TX_SW_MSG_FAIL | \
- AR_MCI_INTERRUPT_RX_MSG | \
- AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE | \
- AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)
-
-#define AR_MCI_INTERRUPT_MSG_FAIL_MASK (AR_MCI_INTERRUPT_RX_HW_MSG_FAIL | \
- AR_MCI_INTERRUPT_RX_SW_MSG_FAIL | \
- AR_MCI_INTERRUPT_TX_HW_MSG_FAIL | \
- AR_MCI_INTERRUPT_TX_SW_MSG_FAIL)
-
-#define AR_MCI_REMOTE_CPU_INT 0x1830
-#define AR_MCI_REMOTE_CPU_INT_EN 0x1834
-#define AR_MCI_INTERRUPT_RX_MSG_RAW 0x1838
-#define AR_MCI_INTERRUPT_RX_MSG_EN 0x183c
-#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET 0x00000001
-#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET_S 0
-#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL 0x00000002
-#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL_S 1
-#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK 0x00000004
-#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK_S 2
-#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO 0x00000008
-#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO_S 3
-#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST 0x00000010
-#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST_S 4
-#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO 0x00000020
-#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO_S 5
-#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT 0x00000040
-#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT_S 6
-#define AR_MCI_INTERRUPT_RX_MSG_GPM 0x00000100
-#define AR_MCI_INTERRUPT_RX_MSG_GPM_S 8
-#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO 0x00000200
-#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO_S 9
-#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING 0x00000400
-#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING_S 10
-#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING 0x00000800
-#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING_S 11
-#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE 0x00001000
-#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE_S 12
-#define AR_MCI_INTERRUPT_RX_HW_MSG_MASK (AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \
- AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL| \
- AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \
- AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \
- AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \
- AR_MCI_INTERRUPT_RX_MSG_CONT_RST)
-
-#define AR_MCI_INTERRUPT_RX_MSG_DEFAULT (AR_MCI_INTERRUPT_RX_MSG_GPM | \
- AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET| \
- AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING | \
- AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING| \
- AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)
-
-#define AR_MCI_CPU_INT 0x1840
-
-#define AR_MCI_RX_STATUS 0x1844
-#define AR_MCI_RX_LAST_SCHD_MSG_INDEX 0x00000F00
-#define AR_MCI_RX_LAST_SCHD_MSG_INDEX_S 8
-#define AR_MCI_RX_REMOTE_SLEEP 0x00001000
-#define AR_MCI_RX_REMOTE_SLEEP_S 12
-#define AR_MCI_RX_MCI_CLK_REQ 0x00002000
-#define AR_MCI_RX_MCI_CLK_REQ_S 13
-
-#define AR_MCI_CONT_STATUS 0x1848
-#define AR_MCI_CONT_RSSI_POWER 0x000000FF
-#define AR_MCI_CONT_RSSI_POWER_S 0
-#define AR_MCI_CONT_PRIORITY 0x0000FF00
-#define AR_MCI_CONT_PRIORITY_S 8
-#define AR_MCI_CONT_TXRX 0x00010000
-#define AR_MCI_CONT_TXRX_S 16
-
-#define AR_MCI_BT_PRI0 0x184c
-#define AR_MCI_BT_PRI1 0x1850
-#define AR_MCI_BT_PRI2 0x1854
-#define AR_MCI_BT_PRI3 0x1858
-#define AR_MCI_BT_PRI 0x185c
-#define AR_MCI_WL_FREQ0 0x1860
-#define AR_MCI_WL_FREQ1 0x1864
-#define AR_MCI_WL_FREQ2 0x1868
-#define AR_MCI_GAIN 0x186c
-#define AR_MCI_WBTIMER1 0x1870
-#define AR_MCI_WBTIMER2 0x1874
-#define AR_MCI_WBTIMER3 0x1878
-#define AR_MCI_WBTIMER4 0x187c
-#define AR_MCI_MAXGAIN 0x1880
-#define AR_MCI_HW_SCHD_TBL_CTL 0x1884
-#define AR_MCI_HW_SCHD_TBL_D0 0x1888
-#define AR_MCI_HW_SCHD_TBL_D1 0x188c
-#define AR_MCI_HW_SCHD_TBL_D2 0x1890
-#define AR_MCI_HW_SCHD_TBL_D3 0x1894
-#define AR_MCI_TX_PAYLOAD0 0x1898
-#define AR_MCI_TX_PAYLOAD1 0x189c
-#define AR_MCI_TX_PAYLOAD2 0x18a0
-#define AR_MCI_TX_PAYLOAD3 0x18a4
-#define AR_BTCOEX_WBTIMER 0x18a8
-
-#define AR_BTCOEX_CTRL 0x18ac
-#define AR_BTCOEX_CTRL_AR9462_MODE 0x00000001
-#define AR_BTCOEX_CTRL_AR9462_MODE_S 0
-#define AR_BTCOEX_CTRL_WBTIMER_EN 0x00000002
-#define AR_BTCOEX_CTRL_WBTIMER_EN_S 1
-#define AR_BTCOEX_CTRL_MCI_MODE_EN 0x00000004
-#define AR_BTCOEX_CTRL_MCI_MODE_EN_S 2
-#define AR_BTCOEX_CTRL_LNA_SHARED 0x00000008
-#define AR_BTCOEX_CTRL_LNA_SHARED_S 3
-#define AR_BTCOEX_CTRL_PA_SHARED 0x00000010
-#define AR_BTCOEX_CTRL_PA_SHARED_S 4
-#define AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN 0x00000020
-#define AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN_S 5
-#define AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN 0x00000040
-#define AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN_S 6
-#define AR_BTCOEX_CTRL_NUM_ANTENNAS 0x00000180
-#define AR_BTCOEX_CTRL_NUM_ANTENNAS_S 7
-#define AR_BTCOEX_CTRL_RX_CHAIN_MASK 0x00000E00
-#define AR_BTCOEX_CTRL_RX_CHAIN_MASK_S 9
-#define AR_BTCOEX_CTRL_AGGR_THRESH 0x00007000
-#define AR_BTCOEX_CTRL_AGGR_THRESH_S 12
-#define AR_BTCOEX_CTRL_1_CHAIN_BCN 0x00080000
-#define AR_BTCOEX_CTRL_1_CHAIN_BCN_S 19
-#define AR_BTCOEX_CTRL_1_CHAIN_ACK 0x00100000
-#define AR_BTCOEX_CTRL_1_CHAIN_ACK_S 20
-#define AR_BTCOEX_CTRL_WAIT_BA_MARGIN 0x1FE00000
-#define AR_BTCOEX_CTRL_WAIT_BA_MARGIN_S 28
-#define AR_BTCOEX_CTRL_REDUCE_TXPWR 0x20000000
-#define AR_BTCOEX_CTRL_REDUCE_TXPWR_S 29
-#define AR_BTCOEX_CTRL_SPDT_ENABLE_10 0x40000000
-#define AR_BTCOEX_CTRL_SPDT_ENABLE_10_S 30
-#define AR_BTCOEX_CTRL_SPDT_POLARITY 0x80000000
-#define AR_BTCOEX_CTRL_SPDT_POLARITY_S 31
-
-#define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2))
-#define AR_BTCOEX_WL_LNA 0x1940
-#define AR_BTCOEX_RFGAIN_CTRL 0x1944
-#define AR_BTCOEX_WL_LNA_TIMEOUT 0x003FFFFF
-#define AR_BTCOEX_WL_LNA_TIMEOUT_S 0
-
-#define AR_BTCOEX_CTRL2 0x1948
-#define AR_BTCOEX_CTRL2_TXPWR_THRESH 0x0007F800
-#define AR_BTCOEX_CTRL2_TXPWR_THRESH_S 11
-#define AR_BTCOEX_CTRL2_TX_CHAIN_MASK 0x00380000
-#define AR_BTCOEX_CTRL2_TX_CHAIN_MASK_S 19
-#define AR_BTCOEX_CTRL2_RX_DEWEIGHT 0x00400000
-#define AR_BTCOEX_CTRL2_RX_DEWEIGHT_S 22
-#define AR_BTCOEX_CTRL2_GPIO_OBS_SEL 0x00800000
-#define AR_BTCOEX_CTRL2_GPIO_OBS_SEL_S 23
-#define AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL 0x01000000
-#define AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL_S 24
-#define AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE 0x02000000
-#define AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE_S 25
-
-#define AR_BTCOEX_CTRL_SPDT_ENABLE 0x00000001
-#define AR_BTCOEX_CTRL_SPDT_ENABLE_S 0
-#define AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL 0x00000002
-#define AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL_S 1
-#define AR_BTCOEX_CTRL_USE_LATCHED_BT_ANT 0x00000004
-#define AR_BTCOEX_CTRL_USE_LATCHED_BT_ANT_S 2
-#define AR_GLB_WLAN_UART_INTF_EN 0x00020000
-#define AR_GLB_WLAN_UART_INTF_EN_S 17
-#define AR_GLB_DS_JTAG_DISABLE 0x00040000
-#define AR_GLB_DS_JTAG_DISABLE_S 18
-
-#define AR_BTCOEX_RC 0x194c
-#define AR_BTCOEX_MAX_RFGAIN(_x) (0x1950 + ((_x) << 2))
-#define AR_BTCOEX_DBG 0x1a50
-#define AR_MCI_LAST_HW_MSG_HDR 0x1a54
-#define AR_MCI_LAST_HW_MSG_BDY 0x1a58
-
-#define AR_MCI_SCHD_TABLE_2 0x1a5c
-#define AR_MCI_SCHD_TABLE_2_MEM_BASED 0x00000001
-#define AR_MCI_SCHD_TABLE_2_MEM_BASED_S 0
-#define AR_MCI_SCHD_TABLE_2_HW_BASED 0x00000002
-#define AR_MCI_SCHD_TABLE_2_HW_BASED_S 1
-
-#define AR_BTCOEX_CTRL3 0x1a60
-#define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT 0x00000fff
-#define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT_S 0
-
-#define AR_GLB_SWREG_DISCONT_MODE 0x2002c
-#define AR_GLB_SWREG_DISCONT_EN_BT_WLAN 0x3
-
-#define AR_MCI_MISC 0x1a74
-#define AR_MCI_MISC_HW_FIX_EN 0x00000001
-#define AR_MCI_MISC_HW_FIX_EN_S 0
-#define AR_MCI_DBG_CNT_CTRL 0x1a78
-#define AR_MCI_DBG_CNT_CTRL_ENABLE 0x00000001
-#define AR_MCI_DBG_CNT_CTRL_ENABLE_S 0
-
#endif
diff --git a/drivers/net/wireless/ath/ath9k/reg_mci.h b/drivers/net/wireless/ath/ath9k/reg_mci.h
new file mode 100644
index 0000000..6251310
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/reg_mci.h
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2015 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 notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef REG_MCI_H
+#define REG_MCI_H
+
+#define AR_MCI_COMMAND0 0x1800
+#define AR_MCI_COMMAND0_HEADER 0xFF
+#define AR_MCI_COMMAND0_HEADER_S 0
+#define AR_MCI_COMMAND0_LEN 0x1f00
+#define AR_MCI_COMMAND0_LEN_S 8
+#define AR_MCI_COMMAND0_DISABLE_TIMESTAMP 0x2000
+#define AR_MCI_COMMAND0_DISABLE_TIMESTAMP_S 13
+
+#define AR_MCI_COMMAND1 0x1804
+
+#define AR_MCI_COMMAND2 0x1808
+#define AR_MCI_COMMAND2_RESET_TX 0x01
+#define AR_MCI_COMMAND2_RESET_TX_S 0
+#define AR_MCI_COMMAND2_RESET_RX 0x02
+#define AR_MCI_COMMAND2_RESET_RX_S 1
+#define AR_MCI_COMMAND2_RESET_RX_NUM_CYCLES 0x3FC
+#define AR_MCI_COMMAND2_RESET_RX_NUM_CYCLES_S 2
+#define AR_MCI_COMMAND2_RESET_REQ_WAKEUP 0x400
+#define AR_MCI_COMMAND2_RESET_REQ_WAKEUP_S 10
+
+#define AR_MCI_RX_CTRL 0x180c
+
+#define AR_MCI_TX_CTRL 0x1810
+/*
+ * 0 = no division,
+ * 1 = divide by 2,
+ * 2 = divide by 4,
+ * 3 = divide by 8
+ */
+#define AR_MCI_TX_CTRL_CLK_DIV 0x03
+#define AR_MCI_TX_CTRL_CLK_DIV_S 0
+#define AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE 0x04
+#define AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE_S 2
+#define AR_MCI_TX_CTRL_GAIN_UPDATE_FREQ 0xFFFFF8
+#define AR_MCI_TX_CTRL_GAIN_UPDATE_FREQ_S 3
+#define AR_MCI_TX_CTRL_GAIN_UPDATE_NUM 0xF000000
+#define AR_MCI_TX_CTRL_GAIN_UPDATE_NUM_S 24
+
+#define AR_MCI_MSG_ATTRIBUTES_TABLE 0x1814
+#define AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM 0xFFFF
+#define AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM_S 0
+#define AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR 0xFFFF0000
+#define AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR_S 16
+
+#define AR_MCI_SCHD_TABLE_0 0x1818
+#define AR_MCI_SCHD_TABLE_1 0x181c
+#define AR_MCI_GPM_0 0x1820
+#define AR_MCI_GPM_1 0x1824
+#define AR_MCI_GPM_WRITE_PTR 0xFFFF0000
+#define AR_MCI_GPM_WRITE_PTR_S 16
+#define AR_MCI_GPM_BUF_LEN 0x0000FFFF
+#define AR_MCI_GPM_BUF_LEN_S 0
+
+#define AR_MCI_INTERRUPT_RAW 0x1828
+
+#define AR_MCI_INTERRUPT_EN 0x182c
+#define AR_MCI_INTERRUPT_SW_MSG_DONE 0x00000001
+#define AR_MCI_INTERRUPT_SW_MSG_DONE_S 0
+#define AR_MCI_INTERRUPT_CPU_INT_MSG 0x00000002
+#define AR_MCI_INTERRUPT_CPU_INT_MSG_S 1
+#define AR_MCI_INTERRUPT_RX_CKSUM_FAIL 0x00000004
+#define AR_MCI_INTERRUPT_RX_CKSUM_FAIL_S 2
+#define AR_MCI_INTERRUPT_RX_INVALID_HDR 0x00000008
+#define AR_MCI_INTERRUPT_RX_INVALID_HDR_S 3
+#define AR_MCI_INTERRUPT_RX_HW_MSG_FAIL 0x00000010
+#define AR_MCI_INTERRUPT_RX_HW_MSG_FAIL_S 4
+#define AR_MCI_INTERRUPT_RX_SW_MSG_FAIL 0x00000020
+#define AR_MCI_INTERRUPT_RX_SW_MSG_FAIL_S 5
+#define AR_MCI_INTERRUPT_TX_HW_MSG_FAIL 0x00000080
+#define AR_MCI_INTERRUPT_TX_HW_MSG_FAIL_S 7
+#define AR_MCI_INTERRUPT_TX_SW_MSG_FAIL 0x00000100
+#define AR_MCI_INTERRUPT_TX_SW_MSG_FAIL_S 8
+#define AR_MCI_INTERRUPT_RX_MSG 0x00000200
+#define AR_MCI_INTERRUPT_RX_MSG_S 9
+#define AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE 0x00000400
+#define AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE_S 10
+#define AR_MCI_INTERRUPT_BT_PRI 0x07fff800
+#define AR_MCI_INTERRUPT_BT_PRI_S 11
+#define AR_MCI_INTERRUPT_BT_PRI_THRESH 0x08000000
+#define AR_MCI_INTERRUPT_BT_PRI_THRESH_S 27
+#define AR_MCI_INTERRUPT_BT_FREQ 0x10000000
+#define AR_MCI_INTERRUPT_BT_FREQ_S 28
+#define AR_MCI_INTERRUPT_BT_STOMP 0x20000000
+#define AR_MCI_INTERRUPT_BT_STOMP_S 29
+#define AR_MCI_INTERRUPT_BB_AIC_IRQ 0x40000000
+#define AR_MCI_INTERRUPT_BB_AIC_IRQ_S 30
+#define AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT 0x80000000
+#define AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT_S 31
+
+#define AR_MCI_REMOTE_CPU_INT 0x1830
+#define AR_MCI_REMOTE_CPU_INT_EN 0x1834
+#define AR_MCI_INTERRUPT_RX_MSG_RAW 0x1838
+#define AR_MCI_INTERRUPT_RX_MSG_EN 0x183c
+#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET 0x00000001
+#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET_S 0
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL 0x00000002
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL_S 1
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK 0x00000004
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK_S 2
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO 0x00000008
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO_S 3
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST 0x00000010
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST_S 4
+#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO 0x00000020
+#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO_S 5
+#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT 0x00000040
+#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT_S 6
+#define AR_MCI_INTERRUPT_RX_MSG_GPM 0x00000100
+#define AR_MCI_INTERRUPT_RX_MSG_GPM_S 8
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO 0x00000200
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO_S 9
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING 0x00000400
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING_S 10
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING 0x00000800
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING_S 11
+#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE 0x00001000
+#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE_S 12
+
+#define AR_MCI_CPU_INT 0x1840
+
+#define AR_MCI_RX_STATUS 0x1844
+#define AR_MCI_RX_LAST_SCHD_MSG_INDEX 0x00000F00
+#define AR_MCI_RX_LAST_SCHD_MSG_INDEX_S 8
+#define AR_MCI_RX_REMOTE_SLEEP 0x00001000
+#define AR_MCI_RX_REMOTE_SLEEP_S 12
+#define AR_MCI_RX_MCI_CLK_REQ 0x00002000
+#define AR_MCI_RX_MCI_CLK_REQ_S 13
+
+#define AR_MCI_CONT_STATUS 0x1848
+#define AR_MCI_CONT_RSSI_POWER 0x000000FF
+#define AR_MCI_CONT_RSSI_POWER_S 0
+#define AR_MCI_CONT_PRIORITY 0x0000FF00
+#define AR_MCI_CONT_PRIORITY_S 8
+#define AR_MCI_CONT_TXRX 0x00010000
+#define AR_MCI_CONT_TXRX_S 16
+
+#define AR_MCI_BT_PRI0 0x184c
+#define AR_MCI_BT_PRI1 0x1850
+#define AR_MCI_BT_PRI2 0x1854
+#define AR_MCI_BT_PRI3 0x1858
+#define AR_MCI_BT_PRI 0x185c
+#define AR_MCI_WL_FREQ0 0x1860
+#define AR_MCI_WL_FREQ1 0x1864
+#define AR_MCI_WL_FREQ2 0x1868
+#define AR_MCI_GAIN 0x186c
+#define AR_MCI_WBTIMER1 0x1870
+#define AR_MCI_WBTIMER2 0x1874
+#define AR_MCI_WBTIMER3 0x1878
+#define AR_MCI_WBTIMER4 0x187c
+#define AR_MCI_MAXGAIN 0x1880
+#define AR_MCI_HW_SCHD_TBL_CTL 0x1884
+#define AR_MCI_HW_SCHD_TBL_D0 0x1888
+#define AR_MCI_HW_SCHD_TBL_D1 0x188c
+#define AR_MCI_HW_SCHD_TBL_D2 0x1890
+#define AR_MCI_HW_SCHD_TBL_D3 0x1894
+#define AR_MCI_TX_PAYLOAD0 0x1898
+#define AR_MCI_TX_PAYLOAD1 0x189c
+#define AR_MCI_TX_PAYLOAD2 0x18a0
+#define AR_MCI_TX_PAYLOAD3 0x18a4
+#define AR_BTCOEX_WBTIMER 0x18a8
+
+#define AR_BTCOEX_CTRL 0x18ac
+#define AR_BTCOEX_CTRL_AR9462_MODE 0x00000001
+#define AR_BTCOEX_CTRL_AR9462_MODE_S 0
+#define AR_BTCOEX_CTRL_WBTIMER_EN 0x00000002
+#define AR_BTCOEX_CTRL_WBTIMER_EN_S 1
+#define AR_BTCOEX_CTRL_MCI_MODE_EN 0x00000004
+#define AR_BTCOEX_CTRL_MCI_MODE_EN_S 2
+#define AR_BTCOEX_CTRL_LNA_SHARED 0x00000008
+#define AR_BTCOEX_CTRL_LNA_SHARED_S 3
+#define AR_BTCOEX_CTRL_PA_SHARED 0x00000010
+#define AR_BTCOEX_CTRL_PA_SHARED_S 4
+#define AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN 0x00000020
+#define AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN_S 5
+#define AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN 0x00000040
+#define AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN_S 6
+#define AR_BTCOEX_CTRL_NUM_ANTENNAS 0x00000180
+#define AR_BTCOEX_CTRL_NUM_ANTENNAS_S 7
+#define AR_BTCOEX_CTRL_RX_CHAIN_MASK 0x00000E00
+#define AR_BTCOEX_CTRL_RX_CHAIN_MASK_S 9
+#define AR_BTCOEX_CTRL_AGGR_THRESH 0x00007000
+#define AR_BTCOEX_CTRL_AGGR_THRESH_S 12
+#define AR_BTCOEX_CTRL_1_CHAIN_BCN 0x00080000
+#define AR_BTCOEX_CTRL_1_CHAIN_BCN_S 19
+#define AR_BTCOEX_CTRL_1_CHAIN_ACK 0x00100000
+#define AR_BTCOEX_CTRL_1_CHAIN_ACK_S 20
+#define AR_BTCOEX_CTRL_WAIT_BA_MARGIN 0x1FE00000
+#define AR_BTCOEX_CTRL_WAIT_BA_MARGIN_S 28
+#define AR_BTCOEX_CTRL_REDUCE_TXPWR 0x20000000
+#define AR_BTCOEX_CTRL_REDUCE_TXPWR_S 29
+#define AR_BTCOEX_CTRL_SPDT_ENABLE_10 0x40000000
+#define AR_BTCOEX_CTRL_SPDT_ENABLE_10_S 30
+#define AR_BTCOEX_CTRL_SPDT_POLARITY 0x80000000
+#define AR_BTCOEX_CTRL_SPDT_POLARITY_S 31
+
+#define AR_BTCOEX_WL_WEIGHTS0 0x18b0
+#define AR_BTCOEX_WL_WEIGHTS1 0x18b4
+#define AR_BTCOEX_WL_WEIGHTS2 0x18b8
+#define AR_BTCOEX_WL_WEIGHTS3 0x18bc
+
+#define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2))
+#define AR_BTCOEX_WL_LNA 0x1940
+#define AR_BTCOEX_RFGAIN_CTRL 0x1944
+#define AR_BTCOEX_WL_LNA_TIMEOUT 0x003FFFFF
+#define AR_BTCOEX_WL_LNA_TIMEOUT_S 0
+
+#define AR_BTCOEX_CTRL2 0x1948
+#define AR_BTCOEX_CTRL2_TXPWR_THRESH 0x0007F800
+#define AR_BTCOEX_CTRL2_TXPWR_THRESH_S 11
+#define AR_BTCOEX_CTRL2_TX_CHAIN_MASK 0x00380000
+#define AR_BTCOEX_CTRL2_TX_CHAIN_MASK_S 19
+#define AR_BTCOEX_CTRL2_RX_DEWEIGHT 0x00400000
+#define AR_BTCOEX_CTRL2_RX_DEWEIGHT_S 22
+#define AR_BTCOEX_CTRL2_GPIO_OBS_SEL 0x00800000
+#define AR_BTCOEX_CTRL2_GPIO_OBS_SEL_S 23
+#define AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL 0x01000000
+#define AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL_S 24
+#define AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE 0x02000000
+#define AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE_S 25
+
+#define AR_BTCOEX_CTRL_SPDT_ENABLE 0x00000001
+#define AR_BTCOEX_CTRL_SPDT_ENABLE_S 0
+#define AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL 0x00000002
+#define AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL_S 1
+#define AR_BTCOEX_CTRL_USE_LATCHED_BT_ANT 0x00000004
+#define AR_BTCOEX_CTRL_USE_LATCHED_BT_ANT_S 2
+#define AR_GLB_WLAN_UART_INTF_EN 0x00020000
+#define AR_GLB_WLAN_UART_INTF_EN_S 17
+#define AR_GLB_DS_JTAG_DISABLE 0x00040000
+#define AR_GLB_DS_JTAG_DISABLE_S 18
+
+#define AR_BTCOEX_RC 0x194c
+#define AR_BTCOEX_MAX_RFGAIN(_x) (0x1950 + ((_x) << 2))
+#define AR_BTCOEX_DBG 0x1a50
+#define AR_MCI_LAST_HW_MSG_HDR 0x1a54
+#define AR_MCI_LAST_HW_MSG_BDY 0x1a58
+
+#define AR_MCI_SCHD_TABLE_2 0x1a5c
+#define AR_MCI_SCHD_TABLE_2_MEM_BASED 0x00000001
+#define AR_MCI_SCHD_TABLE_2_MEM_BASED_S 0
+#define AR_MCI_SCHD_TABLE_2_HW_BASED 0x00000002
+#define AR_MCI_SCHD_TABLE_2_HW_BASED_S 1
+
+#define AR_BTCOEX_CTRL3 0x1a60
+#define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT 0x00000fff
+#define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT_S 0
+
+#define AR_GLB_SWREG_DISCONT_MODE 0x2002c
+#define AR_GLB_SWREG_DISCONT_EN_BT_WLAN 0x3
+
+#define AR_MCI_MISC 0x1a74
+#define AR_MCI_MISC_HW_FIX_EN 0x00000001
+#define AR_MCI_MISC_HW_FIX_EN_S 0
+
+#define AR_MCI_DBG_CNT_CTRL 0x1a78
+#define AR_MCI_DBG_CNT_CTRL_ENABLE 0x00000001
+#define AR_MCI_DBG_CNT_CTRL_ENABLE_S 0
+#define AR_MCI_DBG_CNT_CTRL_BT_LINKID 0x000007f8
+#define AR_MCI_DBG_CNT_CTRL_BT_LINKID_S 3
+
+#define MCI_STAT_ALL_BT_LINKID 0xffff
+
+#define AR_MCI_INTERRUPT_DEFAULT (AR_MCI_INTERRUPT_SW_MSG_DONE | \
+ AR_MCI_INTERRUPT_RX_INVALID_HDR | \
+ AR_MCI_INTERRUPT_RX_HW_MSG_FAIL | \
+ AR_MCI_INTERRUPT_RX_SW_MSG_FAIL | \
+ AR_MCI_INTERRUPT_TX_HW_MSG_FAIL | \
+ AR_MCI_INTERRUPT_TX_SW_MSG_FAIL | \
+ AR_MCI_INTERRUPT_RX_MSG | \
+ AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE | \
+ AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)
+
+#define AR_MCI_INTERRUPT_MSG_FAIL_MASK (AR_MCI_INTERRUPT_RX_HW_MSG_FAIL | \
+ AR_MCI_INTERRUPT_RX_SW_MSG_FAIL | \
+ AR_MCI_INTERRUPT_TX_HW_MSG_FAIL | \
+ AR_MCI_INTERRUPT_TX_SW_MSG_FAIL)
+
+#define AR_MCI_INTERRUPT_RX_HW_MSG_MASK (AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \
+ AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL | \
+ AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \
+ AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \
+ AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \
+ AR_MCI_INTERRUPT_RX_MSG_CONT_RST)
+
+#define AR_MCI_INTERRUPT_RX_MSG_DEFAULT (AR_MCI_INTERRUPT_RX_MSG_GPM | \
+ AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET | \
+ AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING | \
+ AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING | \
+ AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)
+
+#endif /* REG_MCI_H */
diff --git a/drivers/net/wireless/ath/ath9k/reg_wow.h b/drivers/net/wireless/ath/ath9k/reg_wow.h
index 3abfca5..4530540 100644
--- a/drivers/net/wireless/ath/ath9k/reg_wow.h
+++ b/drivers/net/wireless/ath/ath9k/reg_wow.h
@@ -72,7 +72,7 @@
#define AR_WOW_MAC_INTR_EN 0x00040000
#define AR_WOW_MAGIC_EN 0x00010000
#define AR_WOW_PATTERN_EN(x) (x & 0xff)
-#define AR_WOW_PAT_FOUND_SHIFT 8
+#define AR_WOW_PAT_FOUND_SHIFT 8
#define AR_WOW_PATTERN_FOUND(x) (x & (0xff << AR_WOW_PAT_FOUND_SHIFT))
#define AR_WOW_PATTERN_FOUND_MASK ((0xff) << AR_WOW_PAT_FOUND_SHIFT)
#define AR_WOW_MAGIC_PAT_FOUND 0x00020000
@@ -90,6 +90,14 @@
AR_WOW_BEACON_FAIL | \
AR_WOW_KEEP_ALIVE_FAIL))
+#define AR_WOW2_PATTERN_EN(x) ((x & 0xff) << 0)
+#define AR_WOW2_PATTERN_FOUND_SHIFT 8
+#define AR_WOW2_PATTERN_FOUND(x) (x & (0xff << AR_WOW2_PATTERN_FOUND_SHIFT))
+#define AR_WOW2_PATTERN_FOUND_MASK ((0xff) << AR_WOW2_PATTERN_FOUND_SHIFT)
+
+#define AR_WOW_STATUS2(x) (x & AR_WOW2_PATTERN_FOUND_MASK)
+#define AR_WOW_CLEAR_EVENTS2(x) (x & ~(AR_WOW2_PATTERN_EN(0xff)))
+
#define AR_WOW_AIFS_CNT(x) (x & 0xff)
#define AR_WOW_SLOT_CNT(x) ((x & 0xff) << 8)
#define AR_WOW_KEEP_ALIVE_CNT(x) ((x & 0xff) << 16)
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 1b8e75c..0acd079 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1103,14 +1103,28 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
struct sk_buff *skb;
struct ath_frame_info *fi;
struct ieee80211_tx_info *info;
+ struct ieee80211_vif *vif;
struct ath_hw *ah = sc->sc_ah;
if (sc->tx99_state || !ah->tpc_enabled)
return MAX_RATE_POWER;
skb = bf->bf_mpdu;
- fi = get_frame_info(skb);
info = IEEE80211_SKB_CB(skb);
+ vif = info->control.vif;
+
+ if (!vif) {
+ max_power = sc->cur_chan->cur_txpower;
+ goto out;
+ }
+
+ if (vif->bss_conf.txpower_type != NL80211_TX_POWER_LIMITED) {
+ max_power = min_t(u8, sc->cur_chan->cur_txpower,
+ 2 * vif->bss_conf.txpower);
+ goto out;
+ }
+
+ fi = get_frame_info(skb);
if (!AR_SREV_9300_20_OR_LATER(ah)) {
int txpower = fi->tx_power;
@@ -1147,25 +1161,25 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
txpower -= 2;
txpower = max(txpower, 0);
- max_power = min_t(u8, ah->tx_power[rateidx], txpower);
-
- /* XXX: clamp minimum TX power at 1 for AR9160 since if
- * max_power is set to 0, frames are transmitted at max
- * TX power
- */
- if (!max_power && !AR_SREV_9280_20_OR_LATER(ah))
- max_power = 1;
+ max_power = min_t(u8, ah->tx_power[rateidx],
+ 2 * vif->bss_conf.txpower);
+ max_power = min_t(u8, max_power, txpower);
} else if (!bf->bf_state.bfs_paprd) {
if (rateidx < 8 && (info->flags & IEEE80211_TX_CTL_STBC))
- max_power = min(ah->tx_power_stbc[rateidx],
- fi->tx_power);
+ max_power = min_t(u8, ah->tx_power_stbc[rateidx],
+ 2 * vif->bss_conf.txpower);
else
- max_power = min(ah->tx_power[rateidx], fi->tx_power);
+ max_power = min_t(u8, ah->tx_power[rateidx],
+ 2 * vif->bss_conf.txpower);
+ max_power = min(max_power, fi->tx_power);
} else {
max_power = ah->paprd_training_power;
}
-
- return max_power;
+out:
+ /* XXX: clamp minimum TX power at 1 for AR9160 since if max_power
+ * is set to 0, frames are transmitted at max TX power
+ */
+ return (!max_power && !AR_SREV_9280_20_OR_LATER(ah)) ? 1 : max_power;
}
static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 2d5ea21..4bd708c 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -387,11 +387,25 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
int ch;
int rc = 0;
+ wil_print_connect_params(wil, sme);
+
if (test_bit(wil_status_fwconnecting, wil->status) ||
test_bit(wil_status_fwconnected, wil->status))
return -EALREADY;
- wil_print_connect_params(wil, sme);
+ if (sme->ie_len > WMI_MAX_IE_LEN) {
+ wil_err(wil, "IE too large (%td bytes)\n", sme->ie_len);
+ return -ERANGE;
+ }
+
+ rsn_eid = sme->ie ?
+ cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) :
+ NULL;
+
+ if (sme->privacy && !rsn_eid) {
+ wil_err(wil, "Missing RSN IE for secure connection\n");
+ return -EINVAL;
+ }
bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
sme->ssid, sme->ssid_len,
@@ -407,17 +421,9 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
rc = -ENOENT;
goto out;
}
+ wil->privacy = sme->privacy;
- rsn_eid = sme->ie ?
- cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) :
- NULL;
- if (rsn_eid) {
- if (sme->ie_len > WMI_MAX_IE_LEN) {
- rc = -ERANGE;
- wil_err(wil, "IE too large (%td bytes)\n",
- sme->ie_len);
- goto out;
- }
+ if (wil->privacy) {
/* For secure assoc, send WMI_DELETE_CIPHER_KEY_CMD */
rc = wmi_del_cipher_key(wil, 0, bss->bssid);
if (rc) {
@@ -450,7 +456,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
bss->capability);
goto out;
}
- if (rsn_eid) {
+ if (wil->privacy) {
conn.dot11_auth_mode = WMI_AUTH11_SHARED;
conn.auth_mode = WMI_AUTH_WPA2_PSK;
conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP;
@@ -769,7 +775,7 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len,
bcon->assocresp_ies);
- wil->secure_pcp = info->privacy;
+ wil->privacy = info->privacy;
netif_carrier_on(ndev);
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 45c3558e..3830cc2 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -29,6 +29,7 @@
static u32 mem_addr;
static u32 dbg_txdesc_index;
static u32 dbg_vring_index; /* 24+ for Rx, 0..23 for Tx */
+u32 vring_idle_trsh = 16; /* HW fetches up to 16 descriptors at once */
enum dbg_off_type {
doff_u32 = 0,
@@ -102,23 +103,30 @@ static int wil_vring_debugfs_show(struct seq_file *s, void *data)
% vring->size;
int avail = vring->size - used - 1;
char name[10];
+ char sidle[10];
/* performance monitoring */
cycles_t now = get_cycles();
uint64_t idle = txdata->idle * 100;
uint64_t total = now - txdata->begin;
- do_div(idle, total);
+ if (total != 0) {
+ do_div(idle, total);
+ snprintf(sidle, sizeof(sidle), "%3d%%",
+ (int)idle);
+ } else {
+ snprintf(sidle, sizeof(sidle), "N/A");
+ }
txdata->begin = now;
txdata->idle = 0ULL;
snprintf(name, sizeof(name), "tx_%2d", i);
seq_printf(s,
- "\n%pM CID %d TID %d BACK([%d] %d TU A%s) [%3d|%3d] idle %3d%%\n",
- wil->sta[cid].addr, cid, tid,
- txdata->agg_wsize, txdata->agg_timeout,
- txdata->agg_amsdu ? "+" : "-",
- used, avail, (int)idle);
+ "\n%pM CID %d TID %d BACK([%d] %d TU A%s) [%3d|%3d] idle %s\n",
+ wil->sta[cid].addr, cid, tid,
+ txdata->agg_wsize, txdata->agg_timeout,
+ txdata->agg_amsdu ? "+" : "-",
+ used, avail, sidle);
wil_print_vring(s, wil, name, vring, '_', 'H');
}
@@ -549,7 +557,7 @@ static ssize_t wil_write_file_reset(struct file *file, const char __user *buf,
dev_close(ndev);
ndev->flags &= ~IFF_UP;
rtnl_unlock();
- wil_reset(wil);
+ wil_reset(wil, true);
return len;
}
@@ -618,7 +626,7 @@ static ssize_t wil_write_back(struct file *file, const char __user *buf,
struct wil6210_priv *wil = file->private_data;
int rc;
char *kbuf = kmalloc(len + 1, GFP_KERNEL);
- char cmd[8];
+ char cmd[9];
int p1, p2, p3;
if (!kbuf)
@@ -1392,7 +1400,7 @@ static void wil6210_debugfs_init_isr(struct wil6210_priv *wil,
/* fields in struct wil6210_priv */
static const struct dbg_off dbg_wil_off[] = {
- WIL_FIELD(secure_pcp, S_IRUGO | S_IWUSR, doff_u32),
+ WIL_FIELD(privacy, S_IRUGO, doff_u32),
WIL_FIELD(status[0], S_IRUGO | S_IWUSR, doff_ulong),
WIL_FIELD(fw_version, S_IRUGO, doff_u32),
WIL_FIELD(hw_version, S_IRUGO, doff_x32),
@@ -1412,6 +1420,8 @@ static const struct dbg_off dbg_statics[] = {
{"desc_index", S_IRUGO | S_IWUSR, (ulong)&dbg_txdesc_index, doff_u32},
{"vring_index", S_IRUGO | S_IWUSR, (ulong)&dbg_vring_index, doff_u32},
{"mem_addr", S_IRUGO | S_IWUSR, (ulong)&mem_addr, doff_u32},
+ {"vring_idle_trsh", S_IRUGO | S_IWUSR, (ulong)&vring_idle_trsh,
+ doff_u32},
{},
};
diff --git a/drivers/net/wireless/ath/wil6210/ethtool.c b/drivers/net/wireless/ath/wil6210/ethtool.c
index 4c44a82..0ea695f 100644
--- a/drivers/net/wireless/ath/wil6210/ethtool.c
+++ b/drivers/net/wireless/ath/wil6210/ethtool.c
@@ -50,27 +50,19 @@ static int wil_ethtoolops_get_coalesce(struct net_device *ndev,
wil_dbg_misc(wil, "%s()\n", __func__);
- if (test_bit(hw_capability_advanced_itr_moderation,
- wil->hw_capabilities)) {
- tx_itr_en = ioread32(wil->csr +
- HOSTADDR(RGF_DMA_ITR_TX_CNT_CTL));
- if (tx_itr_en & BIT_DMA_ITR_TX_CNT_CTL_EN)
- tx_itr_val =
- ioread32(wil->csr +
- HOSTADDR(RGF_DMA_ITR_TX_CNT_TRSH));
-
- rx_itr_en = ioread32(wil->csr +
- HOSTADDR(RGF_DMA_ITR_RX_CNT_CTL));
- if (rx_itr_en & BIT_DMA_ITR_RX_CNT_CTL_EN)
- rx_itr_val =
- ioread32(wil->csr +
- HOSTADDR(RGF_DMA_ITR_RX_CNT_TRSH));
- } else {
- rx_itr_en = ioread32(wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_CRL));
- if (rx_itr_en & BIT_DMA_ITR_CNT_CRL_EN)
- rx_itr_val = ioread32(wil->csr +
- HOSTADDR(RGF_DMA_ITR_CNT_TRSH));
- }
+ tx_itr_en = ioread32(wil->csr +
+ HOSTADDR(RGF_DMA_ITR_TX_CNT_CTL));
+ if (tx_itr_en & BIT_DMA_ITR_TX_CNT_CTL_EN)
+ tx_itr_val =
+ ioread32(wil->csr +
+ HOSTADDR(RGF_DMA_ITR_TX_CNT_TRSH));
+
+ rx_itr_en = ioread32(wil->csr +
+ HOSTADDR(RGF_DMA_ITR_RX_CNT_CTL));
+ if (rx_itr_en & BIT_DMA_ITR_RX_CNT_CTL_EN)
+ rx_itr_val =
+ ioread32(wil->csr +
+ HOSTADDR(RGF_DMA_ITR_RX_CNT_TRSH));
cp->tx_coalesce_usecs = tx_itr_val;
cp->rx_coalesce_usecs = rx_itr_val;
diff --git a/drivers/net/wireless/ath/wil6210/fw.c b/drivers/net/wireless/ath/wil6210/fw.c
index 93c5cc1..4428345 100644
--- a/drivers/net/wireless/ath/wil6210/fw.c
+++ b/drivers/net/wireless/ath/wil6210/fw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Qualcomm Atheros, Inc.
+ * Copyright (c) 2014-2015 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
@@ -20,6 +20,7 @@
#include "fw.h"
MODULE_FIRMWARE(WIL_FW_NAME);
+MODULE_FIRMWARE(WIL_FW2_NAME);
/* target operations */
/* register read */
diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c
index d4acf93..157f5ef 100644
--- a/drivers/net/wireless/ath/wil6210/fw_inc.c
+++ b/drivers/net/wireless/ath/wil6210/fw_inc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Qualcomm Atheros, Inc.
+ * Copyright (c) 2014-2015 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
@@ -451,8 +451,6 @@ static int wil_fw_load(struct wil6210_priv *wil, const void *data, size_t size)
}
return -EINVAL;
}
- /* Mark FW as loaded from host */
- S(RGF_USER_USAGE_6, 1);
return rc;
}
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index a6f9230..28ffc18 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -166,9 +166,16 @@ void wil_unmask_irq(struct wil6210_priv *wil)
/* target write operation */
#define W(a, v) do { iowrite32(v, wil->csr + HOSTADDR(a)); wmb(); } while (0)
-static
-void wil_configure_interrupt_moderation_new(struct wil6210_priv *wil)
+void wil_configure_interrupt_moderation(struct wil6210_priv *wil)
{
+ wil_dbg_irq(wil, "%s()\n", __func__);
+
+ /* disable interrupt moderation for monitor
+ * to get better timestamp precision
+ */
+ if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR)
+ return;
+
/* Disable and clear tx counter before (re)configuration */
W(RGF_DMA_ITR_TX_CNT_CTL, BIT_DMA_ITR_TX_CNT_CTL_CLR);
W(RGF_DMA_ITR_TX_CNT_TRSH, wil->tx_max_burst_duration);
@@ -206,42 +213,8 @@ void wil_configure_interrupt_moderation_new(struct wil6210_priv *wil)
BIT_DMA_ITR_RX_IDL_CNT_CTL_EXT_TIC_SEL);
}
-static
-void wil_configure_interrupt_moderation_lgc(struct wil6210_priv *wil)
-{
- /* disable, use usec resolution */
- W(RGF_DMA_ITR_CNT_CRL, BIT_DMA_ITR_CNT_CRL_CLR);
-
- wil_info(wil, "set ITR_TRSH = %d usec\n", wil->rx_max_burst_duration);
- W(RGF_DMA_ITR_CNT_TRSH, wil->rx_max_burst_duration);
- /* start it */
- W(RGF_DMA_ITR_CNT_CRL,
- BIT_DMA_ITR_CNT_CRL_EN | BIT_DMA_ITR_CNT_CRL_EXT_TICK);
-}
-
#undef W
-void wil_configure_interrupt_moderation(struct wil6210_priv *wil)
-{
- wil_dbg_irq(wil, "%s()\n", __func__);
-
- /* disable interrupt moderation for monitor
- * to get better timestamp precision
- */
- if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR)
- return;
-
- if (test_bit(hw_capability_advanced_itr_moderation,
- wil->hw_capabilities))
- wil_configure_interrupt_moderation_new(wil);
- else {
- /* Advanced interrupt moderation is not available before
- * Sparrow v2. Will use legacy interrupt moderation
- */
- wil_configure_interrupt_moderation_lgc(wil);
- }
-}
-
static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
{
struct wil6210_priv *wil = cookie;
@@ -253,7 +226,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
trace_wil6210_irq_rx(isr);
wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
- if (!isr) {
+ if (unlikely(!isr)) {
wil_err(wil, "spurious IRQ: RX\n");
return IRQ_NONE;
}
@@ -266,17 +239,18 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
* action is always the same - should empty the accumulated
* packets from the RX ring.
*/
- if (isr & (BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH)) {
+ if (likely(isr & (BIT_DMA_EP_RX_ICR_RX_DONE |
+ BIT_DMA_EP_RX_ICR_RX_HTRSH))) {
wil_dbg_irq(wil, "RX done\n");
- if (isr & BIT_DMA_EP_RX_ICR_RX_HTRSH)
+ if (unlikely(isr & BIT_DMA_EP_RX_ICR_RX_HTRSH))
wil_err_ratelimited(wil,
"Received \"Rx buffer is in risk of overflow\" interrupt\n");
isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE |
BIT_DMA_EP_RX_ICR_RX_HTRSH);
- if (test_bit(wil_status_reset_done, wil->status)) {
- if (test_bit(wil_status_napi_en, wil->status)) {
+ if (likely(test_bit(wil_status_reset_done, wil->status))) {
+ if (likely(test_bit(wil_status_napi_en, wil->status))) {
wil_dbg_txrx(wil, "NAPI(Rx) schedule\n");
need_unmask = false;
napi_schedule(&wil->napi_rx);
@@ -289,7 +263,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
}
}
- if (isr)
+ if (unlikely(isr))
wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr);
/* Rx IRQ will be enabled when NAPI processing finished */
@@ -313,19 +287,19 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
trace_wil6210_irq_tx(isr);
wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
- if (!isr) {
+ if (unlikely(!isr)) {
wil_err(wil, "spurious IRQ: TX\n");
return IRQ_NONE;
}
wil6210_mask_irq_tx(wil);
- if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) {
+ if (likely(isr & BIT_DMA_EP_TX_ICR_TX_DONE)) {
wil_dbg_irq(wil, "TX done\n");
isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE;
/* clear also all VRING interrupts */
isr &= ~(BIT(25) - 1UL);
- if (test_bit(wil_status_reset_done, wil->status)) {
+ if (likely(test_bit(wil_status_reset_done, wil->status))) {
wil_dbg_txrx(wil, "NAPI(Tx) schedule\n");
need_unmask = false;
napi_schedule(&wil->napi_tx);
@@ -334,7 +308,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
}
}
- if (isr)
+ if (unlikely(isr))
wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr);
/* Tx IRQ will be enabled when NAPI processing finished */
@@ -523,11 +497,11 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie)
/**
* pseudo_cause is Clear-On-Read, no need to ACK
*/
- if ((pseudo_cause == 0) || ((pseudo_cause & 0xff) == 0xff))
+ if (unlikely((pseudo_cause == 0) || ((pseudo_cause & 0xff) == 0xff)))
return IRQ_NONE;
/* FIXME: IRQ mask debug */
- if (wil6210_debug_irq_mask(wil, pseudo_cause))
+ if (unlikely(wil6210_debug_irq_mask(wil, pseudo_cause)))
return IRQ_NONE;
trace_wil6210_irq_pseudo(pseudo_cause);
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index b04e0af..db74e81 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -29,10 +29,6 @@ bool no_fw_recovery;
module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(no_fw_recovery, " disable automatic FW error recovery");
-static bool no_fw_load = true;
-module_param(no_fw_load, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(no_fw_load, " do not download FW, use one in on-card flash.");
-
/* if not set via modparam, will be set to default value of 1/8 of
* rx ring size during init flow
*/
@@ -520,8 +516,6 @@ static int wil_target_reset(struct wil6210_priv *wil)
{
int delay = 0;
u32 x;
- bool is_reset_v2 = test_bit(hw_capability_reset_v2,
- wil->hw_capabilities);
wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->hw_name);
@@ -532,82 +526,67 @@ static int wil_target_reset(struct wil6210_priv *wil)
wil_halt_cpu(wil);
+ /* clear all boot loader "ready" bits */
+ W(RGF_USER_BL + offsetof(struct RGF_BL, ready), 0);
/* Clear Fw Download notification */
C(RGF_USER_USAGE_6, BIT(0));
- if (is_reset_v2) {
- S(RGF_CAF_OSC_CONTROL, BIT_CAF_OSC_XTAL_EN);
- /* XTAL stabilization should take about 3ms */
- usleep_range(5000, 7000);
- x = R(RGF_CAF_PLL_LOCK_STATUS);
- if (!(x & BIT_CAF_OSC_DIG_XTAL_STABLE)) {
- wil_err(wil, "Xtal stabilization timeout\n"
- "RGF_CAF_PLL_LOCK_STATUS = 0x%08x\n", x);
- return -ETIME;
- }
- /* switch 10k to XTAL*/
- C(RGF_USER_SPARROW_M_4, BIT_SPARROW_M_4_SEL_SLEEP_OR_REF);
- /* 40 MHz */
- C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL);
-
- W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f);
- W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf);
+ S(RGF_CAF_OSC_CONTROL, BIT_CAF_OSC_XTAL_EN);
+ /* XTAL stabilization should take about 3ms */
+ usleep_range(5000, 7000);
+ x = R(RGF_CAF_PLL_LOCK_STATUS);
+ if (!(x & BIT_CAF_OSC_DIG_XTAL_STABLE)) {
+ wil_err(wil, "Xtal stabilization timeout\n"
+ "RGF_CAF_PLL_LOCK_STATUS = 0x%08x\n", x);
+ return -ETIME;
}
+ /* switch 10k to XTAL*/
+ C(RGF_USER_SPARROW_M_4, BIT_SPARROW_M_4_SEL_SLEEP_OR_REF);
+ /* 40 MHz */
+ C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL);
+
+ W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f);
+ W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F);
- W(RGF_USER_CLKS_CTL_SW_RST_VEC_3,
- is_reset_v2 ? 0x000000f0 : 0x00000170);
+ W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x000000f0);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FE00);
- if (is_reset_v2) {
- W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0);
- W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0x0);
- }
+ W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0);
+ W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0x0);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
- if (is_reset_v2) {
- W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000003);
- /* reset A2 PCIE AHB */
- W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
- } else {
- W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001);
- W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8));
- W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
- }
+ W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000003);
+ W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000); /* reset A2 PCIE AHB */
- /* TODO: check order here!!! Erez code is different */
W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
- /* wait until device ready. typical time is 200..250 msec */
+ /* wait until device ready. typical time is 20..80 msec */
do {
msleep(RST_DELAY);
- x = R(RGF_USER_HW_MACHINE_STATE);
+ x = R(RGF_USER_BL + offsetof(struct RGF_BL, ready));
if (delay++ > RST_COUNT) {
- wil_err(wil, "Reset not completed, hw_state 0x%08x\n",
+ wil_err(wil, "Reset not completed, bl.ready 0x%08x\n",
x);
return -ETIME;
}
- } while (x != HW_MACHINE_BOOT_DONE);
-
- if (!is_reset_v2)
- W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8));
+ } while (!(x & BIT_BL_READY));
C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
+ /* enable fix for HW bug related to the SA/DA swap in AP Rx */
+ S(RGF_DMA_OFUL_NID_0, BIT_DMA_OFUL_NID_0_RX_EXT_TR_EN |
+ BIT_DMA_OFUL_NID_0_RX_EXT_A3_SRC);
+
wil_dbg_misc(wil, "Reset completed in %d ms\n", delay * RST_DELAY);
return 0;
}
-#undef R
-#undef W
-#undef S
-#undef C
-
void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
{
le32_to_cpus(&r->base);
@@ -617,6 +596,32 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
le32_to_cpus(&r->head);
}
+static int wil_get_bl_info(struct wil6210_priv *wil)
+{
+ struct net_device *ndev = wil_to_ndev(wil);
+ struct RGF_BL bl;
+
+ wil_memcpy_fromio_32(&bl, wil->csr + HOSTADDR(RGF_USER_BL), sizeof(bl));
+ le32_to_cpus(&bl.ready);
+ le32_to_cpus(&bl.version);
+ le32_to_cpus(&bl.rf_type);
+ le32_to_cpus(&bl.baseband_type);
+
+ if (!is_valid_ether_addr(bl.mac_address)) {
+ wil_err(wil, "BL: Invalid MAC %pM\n", bl.mac_address);
+ return -EINVAL;
+ }
+
+ ether_addr_copy(ndev->perm_addr, bl.mac_address);
+ if (!is_valid_ether_addr(ndev->dev_addr))
+ ether_addr_copy(ndev->dev_addr, bl.mac_address);
+ wil_info(wil,
+ "Boot Loader: ver = %d MAC = %pM RF = 0x%08x bband = 0x%08x\n",
+ bl.version, bl.mac_address, bl.rf_type, bl.baseband_type);
+
+ return 0;
+}
+
static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
{
ulong to = msecs_to_jiffies(1000);
@@ -637,7 +642,7 @@ static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
* After calling this routine, you're expected to reload
* the firmware.
*/
-int wil_reset(struct wil6210_priv *wil)
+int wil_reset(struct wil6210_priv *wil, bool load_fw)
{
int rc;
@@ -675,30 +680,36 @@ int wil_reset(struct wil6210_priv *wil)
if (rc)
return rc;
- if (!no_fw_load) {
- wil_info(wil, "Use firmware <%s>\n", WIL_FW_NAME);
+ rc = wil_get_bl_info(wil);
+ if (rc)
+ return rc;
+
+ if (load_fw) {
+ wil_info(wil, "Use firmware <%s> + board <%s>\n", WIL_FW_NAME,
+ WIL_FW2_NAME);
+
wil_halt_cpu(wil);
/* Loading f/w from the file */
rc = wil_request_firmware(wil, WIL_FW_NAME);
if (rc)
return rc;
+ rc = wil_request_firmware(wil, WIL_FW2_NAME);
+ if (rc)
+ return rc;
- /* clear any interrupts which on-card-firmware may have set */
+ /* Mark FW as loaded from host */
+ S(RGF_USER_USAGE_6, 1);
+
+ /* clear any interrupts which on-card-firmware
+ * may have set
+ */
wil6210_clear_irq(wil);
- { /* CAF_ICR - clear and mask */
- u32 a = HOSTADDR(RGF_CAF_ICR) +
- offsetof(struct RGF_ICR, ICR);
- u32 m = HOSTADDR(RGF_CAF_ICR) +
- offsetof(struct RGF_ICR, IMV);
- u32 icr = ioread32(wil->csr + a);
-
- iowrite32(icr, wil->csr + a); /* W1C */
- iowrite32(~0, wil->csr + m);
- wmb(); /* wait for completion */
- }
+ /* CAF_ICR - clear and mask */
+ /* it is W1C, clear by writing back same value */
+ S(RGF_CAF_ICR + offsetof(struct RGF_ICR, ICR), 0);
+ W(RGF_CAF_ICR + offsetof(struct RGF_ICR, IMV), ~0);
+
wil_release_cpu(wil);
- } else {
- wil_info(wil, "Use firmware from on-card flash\n");
}
/* init after reset */
@@ -706,15 +717,22 @@ int wil_reset(struct wil6210_priv *wil)
reinit_completion(&wil->wmi_ready);
reinit_completion(&wil->wmi_call);
- wil_configure_interrupt_moderation(wil);
- wil_unmask_irq(wil);
+ if (load_fw) {
+ wil_configure_interrupt_moderation(wil);
+ wil_unmask_irq(wil);
- /* we just started MAC, wait for FW ready */
- rc = wil_wait_for_fw_ready(wil);
+ /* we just started MAC, wait for FW ready */
+ rc = wil_wait_for_fw_ready(wil);
+ }
return rc;
}
+#undef R
+#undef W
+#undef S
+#undef C
+
void wil_fw_error_recovery(struct wil6210_priv *wil)
{
wil_dbg_misc(wil, "starting fw error recovery\n");
@@ -730,7 +748,7 @@ int __wil_up(struct wil6210_priv *wil)
WARN_ON(!mutex_is_locked(&wil->mutex));
- rc = wil_reset(wil);
+ rc = wil_reset(wil, true);
if (rc)
return rc;
@@ -837,7 +855,7 @@ int __wil_down(struct wil6210_priv *wil)
if (!iter)
wil_err(wil, "timeout waiting for idle FW/HW\n");
- wil_rx_fini(wil);
+ wil_reset(wil, false);
return 0;
}
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index 3dd2670..25343cf 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -39,18 +39,6 @@ void wil_set_capabilities(struct wil6210_priv *wil)
bitmap_zero(wil->hw_capabilities, hw_capability_last);
switch (rev_id) {
- case JTAG_DEV_ID_MARLON_B0:
- wil->hw_name = "Marlon B0";
- wil->hw_version = HW_VER_MARLON_B0;
- break;
- case JTAG_DEV_ID_SPARROW_A0:
- wil->hw_name = "Sparrow A0";
- wil->hw_version = HW_VER_SPARROW_A0;
- break;
- case JTAG_DEV_ID_SPARROW_A1:
- wil->hw_name = "Sparrow A1";
- wil->hw_version = HW_VER_SPARROW_A1;
- break;
case JTAG_DEV_ID_SPARROW_B0:
wil->hw_name = "Sparrow B0";
wil->hw_version = HW_VER_SPARROW_B0;
@@ -62,13 +50,6 @@ void wil_set_capabilities(struct wil6210_priv *wil)
}
wil_info(wil, "Board hardware is %s\n", wil->hw_name);
-
- if (wil->hw_version >= HW_VER_SPARROW_A0)
- set_bit(hw_capability_reset_v2, wil->hw_capabilities);
-
- if (wil->hw_version >= HW_VER_SPARROW_B0)
- set_bit(hw_capability_advanced_itr_moderation,
- wil->hw_capabilities);
}
void wil_disable_irq(struct wil6210_priv *wil)
@@ -150,7 +131,7 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
/* need reset here to obtain MAC */
mutex_lock(&wil->mutex);
- rc = wil_reset(wil);
+ rc = wil_reset(wil, false);
mutex_unlock(&wil->mutex);
if (debug_fw)
rc = 0;
@@ -305,7 +286,6 @@ static void wil_pcie_remove(struct pci_dev *pdev)
}
static const struct pci_device_id wil6210_pcie_ids[] = {
- { PCI_DEVICE(0x1ae9, 0x0301) },
{ PCI_DEVICE(0x1ae9, 0x0310) },
{ PCI_DEVICE(0x1ae9, 0x0302) }, /* same as above, firmware broken */
{ /* end: all zeroes */ },
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 8439f65..7f2f560 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -53,34 +53,38 @@ static inline int wil_vring_is_full(struct vring *vring)
return wil_vring_next_tail(vring) == vring->swhead;
}
-/*
- * Available space in Tx Vring
- */
-static inline int wil_vring_avail_tx(struct vring *vring)
+/* Used space in Tx Vring */
+static inline int wil_vring_used_tx(struct vring *vring)
{
u32 swhead = vring->swhead;
u32 swtail = vring->swtail;
- int used = (vring->size + swhead - swtail) % vring->size;
+ return (vring->size + swhead - swtail) % vring->size;
+}
- return vring->size - used - 1;
+/* Available space in Tx Vring */
+static inline int wil_vring_avail_tx(struct vring *vring)
+{
+ return vring->size - wil_vring_used_tx(vring) - 1;
}
-/**
- * wil_vring_wmark_low - low watermark for available descriptor space
- */
+/* wil_vring_wmark_low - low watermark for available descriptor space */
static inline int wil_vring_wmark_low(struct vring *vring)
{
return vring->size/8;
}
-/**
- * wil_vring_wmark_high - high watermark for available descriptor space
- */
+/* wil_vring_wmark_high - high watermark for available descriptor space */
static inline int wil_vring_wmark_high(struct vring *vring)
{
return vring->size/4;
}
+/* wil_val_in_range - check if value in [min,max) */
+static inline bool wil_val_in_range(int val, int min, int max)
+{
+ return val >= min && val < max;
+}
+
static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
{
struct device *dev = wil_to_dev(wil);
@@ -98,8 +102,7 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
vring->va = NULL;
return -ENOMEM;
}
- /*
- * vring->va should be aligned on its size rounded up to power of 2
+ /* vring->va should be aligned on its size rounded up to power of 2
* This is granted by the dma_alloc_coherent
*/
vring->va = dma_alloc_coherent(dev, sz, &vring->pa, GFP_KERNEL);
@@ -346,27 +349,6 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
}
}
-/*
- * Fast swap in place between 2 registers
- */
-static void wil_swap_u16(u16 *a, u16 *b)
-{
- *a ^= *b;
- *b ^= *a;
- *a ^= *b;
-}
-
-static void wil_swap_ethaddr(void *data)
-{
- struct ethhdr *eth = data;
- u16 *s = (u16 *)eth->h_source;
- u16 *d = (u16 *)eth->h_dest;
-
- wil_swap_u16(s++, d++);
- wil_swap_u16(s++, d++);
- wil_swap_u16(s, d);
-}
-
/**
* reap 1 frame from @swhead
*
@@ -386,17 +368,16 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
unsigned int sz = mtu_max + ETH_HLEN;
u16 dmalen;
u8 ftype;
- u8 ds_bits;
int cid;
struct wil_net_stats *stats;
BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb));
- if (wil_vring_is_empty(vring))
+ if (unlikely(wil_vring_is_empty(vring)))
return NULL;
_d = &vring->va[vring->swhead].rx;
- if (!(_d->dma.status & RX_DMA_STATUS_DU)) {
+ if (unlikely(!(_d->dma.status & RX_DMA_STATUS_DU))) {
/* it is not error, we just reached end of Rx done area */
return NULL;
}
@@ -416,7 +397,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4,
(const void *)d, sizeof(*d), false);
- if (dmalen > sz) {
+ if (unlikely(dmalen > sz)) {
wil_err(wil, "Rx size too large: %d bytes!\n", dmalen);
kfree_skb(skb);
return NULL;
@@ -445,14 +426,14 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
* in Rx descriptor. If type is not data, it is 802.11 frame as is
*/
ftype = wil_rxdesc_ftype(d) << 2;
- if (ftype != IEEE80211_FTYPE_DATA) {
+ if (unlikely(ftype != IEEE80211_FTYPE_DATA)) {
wil_dbg_txrx(wil, "Non-data frame ftype 0x%08x\n", ftype);
/* TODO: process it */
kfree_skb(skb);
return NULL;
}
- if (skb->len < ETH_HLEN) {
+ if (unlikely(skb->len < ETH_HLEN)) {
wil_err(wil, "Short frame, len = %d\n", skb->len);
/* TODO: process it (i.e. BAR) */
kfree_skb(skb);
@@ -463,9 +444,9 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
* and in case of error drop the packet
* higher stack layers will handle retransmission (if required)
*/
- if (d->dma.status & RX_DMA_STATUS_L4I) {
+ if (likely(d->dma.status & RX_DMA_STATUS_L4I)) {
/* L4 protocol identified, csum calculated */
- if ((d->dma.error & RX_DMA_ERROR_L4_ERR) == 0)
+ if (likely((d->dma.error & RX_DMA_ERROR_L4_ERR) == 0))
skb->ip_summed = CHECKSUM_UNNECESSARY;
/* If HW reports bad checksum, let IP stack re-check it
* For example, HW don't understand Microsoft IP stack that
@@ -474,15 +455,6 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
*/
}
- ds_bits = wil_rxdesc_ds_bits(d);
- if (ds_bits == 1) {
- /*
- * HW bug - in ToDS mode, i.e. Rx on AP side,
- * addresses get swapped
- */
- wil_swap_ethaddr(skb->data);
- }
-
return skb;
}
@@ -503,7 +475,7 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count)
(next_tail != v->swhead) && (count-- > 0);
v->swtail = next_tail) {
rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom);
- if (rc) {
+ if (unlikely(rc)) {
wil_err(wil, "Error %d in wil_rx_refill[%d]\n",
rc, v->swtail);
break;
@@ -565,7 +537,7 @@ void wil_rx_handle(struct wil6210_priv *wil, int *quota)
struct vring *v = &wil->vring_rx;
struct sk_buff *skb;
- if (!v->va) {
+ if (unlikely(!v->va)) {
wil_err(wil, "Rx IRQ while Rx not yet initialized\n");
return;
}
@@ -952,13 +924,14 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index];
uint i = swhead;
dma_addr_t pa;
+ int used;
wil_dbg_txrx(wil, "%s()\n", __func__);
if (unlikely(!txdata->enabled))
return -EINVAL;
- if (avail < 1 + nr_frags) {
+ if (unlikely(avail < 1 + nr_frags)) {
wil_err_ratelimited(wil,
"Tx ring[%2d] full. No space for %d fragments\n",
vring_index, 1 + nr_frags);
@@ -979,7 +952,7 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
/* 1-st segment */
wil_tx_desc_map(d, pa, skb_headlen(skb), vring_index);
/* Process TCP/UDP checksum offloading */
- if (wil_tx_desc_offload_cksum_set(wil, d, skb)) {
+ if (unlikely(wil_tx_desc_offload_cksum_set(wil, d, skb))) {
wil_err(wil, "Tx[%2d] Failed to set cksum, drop packet\n",
vring_index);
goto dma_error;
@@ -1027,8 +1000,14 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
*/
vring->ctx[i].skb = skb_get(skb);
- if (wil_vring_is_empty(vring)) /* performance monitoring */
+ /* performance monitoring */
+ used = wil_vring_used_tx(vring);
+ if (wil_val_in_range(vring_idle_trsh,
+ used, used + nr_frags + 1)) {
txdata->idle += get_cycles() - txdata->last_idle;
+ wil_dbg_txrx(wil, "Ring[%2d] not idle %d -> %d\n",
+ vring_index, used, used + nr_frags + 1);
+ }
/* advance swhead */
wil_vring_advance_head(vring, nr_frags + 1);
@@ -1082,18 +1061,18 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
int rc;
wil_dbg_txrx(wil, "%s()\n", __func__);
- if (!test_bit(wil_status_fwready, wil->status)) {
+ if (unlikely(!test_bit(wil_status_fwready, wil->status))) {
if (!pr_once_fw) {
wil_err(wil, "FW not ready\n");
pr_once_fw = true;
}
goto drop;
}
- if (!test_bit(wil_status_fwconnected, wil->status)) {
+ if (unlikely(!test_bit(wil_status_fwconnected, wil->status))) {
wil_err(wil, "FW not connected\n");
goto drop;
}
- if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
+ if (unlikely(wil->wdev->iftype == NL80211_IFTYPE_MONITOR)) {
wil_err(wil, "Xmit in monitor mode not supported\n");
goto drop;
}
@@ -1109,7 +1088,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
else
vring = wil_tx_bcast(wil, skb);
}
- if (!vring) {
+ if (unlikely(!vring)) {
wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest);
goto drop;
}
@@ -1117,7 +1096,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
rc = wil_tx_vring(wil, vring, skb);
/* do we still have enough room in the vring? */
- if (wil_vring_avail_tx(vring) < wil_vring_wmark_low(vring)) {
+ if (unlikely(wil_vring_avail_tx(vring) < wil_vring_wmark_low(vring))) {
netif_tx_stop_all_queues(wil_to_ndev(wil));
wil_dbg_txrx(wil, "netif_tx_stop : ring full\n");
}
@@ -1172,19 +1151,23 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
int cid = wil->vring2cid_tid[ringid][0];
struct wil_net_stats *stats = &wil->sta[cid].stats;
volatile struct vring_tx_desc *_d;
+ int used_before_complete;
+ int used_new;
- if (!vring->va) {
+ if (unlikely(!vring->va)) {
wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid);
return 0;
}
- if (!txdata->enabled) {
+ if (unlikely(!txdata->enabled)) {
wil_info(wil, "Tx irq[%d]: vring disabled\n", ringid);
return 0;
}
wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid);
+ used_before_complete = wil_vring_used_tx(vring);
+
while (!wil_vring_is_empty(vring)) {
int new_swtail;
struct wil_ctx *ctx = &vring->ctx[vring->swtail];
@@ -1196,7 +1179,7 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
/* TODO: check we are not past head */
_d = &vring->va[lf].tx;
- if (!(_d->dma.status & TX_DMA_STATUS_DU))
+ if (unlikely(!(_d->dma.status & TX_DMA_STATUS_DU)))
break;
new_swtail = (lf + 1) % vring->size;
@@ -1224,7 +1207,7 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
wil_txdesc_unmap(dev, d, ctx);
if (skb) {
- if (d->dma.error == 0) {
+ if (likely(d->dma.error == 0)) {
ndev->stats.tx_packets++;
stats->tx_packets++;
ndev->stats.tx_bytes += skb->len;
@@ -1246,8 +1229,12 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
}
}
- if (wil_vring_is_empty(vring)) { /* performance monitoring */
- wil_dbg_txrx(wil, "Ring[%2d] empty\n", ringid);
+ /* performance monitoring */
+ used_new = wil_vring_used_tx(vring);
+ if (wil_val_in_range(vring_idle_trsh,
+ used_new, used_before_complete)) {
+ wil_dbg_txrx(wil, "Ring[%2d] idle %d -> %d\n",
+ ringid, used_before_complete, used_new);
txdata->last_idle = get_cycles();
}
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 9461156..b6e65c3 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -27,9 +27,11 @@ extern bool no_fw_recovery;
extern unsigned int mtu_max;
extern unsigned short rx_ring_overflow_thrsh;
extern int agg_wsize;
+extern u32 vring_idle_trsh;
#define WIL_NAME "wil6210"
-#define WIL_FW_NAME "wil6210.fw"
+#define WIL_FW_NAME "wil6210.fw" /* code */
+#define WIL_FW2_NAME "wil6210.board" /* board & radio parameters */
#define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */
@@ -120,6 +122,16 @@ struct RGF_ICR {
u32 IMC; /* Mask Clear, write 1 to clear */
} __packed;
+struct RGF_BL {
+ u32 ready; /* 0x880A3C bit [0] */
+#define BIT_BL_READY BIT(0)
+ u32 version; /* 0x880A40 version of the BL struct */
+ u32 rf_type; /* 0x880A44 ID of the connected RF */
+ u32 baseband_type; /* 0x880A48 ID of the baseband */
+ u8 mac_address[ETH_ALEN]; /* 0x880A4C permanent MAC */
+ u8 pad[2];
+} __packed;
+
/* registers - FW addresses */
#define RGF_USER_USAGE_1 (0x880004)
#define RGF_USER_USAGE_6 (0x880018)
@@ -130,6 +142,7 @@ struct RGF_ICR {
#define RGF_USER_MAC_CPU_0 (0x8801fc)
#define BIT_USER_MAC_CPU_MAN_RST BIT(1) /* mac_cpu_man_rst */
#define RGF_USER_USER_SCRATCH_PAD (0x8802bc)
+#define RGF_USER_BL (0x880A3C) /* Boot Loader */
#define RGF_USER_FW_REV_ID (0x880a8c) /* chip revision */
#define RGF_USER_CLKS_CTL_0 (0x880abc)
#define BIT_USER_CLKS_CAR_AHB_SW_SEL BIT(1) /* ref clk/PLL */
@@ -169,6 +182,13 @@ struct RGF_ICR {
#define BIT_DMA_ITR_CNT_CRL_CLR BIT(3)
#define BIT_DMA_ITR_CNT_CRL_REACH_TRSH BIT(4)
+/* Offload control (Sparrow B0+) */
+#define RGF_DMA_OFUL_NID_0 (0x881cd4)
+ #define BIT_DMA_OFUL_NID_0_RX_EXT_TR_EN BIT(0)
+ #define BIT_DMA_OFUL_NID_0_TX_EXT_TR_EN BIT(1)
+ #define BIT_DMA_OFUL_NID_0_RX_EXT_A3_SRC BIT(2)
+ #define BIT_DMA_OFUL_NID_0_TX_EXT_A3_SRC BIT(3)
+
/* New (sparrow v2+) interrupt moderation control */
#define RGF_DMA_ITR_TX_DESQ_NO_MOD (0x881d40)
#define RGF_DMA_ITR_TX_CNT_TRSH (0x881d34)
@@ -229,16 +249,10 @@ struct RGF_ICR {
#define BIT_CAF_OSC_DIG_XTAL_STABLE BIT(0)
#define RGF_USER_JTAG_DEV_ID (0x880b34) /* device ID */
- #define JTAG_DEV_ID_MARLON_B0 (0x0612072f)
- #define JTAG_DEV_ID_SPARROW_A0 (0x0632072f)
- #define JTAG_DEV_ID_SPARROW_A1 (0x1632072f)
#define JTAG_DEV_ID_SPARROW_B0 (0x2632072f)
enum {
HW_VER_UNKNOWN,
- HW_VER_MARLON_B0, /* JTAG_DEV_ID_MARLON_B0 */
- HW_VER_SPARROW_A0, /* JTAG_DEV_ID_SPARROW_A0 */
- HW_VER_SPARROW_A1, /* JTAG_DEV_ID_SPARROW_A1 */
HW_VER_SPARROW_B0, /* JTAG_DEV_ID_SPARROW_B0 */
};
@@ -482,8 +496,6 @@ enum {
};
enum {
- hw_capability_reset_v2 = 0,
- hw_capability_advanced_itr_moderation = 1,
hw_capability_last
};
@@ -528,7 +540,7 @@ struct wil6210_priv {
wait_queue_head_t wq; /* for all wait_event() use */
/* profile */
u32 monitor_flags;
- u32 secure_pcp; /* create secure PCP? */
+ u32 privacy; /* secure connection? */
int sinfo_gen;
/* interrupt moderation */
u32 tx_max_burst_duration;
@@ -658,7 +670,7 @@ int wil_if_add(struct wil6210_priv *wil);
void wil_if_remove(struct wil6210_priv *wil);
int wil_priv_init(struct wil6210_priv *wil);
void wil_priv_deinit(struct wil6210_priv *wil);
-int wil_reset(struct wil6210_priv *wil);
+int wil_reset(struct wil6210_priv *wil, bool no_fw);
void wil_fw_error_recovery(struct wil6210_priv *wil);
void wil_set_recovery_state(struct wil6210_priv *wil, int state);
int wil_up(struct wil6210_priv *wil);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 0f3e433..0213135 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -281,7 +281,6 @@ int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
/*=== Event handlers ===*/
static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
{
- struct net_device *ndev = wil_to_ndev(wil);
struct wireless_dev *wdev = wil->wdev;
struct wmi_ready_event *evt = d;
@@ -290,11 +289,7 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
wil_info(wil, "FW ver. %d; MAC %pM; %d MID's\n", wil->fw_version,
evt->mac, wil->n_mids);
-
- if (!is_valid_ether_addr(ndev->dev_addr)) {
- memcpy(ndev->dev_addr, evt->mac, ETH_ALEN);
- memcpy(ndev->perm_addr, evt->mac, ETH_ALEN);
- }
+ /* ignore MAC address, we already have it from the boot loader */
snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version),
"%d", wil->fw_version);
}
@@ -879,7 +874,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan)
struct wmi_pcp_started_event evt;
} __packed reply;
- if (!wil->secure_pcp)
+ if (!wil->privacy)
cmd.disable_sec = 1;
if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) ||
OpenPOWER on IntegriCloud