diff options
author | Sriram R <srirrama@codeaurora.org> | 2020-06-11 08:09:54 +0300 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2020-06-15 17:33:10 +0300 |
commit | 0dd6392ac2c0eb3e229631744f54b61789139e33 (patch) | |
tree | 885f6a4ac4f5371e95b2c5d9ec24765be54de1de /drivers/net/wireless/ath | |
parent | 8cacd0389c4f6056250377f44fbfe18a2501dd79 (diff) |
ath11k: Add dp tx err stats
Add support for dp tx error stats which logs tx failure reasons due
to ring full condition, etc. This stats is added in soc_dp_stats
which was earlier used as soc_rx_stats so that all dp related info
are logged in same file.
Below is an example usage,
root@OpenWrt:/# cat /sys/kernel/debug/ath11k/ipq8074/soc_dp_stats
SOC RX STATS:
err ring pkts: 0
Invalid RBM: 0
<snip>
SOC TX STATS:
Ring Full Failures:
ring0: 4
ring1: 3
ring2: 5
Misc Transmit Failures: 2
Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.1.0.1-01213-QCAHKSWPL_SILICONZ-1
Signed-off-by: Sriram R <srirrama@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/1591768308-32005-2-git-send-email-srirrama@codeaurora.org
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath11k/core.h | 14 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath11k/debug.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath11k/dp_tx.c | 7 |
3 files changed, 35 insertions, 9 deletions
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 7e9e9762b1ca..1ff54c2c2c95 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -590,12 +590,22 @@ struct ath11k_board_data { /* IPQ8074 HW channel counters frequency value in hertz */ #define IPQ8074_CC_FREQ_HERTZ 320000 -struct ath11k_soc_dp_rx_stats { +struct ath11k_soc_dp_tx_err_stats { + /* TCL Ring Descriptor unavailable */ + u32 desc_na[DP_TCL_NUM_RING_MAX]; + /* Other failures during dp_tx due to mem allocation failure + * idr unavailable etc. + */ + atomic_t misc_fail; +}; + +struct ath11k_soc_dp_stats { u32 err_ring_pkts; u32 invalid_rbm; u32 rxdma_error[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX]; u32 reo_error[HAL_REO_DEST_RING_ERROR_CODE_MAX]; u32 hal_reo_error[DP_REO_DST_RING_MAX]; + struct ath11k_soc_dp_tx_err_stats tx_err; }; /* Master structure to hold the hw data which may be used in core module */ @@ -664,7 +674,7 @@ struct ath11k_base { struct dentry *debugfs_soc; struct dentry *debugfs_ath11k; #endif - struct ath11k_soc_dp_rx_stats soc_stats; + struct ath11k_soc_dp_stats soc_stats; unsigned long dev_flags; struct completion driver_recovery; diff --git a/drivers/net/wireless/ath/ath11k/debug.c b/drivers/net/wireless/ath/ath11k/debug.c index 3fd6b5af073b..647d5a50043f 100644 --- a/drivers/net/wireless/ath/ath11k/debug.c +++ b/drivers/net/wireless/ath/ath11k/debug.c @@ -739,12 +739,12 @@ static const struct file_operations fops_extd_rx_stats = { .open = simple_open, }; -static ssize_t ath11k_debug_dump_soc_rx_stats(struct file *file, +static ssize_t ath11k_debug_dump_soc_dp_stats(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath11k_base *ab = file->private_data; - struct ath11k_soc_dp_rx_stats *soc_stats = &ab->soc_stats; + struct ath11k_soc_dp_stats *soc_stats = &ab->soc_stats; int len = 0, i, retval; const int size = 4096; static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = { @@ -788,6 +788,17 @@ static ssize_t ath11k_debug_dump_soc_rx_stats(struct file *file, soc_stats->hal_reo_error[2], soc_stats->hal_reo_error[3]); + len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n"); + len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n"); + + for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) + len += scnprintf(buf + len, size - len, "ring%d: %u\n", + i, soc_stats->tx_err.desc_na[i]); + + len += scnprintf(buf + len, size - len, + "\nMisc Transmit Failures: %d\n", + atomic_read(&soc_stats->tx_err.misc_fail)); + if (len > size) len = size; retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); @@ -796,8 +807,8 @@ static ssize_t ath11k_debug_dump_soc_rx_stats(struct file *file, return retval; } -static const struct file_operations fops_soc_rx_stats = { - .read = ath11k_debug_dump_soc_rx_stats, +static const struct file_operations fops_soc_dp_stats = { + .read = ath11k_debug_dump_soc_dp_stats, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, @@ -819,8 +830,8 @@ int ath11k_debug_pdev_create(struct ath11k_base *ab) debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab, &fops_simulate_fw_crash); - debugfs_create_file("soc_rx_stats", 0600, ab->debugfs_soc, ab, - &fops_soc_rx_stats); + debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab, + &fops_soc_dp_stats); return 0; } diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index 41c990aec6b7..1af76775b1a8 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -121,8 +121,10 @@ tcl_ring_sel: spin_unlock_bh(&tx_ring->tx_idr_lock); if (ret < 0) { - if (ring_map == (BIT(DP_TCL_NUM_RING_MAX) - 1)) + if (ring_map == (BIT(DP_TCL_NUM_RING_MAX) - 1)) { + atomic_inc(&ab->soc_stats.tx_err.misc_fail); return -ENOSPC; + } /* Check if the next ring is available */ ring_selector++; @@ -180,11 +182,13 @@ tcl_ring_sel: default: /* TODO: Take care of other encap modes as well */ ret = -EINVAL; + atomic_inc(&ab->soc_stats.tx_err.misc_fail); goto fail_remove_idr; } ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE); if (dma_mapping_error(ab->dev, ti.paddr)) { + atomic_inc(&ab->soc_stats.tx_err.misc_fail); ath11k_warn(ab, "failed to DMA map data Tx buffer\n"); ret = -ENOMEM; goto fail_remove_idr; @@ -208,6 +212,7 @@ tcl_ring_sel: * desc because the desc is directly enqueued onto hw queue. */ ath11k_hal_srng_access_end(ab, tcl_ring); + ab->soc_stats.tx_err.desc_na[ti.ring_id]++; spin_unlock_bh(&tcl_ring->lock); ret = -ENOMEM; |