Skip to content

Commit

Permalink
ath10k: Work around hang on FW crash, tid config, etc.
Browse files Browse the repository at this point in the history
This updates to latest 4.7 CT kernel ath10k-ct driver.

Signed-off-by: Ben Greear <greearb@candelatech.com>
  • Loading branch information
greearb committed Dec 9, 2016
1 parent 2422547 commit 76533a6
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 12 deletions.
4 changes: 4 additions & 0 deletions ath10k/core.c
Expand Up @@ -2006,10 +2006,12 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV |
WMI_STAT_PEER;
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
ar->num_tids = TARGET_NUM_TIDS;
break;
case ATH10K_FW_WMI_OP_VERSION_10_1:
ar->bmiss_offload_max_vdev = TARGET_10X_BMISS_OFFLOAD_MAX_VDEV;
ar->skid_limit = TARGET_10X_AST_SKID_LIMIT;
ar->num_tids = TARGET_10X_NUM_TIDS;
if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT,
fw_file->fw_features)) {
ar->skid_limit = TARGET_10X_AST_SKID_LIMIT_CT;
Expand All @@ -2031,9 +2033,11 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
if (ath10k_peer_stats_enabled(ar)) {
ar->max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS;
ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS;
ar->num_tids = TARGET_10X_TX_STATS_NUM_TIDS;
} else {
ar->max_num_peers = TARGET_10X_NUM_PEERS;
ar->max_num_stations = TARGET_10X_NUM_STATIONS;
ar->num_tids = TARGET_10X_NUM_TIDS;
}
ar->bmiss_offload_max_vdev = TARGET_10X_BMISS_OFFLOAD_MAX_VDEV;
ar->skid_limit = TARGET_10X_AST_SKID_LIMIT;
Expand Down
4 changes: 2 additions & 2 deletions ath10k/hw.h
Expand Up @@ -407,9 +407,9 @@ enum ath10k_hw_4addr_pad {
#define DEF_TARGET_10X_NUM_VDEVS_CT 16 /* Can support up to 64 with proper config of other settings.
* override w/module parm or fwcfg file */
/* NOTE: AST can really hold 4 keys, and there can be some temporarily in use as well. So this
* needs to be pretty large. 256 works in my testing with 64 station vdevs. --Ben
* needs to be pretty large. 256 works in my testing with 64 station vdevs (360 works better). --Ben
*/
#define TARGET_10X_AST_SKID_LIMIT_CT (ath10k_modparam_target_num_peers_ct * TARGET_10X_NUM_PEER_AST)
#define TARGET_10X_AST_SKID_LIMIT_CT 360 /*((ath10k_modparam_target_num_peers_ct * TARGET_10X_NUM_PEER_AST)*/
#define TARGET_10X_NUM_PEER_KEYS_CT (WMI_MAX_KEY_INDEX + 1) /* 4 */

/* Related to HTC buffers */
Expand Down
48 changes: 42 additions & 6 deletions ath10k/mac.c
Expand Up @@ -4190,13 +4190,37 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work)
}
}

static void ath10k_mac_txq_init(struct ieee80211_txq *txq)
static void ath10k_mac_txq_init(struct ath10k *ar, struct ieee80211_txq *txq)
{
struct ath10k_txq *artxq = (void *)txq->drv_priv;
struct ath10k_txq *tmp, *walker;
struct ieee80211_txq *txq_tmp;
int i = 0;

if (!txq)
return;

spin_lock_bh(&ar->txqs_lock);

/* Remove from ar->txqs in case it still exists there. */
list_for_each_entry_safe(walker, tmp, &ar->txqs, list) {
txq_tmp = container_of((void *)walker, struct ieee80211_txq,
drv_priv);
if ((++i % 10000) == 0) {
ath10k_err(ar, "txq-init: Checking txq_tmp: %p i: %d\n", txq_tmp, i);
ath10k_err(ar, "txq-init: txqs: %p walker->list: %p w->next: %p w->prev: %p ar->txqs: %p\n",
&ar->txqs, &(walker->list), walker->list.next, walker->list.prev, &ar->txqs);
}

if (txq_tmp == txq) {
WARN_ON_ONCE(1);
ath10k_err(ar, "txq-init: Found txq when it should be deleted, txq_tmp: %p txq: %p\n",
txq_tmp, txq);
list_del(&walker->list);
}
}
spin_unlock_bh(&ar->txqs_lock);

INIT_LIST_HEAD(&artxq->list);
}

Expand All @@ -4208,6 +4232,7 @@ static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq)
struct sk_buff *msdu;
struct ieee80211_txq *txq_tmp;
int msdu_id;
int i = 0;

if (!txq)
return;
Expand All @@ -4220,8 +4245,18 @@ static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq)
list_for_each_entry_safe(walker, tmp, &ar->txqs, list) {
txq_tmp = container_of((void *)walker, struct ieee80211_txq,
drv_priv);
if (txq_tmp == txq)
if ((++i % 10000) == 0) {
ath10k_err(ar, "Checking txq_tmp: %p i: %d\n", txq_tmp, i);
ath10k_err(ar, "txqs: %p walker->list: %p w->next: %p w->prev: %p ar->txqs: %p\n",
&ar->txqs, &(walker->list), walker->list.next, walker->list.prev, &ar->txqs);
}

if (txq_tmp == txq) {
WARN_ON_ONCE(1);
ath10k_err(ar, "Found txq when it should be deleted, txq_tmp: %p txq: %p\n",
txq_tmp, txq);
list_del(&walker->list);
}
}
spin_unlock_bh(&ar->txqs_lock);

Expand Down Expand Up @@ -5255,7 +5290,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
mutex_lock(&ar->conf_mutex);

memset(arvif, 0, sizeof(*arvif));
ath10k_mac_txq_init(vif->txq);
ath10k_mac_txq_init(ar, vif->txq);

memset(&arvif->bcast_rate, WMI_FIXED_RATE_NONE, sizeof(arvif->bcast_rate));
memset(&arvif->mcast_rate, WMI_FIXED_RATE_NONE, sizeof(arvif->mcast_rate));
Expand Down Expand Up @@ -5620,8 +5655,9 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
kfree(arvif->u.ap.noa_data);
}

ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i delete (remove interface)\n",
arvif->vdev_id);
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac vdev %i delete (remove interface), vif: %p arvif: %p\n",
arvif->vdev_id, vif, arvif);

ret = ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
if (ret)
Expand Down Expand Up @@ -6437,7 +6473,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
INIT_WORK(&arsta->update_wk, ath10k_sta_rc_update_wk);

for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
ath10k_mac_txq_init(sta->txq[i]);
ath10k_mac_txq_init(ar, sta->txq[i]);
}

/* cancel must be done outside the mutex to avoid deadlock */
Expand Down
20 changes: 16 additions & 4 deletions ath10k/wmi.c
Expand Up @@ -1771,6 +1771,15 @@ static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
bool deliver_cab;
int ret;

/* I saw a kasan warning here, looks like arvif and/or ar might have been
* NULL, add something to catch this if it happens again.
*/
if ((((unsigned long)(arvif)) < 8000) || (((unsigned long)(ar)) < 8000)) {
pr_err("tx-beacon-nowait: arvif: %p ar: %p\n", arvif, ar);
BUG_ON(((unsigned long)(arvif)) < 8000);
BUG_ON(((unsigned long)(ar)) < 8000);
}

spin_lock_bh(&ar->data_lock);

bcn = arvif->beacon;
Expand Down Expand Up @@ -5686,6 +5695,10 @@ static struct sk_buff *ath10k_wmi_10_1_op_gen_init(struct ath10k *ar)
config.rx_decap_mode = __cpu_to_le32(ar->wmi.rx_decap_mode);
config.num_vdevs = __cpu_to_le32(ar->max_num_vdevs);
config.num_peers = __cpu_to_le32(ar->max_num_peers);

ath10k_warn(ar, "10.1 wmi init: vdevs: %d peers: %d tid: %d\n",
ar->max_num_vdevs, ar->max_num_peers, ar->num_tids);

config.tx_chain_mask = __cpu_to_le32(TARGET_10X_TX_CHAIN_MASK);

config.roam_offload_max_vdev =
Expand Down Expand Up @@ -5736,7 +5749,7 @@ static struct sk_buff *ath10k_wmi_10_1_op_gen_init(struct ath10k *ar)
ar->htt.max_num_pending_tx);
}

config.num_tids = __cpu_to_le32(TARGET_10X_NUM_TIDS);
config.num_tids = __cpu_to_le32(ar->num_tids);
config.rx_chain_mask = __cpu_to_le32(TARGET_10X_RX_CHAIN_MASK);
config.rx_timeout_pri_vo = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
Expand Down Expand Up @@ -5801,11 +5814,10 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)

if (ath10k_peer_stats_enabled(ar)) {
config.num_peers = __cpu_to_le32(TARGET_10X_TX_STATS_NUM_PEERS);
config.num_tids = __cpu_to_le32(TARGET_10X_TX_STATS_NUM_TIDS);
} else {
config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS);
config.num_tids = __cpu_to_le32(TARGET_10X_NUM_TIDS);
}
config.num_tids = __cpu_to_le32(ar->num_tids);

config.tx_chain_mask = __cpu_to_le32(TARGET_10X_TX_CHAIN_MASK);

Expand Down Expand Up @@ -8460,7 +8472,7 @@ void ath10k_wmi_free_host_mem(struct ath10k *ar)
dma_unmap_single(ar->dev,
ar->wmi.mem_chunks[i].paddr,
ar->wmi.mem_chunks[i].len,
DMA_TO_DEVICE);
DMA_BIDIRECTIONAL);
kfree(ar->wmi.mem_chunks[i].vaddr);
}

Expand Down

0 comments on commit 76533a6

Please sign in to comment.