Skip to content

Commit

Permalink
ath11k: add dbring debug support
Browse files Browse the repository at this point in the history
Target copies spectral report and CFR report through dbring to
host for further processing. This mechanism involves ring and
buffer management in the Host, FW, and uCode, where improper
tail pointer update issues are seen.

This dbring debug support help to debug such issues by tracking
head and tail pointer movement along with the timestamp at which
each buffer is received and replenished.

Provide a debugfs interface to enalbe/disable dbring debug
support and dump the dbring debug entries.

Also introduced a new hardware param to add dbring debugfs support
for few hardwares which are using dbings.

Usage:

echo <dbr_id> <val> > /sys/kernel/debug/ath11k/ipq8074_2/
mac0/enable_dbr_debug

dbr_id: 0 for spectral and 1 for CFR
val: 0 - disable, 1 - enable.

Tested-on: IPQ8074 WLAN.HK.2.4.0.1-01467-QCAHKSWPL_SILICONZ-1

Signed-off-by: Venkateswara Naralasetty <quic_vnaralas@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/1645366059-11798-1-git-send-email-quic_vnaralas@quicinc.com
  • Loading branch information
Venkateswara Naralasetty authored and Kalle Valo committed Feb 24, 2022
1 parent ab0a9ef commit 691425b
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 6 deletions.
6 changes: 6 additions & 0 deletions drivers/net/wireless/ath/ath11k/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_rssi_stats = false,
.fw_wmi_diag_event = false,
.current_cc_support = false,
.dbr_debug_support = true,
},
{
.hw_rev = ATH11K_HW_IPQ6018_HW10,
Expand Down Expand Up @@ -164,6 +165,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_rssi_stats = false,
.fw_wmi_diag_event = false,
.current_cc_support = false,
.dbr_debug_support = true,
},
{
.name = "qca6390 hw2.0",
Expand Down Expand Up @@ -228,6 +230,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_rssi_stats = true,
.fw_wmi_diag_event = true,
.current_cc_support = true,
.dbr_debug_support = false,
},
{
.name = "qcn9074 hw1.0",
Expand Down Expand Up @@ -292,6 +295,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_rssi_stats = false,
.fw_wmi_diag_event = false,
.current_cc_support = false,
.dbr_debug_support = true,
},
{
.name = "wcn6855 hw2.0",
Expand Down Expand Up @@ -356,6 +360,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_rssi_stats = true,
.fw_wmi_diag_event = true,
.current_cc_support = true,
.dbr_debug_support = false,
},
{
.name = "wcn6855 hw2.1",
Expand Down Expand Up @@ -419,6 +424,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_rssi_stats = true,
.fw_wmi_diag_event = true,
.current_cc_support = true,
.dbr_debug_support = false,
},
};

Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/ath11k/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ struct ath11k_debug {
u32 rx_filter;
u32 mem_offset;
u32 module_id_bitmap[MAX_MODULE_ID_BITMAP_WORDS];
struct ath11k_debug_dbr *dbr_debug[WMI_DIRECT_BUF_MAX];
};

struct ath11k_per_peer_tx_stats {
Expand Down
19 changes: 13 additions & 6 deletions drivers/net/wireless/ath/ath11k/dbring.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ static void ath11k_dbring_fill_magic_value(struct ath11k *ar,

static int ath11k_dbring_bufs_replenish(struct ath11k *ar,
struct ath11k_dbring *ring,
struct ath11k_dbring_element *buff)
struct ath11k_dbring_element *buff,
enum wmi_direct_buffer_module id)
{
struct ath11k_base *ab = ar->ab;
struct hal_srng *srng;
Expand Down Expand Up @@ -84,6 +85,7 @@ static int ath11k_dbring_bufs_replenish(struct ath11k *ar,

ath11k_hal_rx_buf_addr_info_set(desc, paddr, cookie, 0);

ath11k_debugfs_add_dbring_entry(ar, id, ATH11K_DBG_DBR_EVENT_REPLENISH, srng);
ath11k_hal_srng_access_end(ab, srng);

return 0;
Expand All @@ -101,7 +103,8 @@ static int ath11k_dbring_bufs_replenish(struct ath11k *ar,
}

static int ath11k_dbring_fill_bufs(struct ath11k *ar,
struct ath11k_dbring *ring)
struct ath11k_dbring *ring,
enum wmi_direct_buffer_module id)
{
struct ath11k_dbring_element *buff;
struct hal_srng *srng;
Expand Down Expand Up @@ -129,7 +132,7 @@ static int ath11k_dbring_fill_bufs(struct ath11k *ar,
kfree(buff);
break;
}
ret = ath11k_dbring_bufs_replenish(ar, ring, buff);
ret = ath11k_dbring_bufs_replenish(ar, ring, buff, id);
if (ret) {
ath11k_warn(ar->ab, "failed to replenish db ring num_remain %d req_ent %d\n",
num_remain, req_entries);
Expand Down Expand Up @@ -210,7 +213,7 @@ int ath11k_dbring_buf_setup(struct ath11k *ar,
ring->hp_addr = ath11k_hal_srng_get_hp_addr(ar->ab, srng);
ring->tp_addr = ath11k_hal_srng_get_tp_addr(ar->ab, srng);

ret = ath11k_dbring_fill_bufs(ar, ring);
ret = ath11k_dbring_fill_bufs(ar, ring, db_cap->id);

return ret;
}
Expand Down Expand Up @@ -270,14 +273,15 @@ int ath11k_dbring_buffer_release_event(struct ath11k_base *ab,
struct ath11k_buffer_addr desc;
u8 *vaddr_unalign;
u32 num_entry, num_buff_reaped;
u8 pdev_idx, rbm;
u8 pdev_idx, rbm, module_id;
u32 cookie;
int buf_id;
int size;
dma_addr_t paddr;
int ret = 0;

pdev_idx = ev->fixed.pdev_id;
module_id = ev->fixed.module_id;

if (pdev_idx >= ab->num_radios) {
ath11k_warn(ab, "Invalid pdev id %d\n", pdev_idx);
Expand Down Expand Up @@ -346,6 +350,9 @@ int ath11k_dbring_buffer_release_event(struct ath11k_base *ab,
dma_unmap_single(ab->dev, buff->paddr, ring->buf_sz,
DMA_FROM_DEVICE);

ath11k_debugfs_add_dbring_entry(ar, module_id,
ATH11K_DBG_DBR_EVENT_RX, srng);

if (ring->handler) {
vaddr_unalign = buff->payload;
handler_data.data = PTR_ALIGN(vaddr_unalign,
Expand All @@ -357,7 +364,7 @@ int ath11k_dbring_buffer_release_event(struct ath11k_base *ab,

buff->paddr = 0;
memset(buff->payload, 0, size);
ath11k_dbring_bufs_replenish(ar, ring, buff);
ath11k_dbring_bufs_replenish(ar, ring, buff, module_id);
}

spin_unlock_bh(&srng->lock);
Expand Down
221 changes: 221 additions & 0 deletions drivers/net/wireless/ath/ath11k/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,45 @@ static const char *htt_bp_lmac_ring[HTT_SW_LMAC_RING_IDX_MAX] = {
"MONITOR_DEST_RING",
};

void ath11k_debugfs_add_dbring_entry(struct ath11k *ar,
enum wmi_direct_buffer_module id,
enum ath11k_dbg_dbr_event event,
struct hal_srng *srng)
{
struct ath11k_debug_dbr *dbr_debug;
struct ath11k_dbg_dbr_data *dbr_data;
struct ath11k_dbg_dbr_entry *entry;

if (id >= WMI_DIRECT_BUF_MAX || event >= ATH11K_DBG_DBR_EVENT_MAX)
return;

dbr_debug = ar->debug.dbr_debug[id];
if (!dbr_debug)
return;

if (!dbr_debug->dbr_debug_enabled)
return;

dbr_data = &dbr_debug->dbr_dbg_data;

spin_lock_bh(&dbr_data->lock);

if (dbr_data->entries) {
entry = &dbr_data->entries[dbr_data->dbr_debug_idx];
entry->hp = srng->u.src_ring.hp;
entry->tp = *srng->u.src_ring.tp_addr;
entry->timestamp = jiffies;
entry->event = event;

dbr_data->dbr_debug_idx++;
if (dbr_data->dbr_debug_idx ==
dbr_data->num_ring_debug_entries)
dbr_data->dbr_debug_idx = 0;
}

spin_unlock_bh(&dbr_data->lock);
}

static void ath11k_fw_stats_pdevs_free(struct list_head *head)
{
struct ath11k_fw_stats_pdev *i, *tmp;
Expand Down Expand Up @@ -1176,6 +1215,169 @@ static const struct file_operations fops_simulate_radar = {
.open = simple_open
};

static ssize_t ath11k_debug_dump_dbr_entries(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath11k_dbg_dbr_data *dbr_dbg_data = file->private_data;
static const char * const event_id_to_string[] = {"empty", "Rx", "Replenish"};
int size = ATH11K_DEBUG_DBR_ENTRIES_MAX * 100;
char *buf;
int i, ret;
int len = 0;

buf = kzalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;

len += scnprintf(buf + len, size - len,
"-----------------------------------------\n");
len += scnprintf(buf + len, size - len,
"| idx | hp | tp | timestamp | event |\n");
len += scnprintf(buf + len, size - len,
"-----------------------------------------\n");

spin_lock_bh(&dbr_dbg_data->lock);

for (i = 0; i < dbr_dbg_data->num_ring_debug_entries; i++) {
len += scnprintf(buf + len, size - len,
"|%4u|%8u|%8u|%11llu|%8s|\n", i,
dbr_dbg_data->entries[i].hp,
dbr_dbg_data->entries[i].tp,
dbr_dbg_data->entries[i].timestamp,
event_id_to_string[dbr_dbg_data->entries[i].event]);
}

spin_unlock_bh(&dbr_dbg_data->lock);

ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);

return ret;
}

static const struct file_operations fops_debug_dump_dbr_entries = {
.read = ath11k_debug_dump_dbr_entries,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};

static void ath11k_debugfs_dbr_dbg_destroy(struct ath11k *ar, int dbr_id)
{
struct ath11k_debug_dbr *dbr_debug;
struct ath11k_dbg_dbr_data *dbr_dbg_data;

if (!ar->debug.dbr_debug[dbr_id])
return;

dbr_debug = ar->debug.dbr_debug[dbr_id];
dbr_dbg_data = &dbr_debug->dbr_dbg_data;

debugfs_remove_recursive(dbr_debug->dbr_debugfs);
kfree(dbr_dbg_data->entries);
kfree(dbr_debug);
ar->debug.dbr_debug[dbr_id] = NULL;
}

static int ath11k_debugfs_dbr_dbg_init(struct ath11k *ar, int dbr_id)
{
struct ath11k_debug_dbr *dbr_debug;
struct ath11k_dbg_dbr_data *dbr_dbg_data;
static const char * const dbr_id_to_str[] = {"spectral", "CFR"};

if (ar->debug.dbr_debug[dbr_id])
return 0;

ar->debug.dbr_debug[dbr_id] = kzalloc(sizeof(*dbr_debug),
GFP_KERNEL);

if (!ar->debug.dbr_debug[dbr_id])
return -ENOMEM;

dbr_debug = ar->debug.dbr_debug[dbr_id];
dbr_dbg_data = &dbr_debug->dbr_dbg_data;

if (dbr_debug->dbr_debugfs)
return 0;

dbr_debug->dbr_debugfs = debugfs_create_dir(dbr_id_to_str[dbr_id],
ar->debug.debugfs_pdev);
if (IS_ERR_OR_NULL(dbr_debug->dbr_debugfs)) {
if (IS_ERR(dbr_debug->dbr_debugfs))
return PTR_ERR(dbr_debug->dbr_debugfs);
return -ENOMEM;
}

dbr_debug->dbr_debug_enabled = true;
dbr_dbg_data->num_ring_debug_entries = ATH11K_DEBUG_DBR_ENTRIES_MAX;
dbr_dbg_data->dbr_debug_idx = 0;
dbr_dbg_data->entries = kcalloc(ATH11K_DEBUG_DBR_ENTRIES_MAX,
sizeof(struct ath11k_dbg_dbr_entry),
GFP_KERNEL);
if (!dbr_dbg_data->entries)
return -ENOMEM;

spin_lock_init(&dbr_dbg_data->lock);

debugfs_create_file("dump_dbr_debug", 0444, dbr_debug->dbr_debugfs,
dbr_dbg_data, &fops_debug_dump_dbr_entries);

return 0;
}

static ssize_t ath11k_debugfs_write_enable_dbr_dbg(struct file *file,
const char __user *ubuf,
size_t count, loff_t *ppos)
{
struct ath11k *ar = file->private_data;
char buf[32] = {0};
u32 dbr_id, enable;
int ret;

mutex_lock(&ar->conf_mutex);

if (ar->state != ATH11K_STATE_ON) {
ret = -ENETDOWN;
goto out;
}

ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
if (ret < 0)
goto out;

buf[ret] = '\0';
ret = sscanf(buf, "%u %u", &dbr_id, &enable);
if (ret != 2 || dbr_id > 1 || enable > 1) {
ret = -EINVAL;
ath11k_warn(ar->ab, "usage: echo <dbr_id> <val> dbr_id:0-Spectral 1-CFR val:0-disable 1-enable\n");
goto out;
}

if (enable) {
ret = ath11k_debugfs_dbr_dbg_init(ar, dbr_id);
if (ret) {
ath11k_warn(ar->ab, "db ring module debugfs init failed: %d\n",
ret);
goto out;
}
} else {
ath11k_debugfs_dbr_dbg_destroy(ar, dbr_id);
}

ret = count;
out:
mutex_unlock(&ar->conf_mutex);
return ret;
}

static const struct file_operations fops_dbr_debug = {
.write = ath11k_debugfs_write_enable_dbr_dbg,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};

int ath11k_debugfs_register(struct ath11k *ar)
{
struct ath11k_base *ab = ar->ab;
Expand Down Expand Up @@ -1218,11 +1420,30 @@ int ath11k_debugfs_register(struct ath11k *ar)
&ar->dfs_block_radar_events);
}

if (ab->hw_params.dbr_debug_support)
debugfs_create_file("enable_dbr_debug", 0200, ar->debug.debugfs_pdev,
ar, &fops_dbr_debug);

return 0;
}

void ath11k_debugfs_unregister(struct ath11k *ar)
{
struct ath11k_debug_dbr *dbr_debug;
struct ath11k_dbg_dbr_data *dbr_dbg_data;
int i;

for (i = 0; i < WMI_DIRECT_BUF_MAX; i++) {
dbr_debug = ar->debug.dbr_debug[i];
if (!dbr_debug)
continue;

dbr_dbg_data = &dbr_debug->dbr_dbg_data;
kfree(dbr_dbg_data->entries);
debugfs_remove_recursive(dbr_debug->dbr_debugfs);
kfree(dbr_debug);
ar->debug.dbr_debug[i] = NULL;
}
}

static ssize_t ath11k_write_twt_add_dialog(struct file *file,
Expand Down
Loading

0 comments on commit 691425b

Please sign in to comment.