Skip to content

Commit

Permalink
ath10k-ct: Support custom stats, fix scanning locking issue
Browse files Browse the repository at this point in the history
Signed-off-by: Ben Greear <greearb@candelatech.com>
  • Loading branch information
greearb committed Feb 13, 2018
1 parent e1edd74 commit 4c164c0
Show file tree
Hide file tree
Showing 19 changed files with 604 additions and 51 deletions.
4 changes: 4 additions & 0 deletions ath10k-4.13/core.c
Expand Up @@ -400,6 +400,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
[ATH10K_FW_FEATURE_NO_BMISS_CT] = "no-bmiss-CT",
[ATH10K_FW_FEATURE_HAS_GET_TEMP_CT] = "get-temp-CT",
[ATH10K_FW_FEATURE_HAS_TX_RC_CT] = "tx-rc-CT",
[ATH10K_FW_FEATURE_CUST_STATS_CT] = "cust-stats-CT",
};

static unsigned int ath10k_core_get_fw_feature_str(char *buf,
Expand Down Expand Up @@ -2110,6 +2111,7 @@ static void ath10k_core_restart(struct work_struct *work)
* with conf_mutex it will deadlock.
*/
cancel_work_sync(&ar->set_coverage_class_work);
cancel_work_sync(&ar->stop_scan_work);

mutex_lock(&ar->conf_mutex);

Expand Down Expand Up @@ -2488,6 +2490,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,

clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);

ar->ok_tx_rate_status = false;
ar->running_fw = fw;

ath10k_bmi_start(ar);
Expand Down Expand Up @@ -3206,6 +3209,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
INIT_WORK(&ar->restart_work, ath10k_core_restart);
INIT_WORK(&ar->set_coverage_class_work,
ath10k_core_set_coverage_class_work);
INIT_WORK(&ar->stop_scan_work, ath10k_wmi_stop_scan_work);

init_dummy_netdev(&ar->napi_dev);

Expand Down
11 changes: 11 additions & 0 deletions ath10k-4.13/core.h
Expand Up @@ -540,6 +540,7 @@ struct ath10k_fw_crash_data {
struct ath10k_debug {
struct dentry *debugfs_phy;

struct ath10k_rx_reorder_stats rx_reorder_stats;
struct ath10k_fw_stats fw_stats;
struct completion fw_stats_complete;
bool fw_stats_done;
Expand Down Expand Up @@ -570,6 +571,10 @@ struct ath10k_debug {

/* These counters are kept in software. */
u64 rx_bytes; /* counter, total received bytes */
u32 rx_drop_unchain_oom; /* AMSDU Dropped due to un-chain OOM case */
u32 rx_drop_decap_non_raw_chained;
u32 rx_drop_no_freq;
u32 rx_drop_cac_running;

u32 tx_ok; /* counter, OK tx status count. */
u32 tx_noack; /* counter, no-ack tx status count. */
Expand Down Expand Up @@ -760,6 +765,9 @@ enum ath10k_fw_features {
*/
ATH10K_FW_FEATURE_HAS_TX_RC_CT = 45,

/* Do we support requesting custom stats */
ATH10K_FW_FEATURE_CUST_STATS_CT = 46,

/* keep last */
ATH10K_FW_FEATURE_COUNT,
};
Expand Down Expand Up @@ -927,6 +935,7 @@ struct ath10k {

enum ath10k_hw_rev hw_rev;
u16 dev_id;
bool ok_tx_rate_status; /* Firmware is sending tx-rate status? (CT only) */
bool fw_powerup_failed; /* If true, might take reboot to recover. */
u32 chip_id;
u32 target_version;
Expand Down Expand Up @@ -1191,6 +1200,8 @@ struct ath10k {
struct net_device napi_dev;
struct napi_struct napi;

struct work_struct stop_scan_work;

struct work_struct set_coverage_class_work;
/* protected by conf_mutex */
struct {
Expand Down
170 changes: 164 additions & 6 deletions ath10k-4.13/debug.c
Expand Up @@ -494,7 +494,45 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)

spin_lock_bh(&ar->data_lock);

/*ath10k_warn(ar, "fw-stats-process: stats-id: 0x%x(0x%x)\n", ev->stats_id, __le32_to_cpu(ev->stats_id));*/
/* CT Firmware only */
if (__le32_to_cpu(ev->stats_id) == WMI_REQUEST_STAT_CUSTOM) {
__le32* data;
u32 stats_len;
u32 *my_stats = NULL;
u32 my_len = 0;

if ((ar->running_fw->fw_file.wmi_op_version == ATH10K_FW_WMI_OP_VERSION_10_2) ||
(ar->running_fw->fw_file.wmi_op_version == ATH10K_FW_WMI_OP_VERSION_10_4) ||
(ar->running_fw->fw_file.wmi_op_version == ATH10K_FW_WMI_OP_VERSION_10_2_4)) {
const struct wmi_10_2_stats_event *ev2 = (void *)skb->data;
data = (__le32*)(ev2->data);
stats_len = (skb->len - sizeof(*ev2)) / 4;
} else {
/* Must be 10.1 */
data = (__le32*)(ev->data);
stats_len = (skb->len - sizeof(*ev)) / 4;
}

if (ev->num_pdev_stats == WMI_STAT_CUSTOM_RX_REORDER_STATS) {
my_len = sizeof(ar->debug.rx_reorder_stats) / 4;
my_len = min(my_len, stats_len);
my_stats = (u32*)(&(ar->debug.rx_reorder_stats));
}

/* If we know about the stats, handle it here. */
if (my_stats) {
int i;
for (i = 0; i<my_len; i++) {
my_stats[i] = __le32_to_cpu(data[i]);
}
}
ar->debug.fw_stats_done = true;
complete(&ar->debug.fw_stats_complete);
/*ath10k_warn(ar, "Completed stat-custom, my_len: %u\n", my_len);*/
goto free;
}

if (__le32_to_cpu(ev->stats_id) == WMI_REQUEST_REGISTER_DUMP) {
struct ath10k_reg_dump* regdump;
struct ath10k_fw_stats* sptr = &ar->debug.fw_stats;
Expand Down Expand Up @@ -586,6 +624,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
break;
}/* switch */
}
ar->debug.fw_stats_done = true;
complete(&ar->debug.fw_stats_complete);
goto free;
}
Expand Down Expand Up @@ -752,23 +791,29 @@ static int ath10k_fw_stats_release(struct inode *inode, struct file *file)
return 0;
}

int ath10k_refresh_peer_stats_t(struct ath10k *ar, u32 type)
static int ath10k_refresh_peer_stats_t(struct ath10k *ar, u32 type, u32 specifier)
{
int ret;
unsigned long time_left;

/*ath10k_warn(ar, "Requesting stats (type 0x%x specifier %d jiffies: %lu)\n",
type, specifier, jiffies);*/
reinit_completion(&ar->debug.fw_stats_complete);
ret = ath10k_wmi_request_stats(ar, type);
ret = ath10k_wmi_request_stats(ar, type, specifier);

if (ret) {
ath10k_warn(ar, "could not request stats (type %d ret %d)\n",
type, ret);
ath10k_warn(ar, "could not request stats (type %d ret %d specifier %d)\n",
type, ret, specifier);
return ret;
}

/* ret means 'time-left' here */
time_left =
wait_for_completion_timeout(&ar->debug.fw_stats_complete, 1*HZ);

/* ath10k_warn(ar, "Requested stats (type 0x%x ret %d specifier %d jiffies: %lu time-left: %lu)\n",
type, ret, specifier, jiffies, time_left);*/

if (time_left == 0)
return -ETIMEDOUT;

Expand All @@ -777,17 +822,112 @@ int ath10k_refresh_peer_stats_t(struct ath10k *ar, u32 type)

int ath10k_refresh_peer_stats(struct ath10k *ar)
{
return ath10k_refresh_peer_stats_t(ar, ar->fw_stats_req_mask);
return ath10k_refresh_peer_stats_t(ar, ar->fw_stats_req_mask, 0);
}

int ath10k_refresh_target_regs(struct ath10k *ar)
{
if (test_bit(ATH10K_FW_FEATURE_REGDUMP_CT,
ar->running_fw->fw_file.fw_features))
return ath10k_refresh_peer_stats_t(ar, WMI_REQUEST_REGISTER_DUMP);
return ath10k_refresh_peer_stats_t(ar, WMI_REQUEST_REGISTER_DUMP, 0);
return 0; /* fail silently if firmware does not support this option. */
}

int ath10k_refresh_target_rx_reorder_stats(struct ath10k *ar)
{
if (test_bit(ATH10K_FW_FEATURE_CUST_STATS_CT,
ar->running_fw->fw_file.fw_features))
return ath10k_refresh_peer_stats_t(ar, WMI_REQUEST_STAT_CUSTOM, WMI_STAT_CUSTOM_RX_REORDER_STATS);
return 0; /* fail silently if firmware does not support this option. */
}


static ssize_t ath10k_read_rx_reorder_stats(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
struct ath10k_rx_reorder_stats *rrs;
char *buf = NULL;
unsigned int len = 0, buf_len = 8000;
ssize_t ret_cnt = 0;
int ret;

mutex_lock(&ar->conf_mutex);

rrs = &ar->debug.rx_reorder_stats;

if (ar->state != ATH10K_STATE_ON)
goto exit;

buf = kzalloc(buf_len, GFP_KERNEL);
if (!buf)
goto exit;

ret = ath10k_refresh_target_rx_reorder_stats(ar);
if (ret)
goto exit;

len += scnprintf(buf + len, buf_len - len, "\n");
len += scnprintf(buf + len, buf_len - len, "%30s\n",
"ath10k RX Reorder Stats");
len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
"=================");

#define PRINT_MY_STATS(a) len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", #a, rrs->a)
/* Non QoS MPDUs received */
PRINT_MY_STATS(deliver_non_qos);
/* MPDUs received in-order */
PRINT_MY_STATS(deliver_in_order);
/* Flush due to reorder timer expired */
PRINT_MY_STATS(deliver_flush_timeout);
/* Flush due to move out of window */
PRINT_MY_STATS(deliver_flush_oow);
/* Flush due to DELBA */
PRINT_MY_STATS(deliver_flush_delba);
/* MPDUs dropped due to FCS error */
PRINT_MY_STATS(fcs_error);
/* MPDUs dropped due to monitor mode non-data packet */
PRINT_MY_STATS(mgmt_ctrl);
/* MPDUs dropped due to invalid peer */
PRINT_MY_STATS(invalid_peer);
/* MPDUs dropped due to duplication (non aggregation) */
PRINT_MY_STATS(dup_non_aggr);
/* MPDUs dropped due to processed before */
PRINT_MY_STATS(dup_past);
/* MPDUs dropped due to duplicate in reorder queue */
PRINT_MY_STATS(dup_in_reorder);
/* Reorder timeout happened */
PRINT_MY_STATS(reorder_timeout);
/* invalid bar ssn */
PRINT_MY_STATS(invalid_bar_ssn);
/* reorder reset due to bar ssn */
PRINT_MY_STATS(ssn_reset);

/* Added by Ben */
PRINT_MY_STATS(frag_invalid_peer);
PRINT_MY_STATS(frag_fcs_error);
PRINT_MY_STATS(frag_ok);
PRINT_MY_STATS(frag_discards);

PRINT_MY_STATS(rx_chatter);
PRINT_MY_STATS(tkip_mic_error);
PRINT_MY_STATS(tkip_decrypt_error);
PRINT_MY_STATS(mpdu_length_error);
PRINT_MY_STATS(non_frag_unicast_ok);

PRINT_MY_STATS(rx_flush_ind); // Flushed these due to timeout, etc.
PRINT_MY_STATS(rx_flush_ie_add); // Flushed these due to timeout, etc

if (len > buf_len)
len = buf_len;

ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);

exit:
mutex_unlock(&ar->conf_mutex);
kfree(buf);
return ret_cnt;
}

static ssize_t ath10k_read_fw_regs(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
Expand Down Expand Up @@ -966,6 +1106,13 @@ static const struct file_operations fops_fw_regs = {
.llseek = default_llseek,
};

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

static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
Expand Down Expand Up @@ -2125,6 +2272,10 @@ static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
"tx_bytes_to_fw", /* sent to firmware, counts all failures */
"rx_pkts_nic", /* From firmware...maybe should be from driver for symmetry? */
"rx_bytes_nic", /* from driver, firmware does not keep this stat. */
"rx_drop_unchain_oom", /* Dropped due to OOM pressure in unchain_msdu path */
"rx_drop_decap_non_raw_chained",
"rx_drop_no_freq",
"rx_drop_cac_running",
"d_noise_floor",
"d_cycle_count", /* this is duty cycle counter, basically channel-time. 88MHz clock */
"d_tx_cycle_count", /* tx cycle count */
Expand Down Expand Up @@ -2243,6 +2394,10 @@ void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
data[i++] = ar->debug.tx_bytes;
data[i++] = pdev_stats->htt_mpdus;
data[i++] = ar->debug.rx_bytes;
data[i++] = ar->debug.rx_drop_unchain_oom;
data[i++] = ar->debug.rx_drop_decap_non_raw_chained;
data[i++] = ar->debug.rx_drop_no_freq;
data[i++] = ar->debug.rx_drop_cac_running;
data[i++] = pdev_stats->ch_noise_floor;
data[i++] = pdev_stats->cycle_count;
data[i++] = pdev_stats->tx_frame_count;
Expand Down Expand Up @@ -3541,6 +3696,9 @@ int ath10k_debug_register(struct ath10k *ar)
debugfs_create_file("fw_regs", 0400, ar->debug.debugfs_phy, ar,
&fops_fw_regs);

debugfs_create_file("rx_reorder_stats", 0400, ar->debug.debugfs_phy, ar,
&fops_rx_reorder_stats);

debugfs_create_file("wmi_services", 0400, ar->debug.debugfs_phy, ar,
&fops_wmi_services);

Expand Down
11 changes: 8 additions & 3 deletions ath10k-4.13/htt_rx.c
Expand Up @@ -855,6 +855,8 @@ static void ath10k_htt_rx_h_signal(struct ath10k *ar,
/* FIXME: Get real NF */
status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
rxd->ppdu_start.rssi_comb;
/* ath10k_warn(ar, "rx-h-sig, signal: %d chains: 0x%x chain[0]: %d chain[1]: %d chan[2]: %d\n",
status->signal, status->chains, status->chain_signal[0], status->chain_signal[1], status->chain_signal[2]); */
status->flag &= ~RX_FLAG_NO_SIGNAL_VAL;
}

Expand Down Expand Up @@ -1530,7 +1532,7 @@ static void ath10k_htt_rx_h_deliver(struct ath10k *ar,
}
}

static int ath10k_unchain_msdu(struct sk_buff_head *amsdu)
static int ath10k_unchain_msdu(struct ath10k *ar, struct sk_buff_head *amsdu)
{
struct sk_buff *skb, *first;
int space;
Expand All @@ -1552,10 +1554,10 @@ static int ath10k_unchain_msdu(struct sk_buff_head *amsdu)
space = total_len - skb_tailroom(first);
if ((space > 0) &&
(pskb_expand_head(first, 0, space, GFP_ATOMIC) < 0)) {
/* TODO: bump some rx-oom error stat */
/* put it back together so we can free the
* whole list at once.
*/
ar->debug.rx_drop_unchain_oom++;
__skb_queue_head(amsdu, first);
return -1;
}
Expand Down Expand Up @@ -1592,11 +1594,12 @@ static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
*/
if (decap != RX_MSDU_DECAP_RAW ||
skb_queue_len(amsdu) != 1 + rxd->frag_info.ring2_more_count) {
ar->debug.rx_drop_decap_non_raw_chained++;
__skb_queue_purge(amsdu);
return;
}

ath10k_unchain_msdu(amsdu);
ath10k_unchain_msdu(ar, amsdu);
}

static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
Expand All @@ -1609,11 +1612,13 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,

if (!rx_status->freq) {
ath10k_warn(ar, "no channel configured; ignoring frame(s)!\n");
ar->debug.rx_drop_no_freq++;
return false;
}

if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) {
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx cac running\n");
ar->debug.rx_drop_cac_running++;
return false;
}

Expand Down

0 comments on commit 4c164c0

Please sign in to comment.