Skip to content

Commit

Permalink
ath10k: refactor phyerr event handlers
Browse files Browse the repository at this point in the history
Existing phyerr event handlers directly uses phyerr header format
(ie, struct wmi_phyerr and struct wmi_phyerr_event) in the code
exactly on how firmware packs it. This is the problem in 10.4 fw
specific phyerr event handling where it uses different phyerror
header format. Before adding 10.4 specific handler, little bit of
refactor is done in existing phyerr handlers.

Two new abstracted structures (struct wmi_phyerr_ev_hdr_arg and
struct wmi_phyerr_ev_arg) are introduced to remove dependency of using
firmware specific header format in the code. So that firmware specific
phyerror handlers can populate values to abstracted structures and
the following code can use abstracted struct for further operation.

.pull_phyerr_hdr is added newly to pull common phyerr header info
like tsf, buf_len, number of phyerr packed. Existing .pull_phyerr
handler is changed and called to parse every sub phyerrs in the event.

Validated these refactoring on qca988x hw2.0 using fw 10.2.4 version.

Signed-off-by: Raja Mani <rmani@qti.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
  • Loading branch information
Raja Mani authored and Kalle Valo committed Aug 17, 2015
1 parent f4bbb82 commit 991adf7
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 67 deletions.
9 changes: 4 additions & 5 deletions drivers/net/wireless/ath/ath10k/spectral.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len,
}

int ath10k_spectral_process_fft(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
const struct phyerr_fft_report *fftr,
size_t bin_len, u64 tsf)
{
Expand Down Expand Up @@ -118,15 +118,14 @@ int ath10k_spectral_process_fft(struct ath10k *ar,
fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);

freq1 = __le16_to_cpu(phyerr->freq1);
freq2 = __le16_to_cpu(phyerr->freq2);
freq1 = phyerr->freq1;
freq2 = phyerr->freq2;
fft_sample->freq1 = __cpu_to_be16(freq1);
fft_sample->freq2 = __cpu_to_be16(freq2);

chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);

fft_sample->noise = __cpu_to_be16(
__le16_to_cpu(phyerr->nf_chains[chain_idx]));
fft_sample->noise = __cpu_to_be16(phyerr->nf_chains[chain_idx]);

bins = (u8 *)fftr;
bins += sizeof(*fftr);
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/ath/ath10k/spectral.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ enum ath10k_spectral_mode {
#ifdef CONFIG_ATH10K_DEBUGFS

int ath10k_spectral_process_fft(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
const struct phyerr_fft_report *fftr,
size_t bin_len, u64 tsf);
int ath10k_spectral_start(struct ath10k *ar);
Expand All @@ -59,7 +59,7 @@ void ath10k_spectral_destroy(struct ath10k *ar);

static inline int
ath10k_spectral_process_fft(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
const struct phyerr_fft_report *fftr,
size_t bin_len, u64 tsf)
{
Expand Down
22 changes: 17 additions & 5 deletions drivers/net/wireless/ath/ath10k/wmi-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ struct wmi_ops {
struct wmi_peer_kick_ev_arg *arg);
int (*pull_swba)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_swba_ev_arg *arg);
int (*pull_phyerr)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_phyerr_ev_arg *arg);
int (*pull_phyerr_hdr)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_phyerr_hdr_arg *arg);
int (*pull_phyerr)(struct ath10k *ar, const void *phyerr_buf,
int left_len, struct wmi_phyerr_ev_arg *arg);
int (*pull_svc_rdy)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_svc_rdy_ev_arg *arg);
int (*pull_rdy)(struct ath10k *ar, struct sk_buff *skb,
Expand Down Expand Up @@ -261,13 +263,23 @@ ath10k_wmi_pull_swba(struct ath10k *ar, struct sk_buff *skb,
}

static inline int
ath10k_wmi_pull_phyerr(struct ath10k *ar, struct sk_buff *skb,
struct wmi_phyerr_ev_arg *arg)
ath10k_wmi_pull_phyerr_hdr(struct ath10k *ar, struct sk_buff *skb,
struct wmi_phyerr_hdr_arg *arg)
{
if (!ar->wmi.ops->pull_phyerr_hdr)
return -EOPNOTSUPP;

return ar->wmi.ops->pull_phyerr_hdr(ar, skb, arg);
}

static inline int
ath10k_wmi_pull_phyerr(struct ath10k *ar, const void *phyerr_buf,
int left_len, struct wmi_phyerr_ev_arg *arg)
{
if (!ar->wmi.ops->pull_phyerr)
return -EOPNOTSUPP;

return ar->wmi.ops->pull_phyerr(ar, skb, arg);
return ar->wmi.ops->pull_phyerr(ar, phyerr_buf, left_len, arg);
}

static inline int
Expand Down
17 changes: 9 additions & 8 deletions drivers/net/wireless/ath/ath10k/wmi-tlv.c
Original file line number Diff line number Diff line change
Expand Up @@ -838,9 +838,9 @@ static int ath10k_wmi_tlv_op_pull_swba_ev(struct ath10k *ar,
return 0;
}

static int ath10k_wmi_tlv_op_pull_phyerr_ev(struct ath10k *ar,
struct sk_buff *skb,
struct wmi_phyerr_ev_arg *arg)
static int ath10k_wmi_tlv_op_pull_phyerr_ev_hdr(struct ath10k *ar,
struct sk_buff *skb,
struct wmi_phyerr_hdr_arg *arg)
{
const void **tb;
const struct wmi_tlv_phyerr_ev *ev;
Expand All @@ -862,10 +862,10 @@ static int ath10k_wmi_tlv_op_pull_phyerr_ev(struct ath10k *ar,
return -EPROTO;
}

arg->num_phyerrs = ev->num_phyerrs;
arg->tsf_l32 = ev->tsf_l32;
arg->tsf_u32 = ev->tsf_u32;
arg->buf_len = ev->buf_len;
arg->num_phyerrs = __le32_to_cpu(ev->num_phyerrs);
arg->tsf_l32 = __le32_to_cpu(ev->tsf_l32);
arg->tsf_u32 = __le32_to_cpu(ev->tsf_u32);
arg->buf_len = __le32_to_cpu(ev->buf_len);
arg->phyerrs = phyerrs;

kfree(tb);
Expand Down Expand Up @@ -3407,7 +3407,8 @@ static const struct wmi_ops wmi_tlv_ops = {
.pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev,
.pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev,
.pull_swba = ath10k_wmi_tlv_op_pull_swba_ev,
.pull_phyerr = ath10k_wmi_tlv_op_pull_phyerr_ev,
.pull_phyerr_hdr = ath10k_wmi_tlv_op_pull_phyerr_ev_hdr,
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
.pull_svc_rdy = ath10k_wmi_tlv_op_pull_svc_rdy_ev,
.pull_rdy = ath10k_wmi_tlv_op_pull_rdy_ev,
.pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats,
Expand Down
121 changes: 85 additions & 36 deletions drivers/net/wireless/ath/ath10k/wmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -3271,7 +3271,7 @@ void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, struct sk_buff *skb)
}

static void ath10k_dfs_radar_report(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
const struct phyerr_radar_report *rr,
u64 tsf)
{
Expand Down Expand Up @@ -3315,7 +3315,7 @@ static void ath10k_dfs_radar_report(struct ath10k *ar,
}

/* report event to DFS pattern detector */
tsf32l = __le32_to_cpu(phyerr->tsf_timestamp);
tsf32l = phyerr->tsf_timestamp;
tsf64 = tsf & (~0xFFFFFFFFULL);
tsf64 |= tsf32l;

Expand Down Expand Up @@ -3360,7 +3360,7 @@ static void ath10k_dfs_radar_report(struct ath10k *ar,
}

static int ath10k_dfs_fft_report(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
const struct phyerr_fft_report *fftr,
u64 tsf)
{
Expand Down Expand Up @@ -3398,7 +3398,7 @@ static int ath10k_dfs_fft_report(struct ath10k *ar,
}

void ath10k_wmi_event_dfs(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
u64 tsf)
{
int buf_len, tlv_len, res, i = 0;
Expand All @@ -3407,11 +3407,11 @@ void ath10k_wmi_event_dfs(struct ath10k *ar,
const struct phyerr_fft_report *fftr;
const u8 *tlv_buf;

buf_len = __le32_to_cpu(phyerr->buf_len);
buf_len = phyerr->buf_len;
ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
"wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n",
phyerr->phy_err_code, phyerr->rssi_combined,
__le32_to_cpu(phyerr->tsf_timestamp), tsf, buf_len);
phyerr->tsf_timestamp, tsf, buf_len);

/* Skip event if DFS disabled */
if (!config_enabled(CONFIG_ATH10K_DFS_CERTIFIED))
Expand Down Expand Up @@ -3463,7 +3463,7 @@ void ath10k_wmi_event_dfs(struct ath10k *ar,
}

void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
u64 tsf)
{
int buf_len, tlv_len, res, i = 0;
Expand All @@ -3472,7 +3472,7 @@ void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
const struct phyerr_fft_report *fftr;
size_t fftr_len;

buf_len = __le32_to_cpu(phyerr->buf_len);
buf_len = phyerr->buf_len;

while (i < buf_len) {
if (i + sizeof(*tlv) > buf_len) {
Expand Down Expand Up @@ -3516,65 +3516,110 @@ void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
}
}

static int ath10k_wmi_op_pull_phyerr_ev(struct ath10k *ar, struct sk_buff *skb,
struct wmi_phyerr_ev_arg *arg)
static int ath10k_wmi_op_pull_phyerr_ev_hdr(struct ath10k *ar,
struct sk_buff *skb,
struct wmi_phyerr_hdr_arg *arg)
{
struct wmi_phyerr_event *ev = (void *)skb->data;

if (skb->len < sizeof(*ev))
return -EPROTO;

arg->num_phyerrs = ev->num_phyerrs;
arg->tsf_l32 = ev->tsf_l32;
arg->tsf_u32 = ev->tsf_u32;
arg->buf_len = __cpu_to_le32(skb->len - sizeof(*ev));
arg->num_phyerrs = __le32_to_cpu(ev->num_phyerrs);
arg->tsf_l32 = __le32_to_cpu(ev->tsf_l32);
arg->tsf_u32 = __le32_to_cpu(ev->tsf_u32);
arg->buf_len = skb->len - sizeof(*ev);
arg->phyerrs = ev->phyerrs;

return 0;
}

int ath10k_wmi_op_pull_phyerr_ev(struct ath10k *ar,
const void *phyerr_buf,
int left_len,
struct wmi_phyerr_ev_arg *arg)
{
const struct wmi_phyerr *phyerr = phyerr_buf;
int i;

if (left_len < sizeof(*phyerr)) {
ath10k_warn(ar, "wrong phyerr event head len %d (need: >=%d)\n",
left_len, sizeof(*phyerr));
return -EINVAL;
}

arg->tsf_timestamp = __le32_to_cpu(phyerr->tsf_timestamp);
arg->freq1 = __le16_to_cpu(phyerr->freq1);
arg->freq2 = __le16_to_cpu(phyerr->freq2);
arg->rssi_combined = phyerr->rssi_combined;
arg->chan_width_mhz = phyerr->chan_width_mhz;
arg->buf_len = __le32_to_cpu(phyerr->buf_len);
arg->buf = phyerr->buf;
arg->hdr_len = sizeof(*phyerr);

for (i = 0; i < 4; i++)
arg->nf_chains[i] = __le16_to_cpu(phyerr->nf_chains[i]);

switch (phyerr->phy_err_code) {
case PHY_ERROR_GEN_SPECTRAL_SCAN:
arg->phy_err_code = PHY_ERROR_SPECTRAL_SCAN;
break;
case PHY_ERROR_GEN_FALSE_RADAR_EXT:
arg->phy_err_code = PHY_ERROR_FALSE_RADAR_EXT;
break;
case PHY_ERROR_GEN_RADAR:
arg->phy_err_code = PHY_ERROR_RADAR;
break;
default:
arg->phy_err_code = PHY_ERROR_UNKNOWN;
break;
}

return 0;
}

void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_phyerr_ev_arg arg = {};
const struct wmi_phyerr *phyerr;
struct wmi_phyerr_hdr_arg hdr_arg = {};
struct wmi_phyerr_ev_arg phyerr_arg = {};
const void *phyerr;
u32 count, i, buf_len, phy_err_code;
u64 tsf;
int left_len, ret;

ATH10K_DFS_STAT_INC(ar, phy_errors);

ret = ath10k_wmi_pull_phyerr(ar, skb, &arg);
ret = ath10k_wmi_pull_phyerr_hdr(ar, skb, &hdr_arg);
if (ret) {
ath10k_warn(ar, "failed to parse phyerr event: %d\n", ret);
ath10k_warn(ar, "failed to parse phyerr event hdr: %d\n", ret);
return;
}

left_len = __le32_to_cpu(arg.buf_len);

/* Check number of included events */
count = __le32_to_cpu(arg.num_phyerrs);
count = hdr_arg.num_phyerrs;

tsf = __le32_to_cpu(arg.tsf_u32);
left_len = hdr_arg.buf_len;

tsf = hdr_arg.tsf_u32;
tsf <<= 32;
tsf |= __le32_to_cpu(arg.tsf_l32);
tsf |= hdr_arg.tsf_l32;

ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi event phyerr count %d tsf64 0x%llX\n",
count, tsf);

phyerr = arg.phyerrs;
phyerr = hdr_arg.phyerrs;
for (i = 0; i < count; i++) {
/* Check if we can read event header */
if (left_len < sizeof(*phyerr)) {
ath10k_warn(ar, "single event (%d) wrong head len\n",
ret = ath10k_wmi_pull_phyerr(ar, phyerr, left_len, &phyerr_arg);
if (ret) {
ath10k_warn(ar, "failed to parse phyerr event (%d)\n",
i);
return;
}

left_len -= sizeof(*phyerr);

buf_len = __le32_to_cpu(phyerr->buf_len);
phy_err_code = phyerr->phy_err_code;
left_len -= phyerr_arg.hdr_len;
buf_len = phyerr_arg.buf_len;
phy_err_code = phyerr_arg.phy_err_code;

if (left_len < buf_len) {
ath10k_warn(ar, "single event (%d) wrong buf len\n", i);
Expand All @@ -3585,20 +3630,20 @@ void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)

switch (phy_err_code) {
case PHY_ERROR_RADAR:
ath10k_wmi_event_dfs(ar, phyerr, tsf);
ath10k_wmi_event_dfs(ar, &phyerr_arg, tsf);
break;
case PHY_ERROR_SPECTRAL_SCAN:
ath10k_wmi_event_spectral_scan(ar, phyerr, tsf);
ath10k_wmi_event_spectral_scan(ar, &phyerr_arg, tsf);
break;
case PHY_ERROR_FALSE_RADAR_EXT:
ath10k_wmi_event_dfs(ar, phyerr, tsf);
ath10k_wmi_event_spectral_scan(ar, phyerr, tsf);
ath10k_wmi_event_dfs(ar, &phyerr_arg, tsf);
ath10k_wmi_event_spectral_scan(ar, &phyerr_arg, tsf);
break;
default:
break;
}

phyerr = (void *)phyerr + sizeof(*phyerr) + buf_len;
phyerr = phyerr + phyerr_arg.hdr_len + buf_len;
}
}

Expand Down Expand Up @@ -6197,6 +6242,7 @@ static const struct wmi_ops wmi_ops = {
.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
.pull_swba = ath10k_wmi_op_pull_swba_ev,
.pull_phyerr_hdr = ath10k_wmi_op_pull_phyerr_ev_hdr,
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
.pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev,
.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
Expand Down Expand Up @@ -6268,6 +6314,7 @@ static const struct wmi_ops wmi_10_1_ops = {
.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
.pull_swba = ath10k_wmi_op_pull_swba_ev,
.pull_phyerr_hdr = ath10k_wmi_op_pull_phyerr_ev_hdr,
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
.pull_roam_ev = ath10k_wmi_op_pull_roam_ev,
Expand Down Expand Up @@ -6333,6 +6380,7 @@ static const struct wmi_ops wmi_10_2_ops = {
.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
.pull_swba = ath10k_wmi_op_pull_swba_ev,
.pull_phyerr_hdr = ath10k_wmi_op_pull_phyerr_ev_hdr,
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
.pull_roam_ev = ath10k_wmi_op_pull_roam_ev,
Expand Down Expand Up @@ -6394,6 +6442,7 @@ static const struct wmi_ops wmi_10_2_4_ops = {
.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
.pull_swba = ath10k_wmi_op_pull_swba_ev,
.pull_phyerr_hdr = ath10k_wmi_op_pull_phyerr_ev_hdr,
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
.pull_roam_ev = ath10k_wmi_op_pull_roam_ev,
Expand Down
Loading

0 comments on commit 991adf7

Please sign in to comment.