M7350/external/compat-wireless/drivers/net/wireless/ath/ath6kl-3.5/diag.c
2024-09-09 08:57:42 +00:00

1444 lines
39 KiB
C

/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/ip.h>
#include "core.h"
#include "wmi.h"
#include "diagnose.h"
#ifdef ATH6KL_DIAGNOSTIC
struct wifi_diag_callbacks diag_evt_callback;
struct sk_buff_head diag_events;
static DEFINE_MUTEX(diag_event_mutex);
enum WIFI_DIAG_PM_STATE {
WIFI_DIAG_PM_STATE_SLEEP = 1,
WIFI_DIAG_PM_STATE_AWAKE = 2,
WIFI_DIAG_PM_STATE_FAKE_SLEEP = 3,
};
/* diag wmi command */
int
ath6kl_wmi_cmd_send_diag(struct wmi *wmi, struct sk_buff *skb,
enum wmid_command_id cmd_id,
enum wmi_sync_flag sync_flag)
{
struct wmid_cmd_hdr *cmd_hdr;
int ret;
skb_push(skb, sizeof(struct wmid_cmd_hdr));
cmd_hdr = (struct wmid_cmd_hdr *) skb->data;
cmd_hdr->cmd_id = cpu_to_le32(cmd_id);
ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_DIAGNOSTIC_CMDID, sync_flag);
return ret;
}
int
ath6kl_wmi_macfilter_cmd(struct wmi *wmi, int type, u32 low, u32 high)
{
struct sk_buff *skb;
int ret;
struct wmid_macfilter_cmd *macfilter;
skb = ath6kl_wmi_get_new_buf(
sizeof(struct wmid_cmd_hdr)+sizeof(*macfilter));
if (!skb)
return -ENOMEM;
macfilter = (struct wmid_macfilter_cmd *)skb->data;
macfilter->type = type;
macfilter->low = low;
macfilter->high = high;
ret = ath6kl_wmi_cmd_send_diag(wmi, skb, WMID_MACFILTER_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
int
ath6kl_wmi_fsm_cmd(struct wmi *wmi, bool enable)
{
struct sk_buff *skb;
int ret;
struct wmid_event_set_cmd *fsm;
skb = ath6kl_wmi_get_new_buf(sizeof(struct wmid_cmd_hdr)+sizeof(*fsm));
if (!skb)
return -ENOMEM;
fsm = (struct wmid_event_set_cmd *)skb->data;
fsm->enable = enable;
ret = ath6kl_wmi_cmd_send_diag(wmi, skb, WMID_FSM_EVENT_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
int
ath6kl_wmi_pwrsave_cmd(struct wmi *wmi, bool enable)
{
struct sk_buff *skb;
int ret;
struct wmid_event_set_cmd *ps;
skb = ath6kl_wmi_get_new_buf(sizeof(struct wmid_cmd_hdr)+sizeof(*ps));
if (!skb)
return -ENOMEM;
ps = (struct wmid_event_set_cmd *)skb->data;
ps->enable = enable;
ret = ath6kl_wmi_cmd_send_diag(wmi, skb, WMID_PWR_SAVE_EVENT_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
int
ath6kl_wmi_interference_cmd(struct wmi *wmi)
{
struct sk_buff *skb;
int ret;
skb = ath6kl_wmi_get_new_buf(sizeof(struct wmid_cmd_hdr));
if (!skb)
return -ENOMEM;
ret = ath6kl_wmi_cmd_send_diag(wmi, skb, WMID_INTERFERENCE_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
int
ath6kl_wmi_rxtime_cmd(struct wmi *wmi)
{
struct sk_buff *skb;
int ret;
skb = ath6kl_wmi_get_new_buf(sizeof(struct wmid_cmd_hdr));
if (!skb)
return -ENOMEM;
ret = ath6kl_wmi_cmd_send_diag(wmi, skb, WMID_RXTIME_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
int
ath6kl_wmi_pktlog_enable_cmd(struct wmi *wmi,
struct wmi_enable_pktlog_cmd *options)
{
struct sk_buff *skb;
struct wmi_enable_pktlog_cmd *cmd;
int status = 0;
skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_enable_pktlog_cmd));
if (!skb)
return -ENOMEM;
cmd = (struct wmi_enable_pktlog_cmd *) skb->data;
cmd->evlist = options->evlist;
cmd->option = options->option;
cmd->trigger_thresh = cpu_to_le32(options->trigger_thresh);
cmd->trigger_interval = cpu_to_le32(options->trigger_interval);
cmd->trigger_tail_count = cpu_to_le32(options->trigger_tail_count);
cmd->buffer_size = cpu_to_le32(options->buffer_size);
status = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_PKTLOG_ENABLE_CMDID,
NO_SYNC_WMIFLAG);
return status;
}
int
ath6kl_wmi_pktlog_disable_cmd(struct wmi *wmi)
{
return ath6kl_wmi_simple_cmd(wmi, 0, WMI_PKTLOG_DISABLE_CMDID);
}
/* diag wmi event */
#if 0
static void
dump_hex(u8 *frm, u32 len)
{
u32 i;
printk(KERN_INFO "\n-----------------------------\n");
for (i = 0; i < len; i++) {
printk(KERN_INFO "0x%02x ", frm[i]);
if ((i+1) % 16 == 0)
printk(KERN_INFO "\n");
}
printk(KERN_INFO "\n");
printk(KERN_INFO "\n=============================\n\n");
}
#endif
int
ath6kl_wmi_pktlog_event_rx(struct wmi *wmi, u8 *datap, u32 len)
{
u8 *pdata = NULL;
struct ath_pktlog_hdr *log_hdr = (struct ath_pktlog_hdr *)datap ;
u32 offset = 0;
struct ath6kl_vif *vif = ath6kl_get_vif_by_index(wmi->parent_dev, 0);
if (vif == NULL)
return -EINVAL;
while (len - offset > 0) {
switch (le16_to_cpu(log_hdr->log_type)) {
case PKTLOG_TYPE_TXSTATUS:
pdata = (u8 *)log_hdr + sizeof(struct ath_pktlog_hdr);
wifi_diag_mac_tx_frame_event(vif,
(struct ath_pktlog_txstatus *)pdata);
break;
case PKTLOG_TYPE_TXCTL:
pdata = (u8 *)log_hdr + sizeof(struct ath_pktlog_hdr);
wifi_diag_mac_txctrl_event(vif,
(struct ath_pktlog_txctl *)pdata);
break;
case PKTLOG_TYPE_RX:
pdata = (u8 *)log_hdr + sizeof(struct ath_pktlog_hdr);
wifi_diag_mac_rx_frame_event(vif,
(struct ath_pktlog_rx *)pdata);
break;
default:
break;
}
offset += le16_to_cpu(log_hdr->size) +
sizeof(struct ath_pktlog_hdr);
log_hdr = (struct ath_pktlog_hdr *)
((u8 *)log_hdr + le16_to_cpu(log_hdr->size) +
sizeof(struct ath_pktlog_hdr));
}
return 0;
}
int
ath6kl_wmi_start_scan_event(struct ath6kl_vif *vif, u32 seq_num)
{
enum wifi_diag_mac_fsm_t fsm_event = WIFI_DIAG_MAC_FSM_SCANNING;
printk(KERN_INFO "ath6kl_wmi_start_scan_event\n");
wifi_diag_mac_fsm_event(vif, fsm_event, seq_num);
return 0;
}
int
ath6kl_wmi_fsm_auth_event(struct ath6kl_vif *vif, u32 seq_num)
{
enum wifi_diag_mac_fsm_t fsm_event = WIFI_DIAG_MAC_FSM_AUTH;
printk(KERN_INFO "ath6kl_wmi_fsm_auth_event\n");
wifi_diag_mac_fsm_event(vif, fsm_event, seq_num);
return 0;
}
int
ath6kl_wmi_fsm_assoc_event(struct ath6kl_vif *vif, u32 seq_num)
{
enum wifi_diag_mac_fsm_t fsm_event = WIFI_DIAG_MAC_FSM_ASSOC;
printk(KERN_INFO "ath6kl_wmi_fsm_assoc_event\n");
wifi_diag_mac_fsm_event(vif, fsm_event, seq_num);
return 0;
}
int
ath6kl_wmi_fsm_deauth_event(struct ath6kl_vif *vif, u32 seq_num)
{
enum wifi_diag_mac_fsm_t fsm_event = WIFI_DIAG_MAC_FSM_DEAUTH;
printk(KERN_INFO "ath6kl_wmi_fsm_deauth_event\n");
wifi_diag_mac_fsm_event(vif, fsm_event, seq_num);
return 0;
}
int
ath6kl_wmi_fsm_disassoc_event(struct ath6kl_vif *vif, u32 seq_num)
{
enum wifi_diag_mac_fsm_t fsm_event = WIFI_DIAG_MAC_FSM_DISASSOC;
printk(KERN_INFO "ath6kl_wmi_fsm_disassoc_event\n");
wifi_diag_mac_fsm_event(vif, fsm_event, seq_num);
return 0;
}
int
ath6kl_wmi_pwrsave_event(struct ath6kl_vif *vif,
struct wmi *wmi, u8 *datap, int len, u32 seq_num)
{
struct wmid_pwr_save_event *state =
(struct wmid_pwr_save_event *)datap;
enum wifi_diag_pwrsave_t oldpwrsave, pmpwrsave;
printk(KERN_INFO "ath6kl_wmi_pwrsave_event\n");
switch (state->oldState) {
case WIFI_DIAG_PM_STATE_SLEEP:
oldpwrsave = WIFI_DIAG_DEEPSLEEP_STOP;
break;
case WIFI_DIAG_PM_STATE_AWAKE:
oldpwrsave = WIFI_DIAG_MAXPERF_STOP;
break;
case WIFI_DIAG_PM_STATE_FAKE_SLEEP:
oldpwrsave = WIFI_DIAG_FAKESLEEP_STOP;
break;
default:
return 0;
break;
}
wifi_diag_send_pwrsave_event(vif, oldpwrsave, seq_num);
switch (state->pmState) {
case WIFI_DIAG_PM_STATE_SLEEP:
pmpwrsave = WIFI_DIAG_DEEPSLEEP_START;
break;
case WIFI_DIAG_PM_STATE_AWAKE:
pmpwrsave = WIFI_DIAG_MAXPERF_START;
break;
case WIFI_DIAG_PM_STATE_FAKE_SLEEP:
pmpwrsave = WIFI_DIAG_FAKESLEEP_START;
break;
default:
return 0;
break;
}
wifi_diag_send_pwrsave_event(vif, pmpwrsave, seq_num);
return 0;
}
int
ath6kl_wmi_diag_event(struct ath6kl_vif *vif,
struct wmi *wmi, struct sk_buff *skb)
{
struct wmid_cmd_hdr *cmd;
u32 len;
u16 id;
u32 seq_num;
u8 *datap;
int ret = 0;
if (skb->len < sizeof(struct wmid_cmd_hdr)) {
printk(KERN_INFO "bad packet 1\n");
return -EINVAL;
}
cmd = (struct wmid_cmd_hdr *) skb->data;
id = le32_to_cpu(cmd->cmd_id);
seq_num = le32_to_cpu(cmd->seq_num);
skb_pull(skb, sizeof(struct wmid_cmd_hdr));
datap = skb->data;
len = skb->len;
switch (id) {
case WMID_START_SCAN_EVENTID:
ret = ath6kl_wmi_start_scan_event(vif, seq_num);
break;
case WMID_FSM_AUTH_EVENTID:
ret = ath6kl_wmi_fsm_auth_event(vif, seq_num);
break;
case WMID_FSM_ASSOC_EVENTID:
ret = ath6kl_wmi_fsm_assoc_event(vif, seq_num);
break;
case WMID_FSM_DEAUTH_EVENTID:
ret = ath6kl_wmi_fsm_deauth_event(vif, seq_num);
break;
case WMID_FSM_DISASSOC_EVENTID:
ret = ath6kl_wmi_fsm_disassoc_event(vif, seq_num);
break;
case WMID_STAT_RX_RATE_EVENTID:
ret = ath6kl_wmi_stat_rx_rate_event(vif, wmi,
datap, len, seq_num);
break;
case WMID_STAT_TX_RATE_EVENTID:
ret = ath6kl_wmi_stat_tx_rate_event(vif, wmi,
datap, len, seq_num);
break;
case WMID_INTERFERENCE_EVENTID:
ath6kl_wmi_interference_event(vif, wmi, datap, len, seq_num);
break;
case WMID_RXTIME_EVENTID:
ath6kl_wmi_rxtime_event(vif, wmi, datap, len, seq_num);
break;
case WMID_PWR_SAVE_EVENTID:
ath6kl_wmi_pwrsave_event(vif, wmi, datap, len, seq_num);
break;
case WMID_FSM_CONNECT_EVENTID:
vif->diag.connect_seq_num = seq_num;
break;
case WMID_FSM_DISCONNECT_EVENTID:
vif->diag.disconnect_seq_num = seq_num;
break;
default:
printk(KERN_INFO "unknown cmd id 0x%x\n", id);
ret = -EINVAL;
break;
}
return ret;
}
/* diag driver handler table */
static struct wifi_drv_hdl_list wifi_drv_hdl_table = {
.wifi_register = wifi_diag_drv_register,
.wifi_unregister = wifi_diag_drv_unregister,
.wifi_diag_reg_event_callback = wifi_diag_register_event_callback,
.wifi_diag_cmd = wifi_diag_cmd_send,
};
void *
wifi_diag_drv_register(void *diag_hdl)
{
return (void *)&wifi_drv_hdl_table;
}
EXPORT_SYMBOL(wifi_diag_drv_register);
enum wifi_diag_status_t
wifi_diag_drv_unregister(void *drv_hdl)
{
struct ath6kl_vif *vif = ath6kl_get_vif_by_index(
globalwmi->parent_dev, 0);
enum wifi_diag_status_t diag_status = WIFI_DIAG_EOK;
ath6kl_wmi_macfilter_cmd(globalwmi,
WMI_PKTLOG_EVENT_TX | WMI_PKTLOG_EVENT_RX,
WIFI_DIAG_MACFILTER_DISABLEALL,
WIFI_DIAG_MACFILTER_DISABLEALL);
ath6kl_wmi_pktlog_disable_cmd(globalwmi);
ath6kl_wmi_fsm_cmd(globalwmi, false);
ath6kl_wmi_pwrsave_cmd(globalwmi, false);
if (vif != NULL)
wifi_diag_timer_destroy(vif);
return diag_status;
}
enum wifi_diag_status_t
wifi_diag_register_event_callback(void *drv_hdl,
struct wifi_diag_callbacks *evt_callback)
{
enum wifi_diag_status_t diag_status = WIFI_DIAG_EOK;
struct ath6kl_vif *vif = ath6kl_get_vif_by_index(
globalwmi->parent_dev, 0);
if (vif == NULL)
return WIFI_DIAG_ENXIO;
if (!vif->diag.diag_event_init) {
skb_queue_head_init(&diag_events);
vif->diag.diag_event_init = true;
}
diag_evt_callback.diag_event_callback =
evt_callback->diag_event_callback;
return diag_status;
}
enum wifi_diag_status_t
wifi_diag_cmd_send(void *drv_hdl, struct wifi_diag_cmd_t *cmd)
{
enum wifi_diag_status_t diag_status = WIFI_DIAG_EOK;
struct ath6kl_vif *vif = ath6kl_get_vif_by_index(
globalwmi->parent_dev, 0);
switch (cmd->cmd_id) {
case WIFI_DIAG_MAC_TX_FILTER_CMDID:
{
if (cmd->len == sizeof(struct wifi_diag_mac_tx_filter_cmd_t)) {
struct wifi_diag_mac_tx_filter_cmd_t *ptxfilter =
(struct wifi_diag_mac_tx_filter_cmd_t *)
cmd->cmd_data;
ath6kl_wmi_macfilter_cmd(globalwmi,
WMI_PKTLOG_EVENT_TX,
ptxfilter->filter_mask_low &
WIFI_DIAG_MACFILTER_LOW_MASK,
ptxfilter->filter_mask_high &
WIFI_DIAG_MACFILTER_HIGH_MASK);
}
break;
}
case WIFI_DIAG_MAC_RX_FILTER_CMDID:
{
if (cmd->len == sizeof(struct wifi_diag_mac_rx_filter_cmd_t)) {
struct wifi_diag_mac_rx_filter_cmd_t *prxfilter =
(struct wifi_diag_mac_rx_filter_cmd_t *)
cmd->cmd_data;
ath6kl_wmi_macfilter_cmd(globalwmi, WMI_PKTLOG_EVENT_RX,
prxfilter->filter_mask_low &
WIFI_DIAG_MACFILTER_LOW_MASK,
prxfilter->filter_mask_high &
WIFI_DIAG_MACFILTER_HIGH_MASK);
}
break;
}
case WIFI_DIAG_CFG_CMDID:
{
if (cmd->len == sizeof(struct wifi_diag_cfg_cmd_t)) {
struct wifi_diag_cfg_cmd_t *pcfg =
(struct wifi_diag_cfg_cmd_t *)cmd->cmd_data;
if (vif == NULL)
return WIFI_DIAG_ENXIO;
if (pcfg->cfg != vif->diag.cfg_mask) {
if (pcfg->cfg &
(WIFI_DIAG_MAC_TX_FRAME_EVENTENABLE |
WIFI_DIAG_MAC_RX_FRAME_EVENTENABLE)) {
ath6kl_wmi_pktlog_disable_cmd(globalwmi);
{
struct wmi_enable_pktlog_cmd cmd;
cmd.option = WMI_PKTLOG_OPTION_LOG_DIAGNOSTIC;
cmd.evlist = 0;
cmd.trigger_interval = 0;
cmd.trigger_tail_count = 0;
cmd.trigger_thresh = 0;
cmd.buffer_size = 1500;
if (pcfg->cfg &
WIFI_DIAG_MAC_TX_FRAME_EVENTENABLE)
cmd.evlist |= WMI_PKTLOG_EVENT_TX;
if (pcfg->cfg &
WIFI_DIAG_MAC_RX_FRAME_EVENTENABLE)
cmd.evlist |=
WMI_PKTLOG_EVENT_RX;
ath6kl_wmi_pktlog_enable_cmd(
globalwmi, &cmd);
}
} else {
ath6kl_wmi_pktlog_disable_cmd(
globalwmi);
}
if (pcfg->cfg & WIFI_DIAG_MAC_FSM_EVENTENABLE)
ath6kl_wmi_fsm_cmd(globalwmi, true);
else
ath6kl_wmi_fsm_cmd(globalwmi, false);
if (pcfg->cfg &
WIFI_DIAG_INTERFERENCE_EVENTENABLE) {
del_timer(&vif->diag.interference_timer);
init_timer(&vif->diag.interference_timer);
setup_timer(&vif->diag.interference_timer,
wifi_diag_interference_timer_handler,
(unsigned long) vif);
mod_timer(
&vif->diag.interference_timer,
jiffies +
msecs_to_jiffies(1000));
} else {
del_timer(&vif->diag.
interference_timer);
}
if (pcfg->cfg & WIFI_DIAG_RX_TIME_EVENTENABLE) {
del_timer(&vif->diag.rxtime_timer);
init_timer(&vif->diag.rxtime_timer);
setup_timer(&vif->diag.rxtime_timer,
wifi_diag_rxtime_timer_handler,
(unsigned long) vif);
mod_timer(&vif->diag.rxtime_timer,
jiffies +
msecs_to_jiffies(1000));
} else {
del_timer(&vif->diag.rxtime_timer);
}
if (pcfg->cfg & WIFI_DIAG_PWR_SAVE_EVENTENABLE)
ath6kl_wmi_pwrsave_cmd(globalwmi, true);
else
ath6kl_wmi_pwrsave_cmd(globalwmi,
false);
if (pcfg->cfg & WIFI_DIAG_TX_STAT_EVENTENABLE) {
vif->diag.tx_timer_val = pcfg->value;
del_timer(&vif->diag.tx_stat_timer);
init_timer(&vif->diag.tx_stat_timer);
setup_timer(&vif->diag.tx_stat_timer,
wifi_diag_tx_stat_timer_handler,
(unsigned long) vif);
mod_timer(&vif->diag.tx_stat_timer,
jiffies +
msecs_to_jiffies(
vif->diag.tx_timer_val));
} else {
del_timer(&vif->diag.tx_stat_timer);
}
if (pcfg->cfg & WIFI_DIAG_RX_STAT_EVENTENABLE) {
vif->diag.rx_timer_val = pcfg->value;
del_timer(&vif->diag.rx_stat_timer);
init_timer(&vif->diag.rx_stat_timer);
setup_timer(&vif->diag.rx_stat_timer,
wifi_diag_rx_stat_timer_handler,
(unsigned long) vif);
mod_timer(&vif->diag.rx_stat_timer,
jiffies +
msecs_to_jiffies(
vif->diag.rx_timer_val));
} else {
del_timer(&vif->diag.rx_stat_timer);
}
vif->diag.cfg_mask = pcfg->cfg;
}
}
break;
}
default:
break;
}
return diag_status;
}
/* wifi diag event */
static const s32 _rate_tbl_11[][2] = {
/* {W/O SGI, with SGI} */
{1000, 1000},
{2000, 2000},
{5500, 5500},
{11000, 11000},
{6000, 6000},
{9000, 9000},
{12000, 12000},
{18000, 18000},
{24000, 24000},
{36000, 36000},
{48000, 48000},
{54000, 54000},
{6500, 7200}, /* HT 20, MCS 0 */
{13000, 14400},
{19500, 21700},
{26000, 28900},
{39000, 43300},
{52000, 57800},
{58500, 65000},
{65000, 72200},
{13000, 14400}, /* HT 20, MCS 8 */
{26000, 28900},
{39000, 43300},
{52000, 57800},
{78000, 86700},
{104000, 115600},
{117000, 130000},
{130000, 144400}, /* HT 20, MCS 15 */
{13500, 15000}, /* HT 40, MCS 0 */
{27000, 30000},
{40500, 45000},
{54000, 60000},
{81000, 90000},
{108000, 120000},
{121500, 135000},
{135000, 150000},
{27000, 30000}, /*HT 40, MCS 8 */
{54000, 60000},
{81000, 90000},
{108000, 120000},
{162000, 180000},
{216000, 240000},
{243000, 270000},
{270000, 300000}, /*HT 40, MCS 15 */
{0, 0}
};
static void wifi_diag_event_process(struct work_struct *work)
{
struct sk_buff *skb;
struct wifi_diag_event_t *pwifi_diag_event;
mutex_lock(&diag_event_mutex);
while ((skb = skb_dequeue(&diag_events))) {
pwifi_diag_event = (struct wifi_diag_event_t *) skb->data;
if (!diag_local_test) {
diag_evt_callback.diag_event_callback(
(void *)&wifi_drv_hdl_table, skb);
} else {
printk(KERN_INFO "eventid=%d seq_num=%d\n",
pwifi_diag_event->event_id,
pwifi_diag_event->seq_num);
switch (pwifi_diag_event->event_id) {
case WIFI_DIAG_MAC_TX_FRAME_EVENTID:
{
struct wifi_diag_mac_tx_frame_event_t
*ptx_frame_event_data;
ptx_frame_event_data =
(struct wifi_diag_mac_tx_frame_event_t *)
pwifi_diag_event->event_data;
if (ptx_frame_event_data->frame_data != 0) {
printk(KERN_INFO "tx wh[0]=%x wh[%d]=%x\n",
ptx_frame_event_data->frame_data[0],
ptx_frame_event_data->frame_length-1,
ptx_frame_event_data->
frame_data[ptx_frame_event_data->
frame_length-1]);
}
printk(KERN_INFO
"frame_type 0x%x frame_subtype 0x%x flen 0x%x pwr %d mcs %d bitrate %d\n",
ptx_frame_event_data->frame_type,
ptx_frame_event_data->frame_sub_type,
ptx_frame_event_data->frame_length,
ptx_frame_event_data->tx_pwr,
ptx_frame_event_data->tx_mcs,
ptx_frame_event_data->tx_bitrate);
}
break;
case WIFI_DIAG_MAC_RX_FRAME_EVENTID:
{
struct wifi_diag_mac_rx_frame_event_t
*prx_frame_event_data;
prx_frame_event_data =
(struct wifi_diag_mac_rx_frame_event_t *)
pwifi_diag_event->event_data;
if (prx_frame_event_data->frame_data != 0) {
printk(KERN_INFO "rx wh[0]=%x wh[%d]=%x\n",
prx_frame_event_data->frame_data[0],
prx_frame_event_data->frame_length-1,
prx_frame_event_data->
frame_data[prx_frame_event_data->
frame_length-1]);
}
printk(KERN_INFO
"rssi %d, frame_type 0x%x frame_subtype 0x%x flen 0x%x rateindex %d bitrate %d\n",
prx_frame_event_data->rssi,
prx_frame_event_data->frame_type,
prx_frame_event_data->frame_sub_type,
prx_frame_event_data->frame_length,
prx_frame_event_data->rx_mcs,
prx_frame_event_data->rx_bitrate);
}
break;
case WIFI_DIAG_MAC_FSM_EVENTID:
{
struct wifi_diag_mac_fsm_event_t
*pfsm_event_data;
pfsm_event_data =
(struct wifi_diag_mac_fsm_event_t *)
pwifi_diag_event->event_data;
printk(KERN_INFO
"fsm event %d\n", pfsm_event_data->fsm);
}
break;
case WIFI_DIAG_INTERFERENCE_EVENTID:
{
struct wifi_diag_interference_event_t
*pinterference_event_data;
pinterference_event_data =
(struct wifi_diag_interference_event_t *)
pwifi_diag_event->event_data;
printk(KERN_INFO
"MAC_PCU_RX_CLEAR_CNT = 0x%x\n",
pinterference_event_data->rx_clear_cnt);
}
break;
case WIFI_DIAG_RX_TIME_EVENTID:
{
struct wifi_diag_rxtime_event_t
*prxtime_event_data;
prxtime_event_data =
(struct wifi_diag_rxtime_event_t *)
pwifi_diag_event->event_data;
printk(KERN_INFO
"MAC_PCU_RX_FRAME_CNT = 0x%x\n",
prxtime_event_data->rx_frame_cnt);
}
break;
case WIFI_DIAG_PWR_SAVE_EVENTID:
{
struct wifi_diag_pwrsave_event_t
*ppwrsave_event_data;
ppwrsave_event_data =
(struct wifi_diag_pwrsave_event_t *)
pwifi_diag_event->event_data;
printk(KERN_INFO
"enum wifi_diag_pwrsave_t = %d\n",
ppwrsave_event_data->pwrsave);
}
break;
case WIFI_DIAG_TX_STAT_EVENTID:
{
u32 i;
struct wifi_diag_tx_stat_event_t
*ptx_stat_event_data;
ptx_stat_event_data =
(struct wifi_diag_tx_stat_event_t *)
pwifi_diag_event->event_data;
printk(KERN_INFO "tx_pkt=%lld, tx_ucast_pkt=%lld, tx_retry_cnt=%lld, tx_fail_cnt=%lld\n",
ptx_stat_event_data->tx_pkt,
ptx_stat_event_data->tx_ucast_pkt,
ptx_stat_event_data->tx_retry_cnt,
ptx_stat_event_data->tx_fail_cnt);
for (i = 0; i < 44; i++)
printk(KERN_INFO "tx_rate_pkt[%d]=%d\n",
i,
ptx_stat_event_data->
tx_rate_pkt[i]
);
}
break;
case WIFI_DIAG_RX_STAT_EVENTID:
{
u32 i;
struct wifi_diag_rx_stat_event_t
*prx_stat_event_data;
prx_stat_event_data =
(struct wifi_diag_rx_stat_event_t *)
pwifi_diag_event->event_data;
printk(KERN_INFO "rx_pkt=%lld, rx_ucast_pkt=%lld, rx_dupl_frame=%lld\n",
prx_stat_event_data->rx_pkt,
prx_stat_event_data->rx_ucast_pkt,
prx_stat_event_data->rx_dupl_frame);
for (i = 0; i < 44; i++)
printk(KERN_INFO
"rx_rate_pkt[%d]=%d\n",
i,
prx_stat_event_data->
rx_rate_pkt[i]
);
}
break;
default:
break;
}
dev_kfree_skb(skb);
}
}
mutex_unlock(&diag_event_mutex);
}
static DECLARE_WORK(wifi_diag_event_work, wifi_diag_event_process);
void
wifi_diag_mac_tx_frame_event(struct ath6kl_vif *vif,
struct ath_pktlog_txstatus *txstatus_log)
{
struct wifi_diag_event_t *pwifi_diag_txframe_event;
struct wifi_diag_mac_tx_frame_event_t *ptx_frame_event_data;
struct sk_buff *skb;
u32 size;
u32 tx_mcs;
u8 sgi = 0;
u32 tx_buf_len = 0;
if (!diag_local_test) {
if (!(vif->diag.cfg_mask & WIFI_DIAG_MAC_TX_FRAME_EVENTENABLE)
|| diag_evt_callback.diag_event_callback == NULL)
return;
}
size = sizeof(*pwifi_diag_txframe_event) +
sizeof(*ptx_frame_event_data) + 512;
skb = ath6kl_wmi_get_new_buf(size);
if (!skb)
return ;
pwifi_diag_txframe_event = (struct wifi_diag_event_t *) skb->data;
pwifi_diag_txframe_event->event_id = WIFI_DIAG_MAC_TX_FRAME_EVENTID;
pwifi_diag_txframe_event->seq_num = le32_to_cpu(txstatus_log->misc[2]);
ptx_frame_event_data = (struct wifi_diag_mac_tx_frame_event_t *)
pwifi_diag_txframe_event->event_data;
ptx_frame_event_data->tx_pwr = txstatus_log->misc[1];
tx_mcs = le16_to_cpu(txstatus_log->misc[0]);
if (tx_mcs > MAX11_RATE_INDEX)
tx_mcs = MAX11_RATE_INDEX;
ptx_frame_event_data->tx_mcs = tx_mcs;
sgi = (txstatus_log->misc[0]>>8) & WHAL_RC_FLAG_SGI;
ptx_frame_event_data->tx_bitrate = _rate_tbl_11[tx_mcs][sgi];
ptx_frame_event_data->frame_type = vif->diag.tx_frame_type;
ptx_frame_event_data->frame_sub_type = vif->diag.tx_frame_subtype;
ptx_frame_event_data->frame_length = vif->diag.tx_frame_len;
tx_buf_len = le32_to_cpu(txstatus_log->buf_len);
pwifi_diag_txframe_event->len = tx_buf_len +
sizeof(*ptx_frame_event_data) - 1;
if (ptx_frame_event_data->frame_data != 0) {
u16 framectrl = vif->diag.tx_frame_subtype << 4 |
vif->diag.tx_frame_type;
memset(ptx_frame_event_data->frame_data, 0, 512);
/* skip 2 pad bytes after qos header, assume there are no addr4 */
if (IEEE80211_QOS_HAS_SEQ(framectrl)) {
tx_buf_len -= IEEE80211_QOS_PADLEN;
pwifi_diag_txframe_event->len -= IEEE80211_QOS_PADLEN;
ptx_frame_event_data->frame_length -=
IEEE80211_QOS_PADLEN;
memcpy(ptx_frame_event_data->frame_data,
txstatus_log->buf, IEEE80211_QOS_HEADERLEN);
memcpy(ptx_frame_event_data->frame_data+
IEEE80211_QOS_HEADERLEN,
txstatus_log->buf+
IEEE80211_QOS_HEADERLEN+
IEEE80211_QOS_PADLEN,
tx_buf_len - IEEE80211_QOS_HEADERLEN);
} else {
memcpy(ptx_frame_event_data->frame_data,
txstatus_log->buf, tx_buf_len);
}
}
if (vif->diag.diag_event_init) {
skb_queue_tail(&diag_events, skb);
schedule_work(&wifi_diag_event_work);
}
}
/* record last descriptor's type, subtype and len for tx log*/
void
wifi_diag_mac_txctrl_event(struct ath6kl_vif *vif,
struct ath_pktlog_txctl *txctrl_log)
{
struct tx_ctrl_desc *txctrl;
if (!diag_local_test) {
if (!(vif->diag.cfg_mask & WIFI_DIAG_MAC_TX_FRAME_EVENTENABLE)
|| diag_evt_callback.diag_event_callback == NULL)
return;
}
vif->diag.tx_frame_type = le16_to_cpu(txctrl_log->framectrl) &
IEEE80211_FC0_TYPE_MASK;
vif->diag.tx_frame_subtype = (le16_to_cpu(txctrl_log->framectrl) &
IEEE80211_FC0_SUBTYPE_MASK) >> 4;
txctrl = (struct tx_ctrl_desc *)txctrl_log->txdesc_ctl;
vif->diag.tx_frame_len = le16_to_cpu(WHAL_TXDESC_GET_FRAME_LEN(txctrl));
}
void
wifi_diag_mac_rx_frame_event(struct ath6kl_vif *vif,
struct ath_pktlog_rx *rx_log)
{
struct wifi_diag_event_t *pwifi_diag_rxframe_event;
struct wifi_diag_mac_rx_frame_event_t *prx_frame_event_data;
struct sk_buff *skb;
u32 size;
struct rx_desc_status *rxstatus;
u8 sgi = 0;
u32 rx_mcs = 0, rx_buf_len = 0;
if (!diag_local_test) {
if (!(vif->diag.cfg_mask & WIFI_DIAG_MAC_RX_FRAME_EVENTENABLE)
|| diag_evt_callback.diag_event_callback == NULL)
return;
}
size = sizeof(*pwifi_diag_rxframe_event) +
sizeof(*prx_frame_event_data) + 512;
skb = ath6kl_wmi_get_new_buf(size);
if (!skb)
return ;
pwifi_diag_rxframe_event = (struct wifi_diag_event_t *) skb->data;
pwifi_diag_rxframe_event->event_id = WIFI_DIAG_MAC_RX_FRAME_EVENTID;
pwifi_diag_rxframe_event->seq_num = rx_log->seq_num;
prx_frame_event_data = (struct wifi_diag_mac_rx_frame_event_t *)
pwifi_diag_rxframe_event->event_data;
rxstatus = (struct rx_desc_status *)&rx_log->rxstatus[0];
prx_frame_event_data->rssi = le16_to_cpu(rxstatus->rsRssi) +
rx_log->calibratednf;
/* this needs to be compensated withnosie floor later */
prx_frame_event_data->snr = le16_to_cpu(rxstatus->rsRssi);
rx_mcs = le32_to_cpu(rx_log->rxmcs);
if (rx_mcs > MAX11_RATE_INDEX)
rx_mcs = MAX11_RATE_INDEX;
prx_frame_event_data->rx_mcs = rx_mcs;
sgi = rxstatus->rsRate.flags & WHAL_RC_FLAG_SGI;
prx_frame_event_data->rx_bitrate = _rate_tbl_11[rx_mcs][sgi];
prx_frame_event_data->fcs = (rxstatus->rsStatus & WHAL_RXERR_CRC) ?
1 : 0;
prx_frame_event_data->frame_type =
le16_to_cpu(rx_log->framectrl) & IEEE80211_FC0_TYPE_MASK;
prx_frame_event_data->frame_sub_type =
(le16_to_cpu(rx_log->framectrl) &
IEEE80211_FC0_SUBTYPE_MASK) >> 4;
prx_frame_event_data->frame_length = le16_to_cpu(rxstatus->rsDataLen);
rx_buf_len = le32_to_cpu(rx_log->buf_len);
pwifi_diag_rxframe_event->len = rx_buf_len +
sizeof(*prx_frame_event_data) - 1;
if (prx_frame_event_data->frame_data != 0) {
memset(prx_frame_event_data->frame_data, 0, 512);
/* skip 2 pad bytes after qos header,
assume there are no addr4 */
if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(rx_log->framectrl))) {
rx_buf_len -= IEEE80211_QOS_PADLEN;
pwifi_diag_rxframe_event->len -= IEEE80211_QOS_PADLEN;
prx_frame_event_data->frame_length -=
IEEE80211_QOS_PADLEN;
memcpy(prx_frame_event_data->frame_data,
rx_log->buf, IEEE80211_QOS_HEADERLEN);
memcpy(prx_frame_event_data->frame_data+
IEEE80211_QOS_HEADERLEN,
rx_log->buf+IEEE80211_QOS_HEADERLEN+
IEEE80211_QOS_PADLEN,
rx_buf_len - IEEE80211_QOS_HEADERLEN);
} else {
memcpy(prx_frame_event_data->frame_data,
rx_log->buf, rx_buf_len);
}
}
if (vif->diag.diag_event_init) {
skb_queue_tail(&diag_events, skb);
schedule_work(&wifi_diag_event_work);
}
}
void
wifi_diag_mac_fsm_event(struct ath6kl_vif *vif,
enum wifi_diag_mac_fsm_t eventtype, u32 seq_num)
{
struct wifi_diag_event_t *pwifi_diag_event;
struct wifi_diag_mac_fsm_event_t *pfsm_event_data;
struct sk_buff *skb;
u32 size;
if (!diag_local_test) {
if (!(vif->diag.cfg_mask & WIFI_DIAG_MAC_FSM_EVENTENABLE)
|| diag_evt_callback.diag_event_callback == NULL)
return;
}
size = sizeof(*pwifi_diag_event) + sizeof(*pfsm_event_data) ;
skb = ath6kl_wmi_get_new_buf(size);
if (!skb)
return;
pwifi_diag_event = (struct wifi_diag_event_t *) skb->data;
pwifi_diag_event->event_id = WIFI_DIAG_MAC_FSM_EVENTID;
pwifi_diag_event->seq_num = seq_num;
pwifi_diag_event->len = sizeof(*pfsm_event_data);
pfsm_event_data = (struct wifi_diag_mac_fsm_event_t *)
pwifi_diag_event->event_data;
pfsm_event_data->fsm = eventtype;
if (vif->diag.diag_event_init) {
skb_queue_tail(&diag_events, skb);
schedule_work(&wifi_diag_event_work);
}
}
void
wifi_diag_send_pwrsave_event(struct ath6kl_vif *vif,
enum wifi_diag_pwrsave_t pwrsave, u32 seq_num)
{
struct wifi_diag_event_t *pwifi_diag_pwrsave_event;
struct wifi_diag_pwrsave_event_t *ppwrsave_event_data;
struct sk_buff *skb;
u32 size;
if (!diag_local_test) {
if (!(vif->diag.cfg_mask & WIFI_DIAG_PWR_SAVE_EVENTENABLE)
|| diag_evt_callback.diag_event_callback == NULL)
return;
}
size = sizeof(*pwifi_diag_pwrsave_event) + sizeof(*ppwrsave_event_data);
skb = ath6kl_wmi_get_new_buf(size);
if (!skb)
return;
pwifi_diag_pwrsave_event = (struct wifi_diag_event_t *) skb->data;
pwifi_diag_pwrsave_event->event_id = WIFI_DIAG_PWR_SAVE_EVENTID;
pwifi_diag_pwrsave_event->seq_num = seq_num;
pwifi_diag_pwrsave_event->len = sizeof(*ppwrsave_event_data);
ppwrsave_event_data = (struct wifi_diag_pwrsave_event_t *)
pwifi_diag_pwrsave_event->event_data;
ppwrsave_event_data->pwrsave = pwrsave;
if (vif->diag.diag_event_init) {
skb_queue_tail(&diag_events, skb);
schedule_work(&wifi_diag_event_work);
}
}
int
ath6kl_wmi_stat_rx_rate_event(struct ath6kl_vif *vif,
struct wmi *wmi, u8 *datap, int len, u32 seq_num)
{
struct wifi_diag_event_t *pwifi_diag_rxstat_event;
struct wifi_diag_rx_stat_event_t *prx_stat_event_data;
struct sk_buff *skb;
u32 size, i;
u32 rx_rate_pkt[44];
memcpy(&rx_rate_pkt[0], datap, sizeof(u32)*44);
if (!diag_local_test) {
if (!(vif->diag.cfg_mask & WIFI_DIAG_RX_STAT_EVENTENABLE)
|| diag_evt_callback.diag_event_callback == NULL)
return -EINVAL;
}
printk(KERN_INFO "ath6kl_wmi_stat_rx_rate_event\n");
size = sizeof(*pwifi_diag_rxstat_event) + sizeof(*prx_stat_event_data);
skb = ath6kl_wmi_get_new_buf(size);
if (!skb)
return -ENOMEM;
pwifi_diag_rxstat_event = (struct wifi_diag_event_t *) skb->data;
pwifi_diag_rxstat_event->event_id = WIFI_DIAG_RX_STAT_EVENTID;
pwifi_diag_rxstat_event->seq_num = seq_num;
pwifi_diag_rxstat_event->len = sizeof(*prx_stat_event_data);
prx_stat_event_data = (struct wifi_diag_rx_stat_event_t *)
pwifi_diag_rxstat_event->event_data;
prx_stat_event_data->rx_pkt = vif->target_stats.rx_pkt;
prx_stat_event_data->rx_ucast_pkt = vif->target_stats.rx_ucast_pkt;
prx_stat_event_data->rx_dupl_frame = vif->target_stats.rx_dupl_frame;
for (i = 0; i < 44; i++)
prx_stat_event_data->rx_rate_pkt[i] = rx_rate_pkt[i];
if (vif->diag.diag_event_init) {
skb_queue_tail(&diag_events, skb);
schedule_work(&wifi_diag_event_work);
}
return 0;
}
int
ath6kl_wmi_stat_tx_rate_event(struct ath6kl_vif *vif,
struct wmi *wmi, u8 *datap, int len, u32 seq_num)
{
struct wifi_diag_event_t *pwifi_diag_txstat_event;
struct wifi_diag_tx_stat_event_t *ptx_stat_event_data;
struct sk_buff *skb;
u32 size, i;
u32 tx_rate_pkt[44];
memcpy(&tx_rate_pkt[0], datap, sizeof(u32)*44);
if (!diag_local_test) {
if (!(vif->diag.cfg_mask & WIFI_DIAG_TX_STAT_EVENTENABLE)
|| diag_evt_callback.diag_event_callback == NULL)
return -EINVAL;
}
printk(KERN_INFO "ath6kl_wmi_stat_tx_rate_event\n");
size = sizeof(*pwifi_diag_txstat_event) + sizeof(*ptx_stat_event_data);
skb = ath6kl_wmi_get_new_buf(size);
if (!skb)
return -ENOMEM;
pwifi_diag_txstat_event = (struct wifi_diag_event_t *) skb->data;
pwifi_diag_txstat_event->event_id = WIFI_DIAG_TX_STAT_EVENTID;
pwifi_diag_txstat_event->seq_num = seq_num;
pwifi_diag_txstat_event->len = sizeof(*ptx_stat_event_data);
ptx_stat_event_data = (struct wifi_diag_tx_stat_event_t *)
pwifi_diag_txstat_event->event_data;
ptx_stat_event_data->tx_pkt = vif->target_stats.tx_pkt;
ptx_stat_event_data->tx_ucast_pkt = vif->target_stats.tx_ucast_pkt;
ptx_stat_event_data->tx_retry_cnt = vif->target_stats.tx_retry_cnt;
ptx_stat_event_data->tx_fail_cnt = vif->target_stats.tx_fail_cnt;
for (i = 0; i < 44; i++)
ptx_stat_event_data->tx_rate_pkt[i] = tx_rate_pkt[i];
if (vif->diag.diag_event_init) {
skb_queue_tail(&diag_events, skb);
schedule_work(&wifi_diag_event_work);
}
return 0;
}
int
ath6kl_wmi_interference_event(struct ath6kl_vif *vif,
struct wmi *wmi, u8 *datap, int len, u32 seq_num)
{
struct wifi_diag_event_t *pwifi_diag_interference_event;
struct wifi_diag_interference_event_t *pinterference_event_data;
struct sk_buff *skb;
u32 size, rx_clear_cnt;
printk(KERN_INFO "ath6kl_wmi_interference_event\n");
if (!diag_local_test) {
if (!(vif->diag.cfg_mask & WIFI_DIAG_INTERFERENCE_EVENTENABLE)
|| diag_evt_callback.diag_event_callback == NULL)
return -EINVAL;
}
size = sizeof(*pwifi_diag_interference_event) +
sizeof(*pinterference_event_data);
skb = ath6kl_wmi_get_new_buf(size);
if (!skb)
return -ENOMEM;
pwifi_diag_interference_event = (struct wifi_diag_event_t *) skb->data;
pwifi_diag_interference_event->event_id =
WIFI_DIAG_INTERFERENCE_EVENTID;
pwifi_diag_interference_event->seq_num = seq_num;
pwifi_diag_interference_event->len = sizeof(*pinterference_event_data);
pinterference_event_data = (struct wifi_diag_interference_event_t *)
pwifi_diag_interference_event->event_data;
rx_clear_cnt = *((u32 *)datap);
if (rx_clear_cnt >= vif->diag.pre_rx_clear_cnt)
pinterference_event_data->rx_clear_cnt =
rx_clear_cnt - vif->diag.pre_rx_clear_cnt;
else
pinterference_event_data->rx_clear_cnt =
0xFFFFFFFF - (vif->diag.pre_rx_clear_cnt - rx_clear_cnt);
vif->diag.pre_rx_clear_cnt = rx_clear_cnt;
if (vif->diag.diag_event_init) {
skb_queue_tail(&diag_events, skb);
schedule_work(&wifi_diag_event_work);
}
return 0;
}
int
ath6kl_wmi_rxtime_event(struct ath6kl_vif *vif,
struct wmi *wmi, u8 *datap, int len, u32 seq_num)
{
struct wifi_diag_event_t *pwifi_diag_rxtime_event;
struct wifi_diag_rxtime_event_t *prxtime_event_data;
struct sk_buff *skb;
u32 size, rx_frame_cnt;
printk(KERN_INFO KERN_INFO KERN_INFO "ath6kl_wmi_rxtime_event\n");
if (!diag_local_test) {
if (!(vif->diag.cfg_mask & WIFI_DIAG_RX_TIME_EVENTENABLE)
|| diag_evt_callback.diag_event_callback == NULL)
return -EINVAL;
}
size = sizeof(*pwifi_diag_rxtime_event) + sizeof(*prxtime_event_data);
skb = ath6kl_wmi_get_new_buf(size);
if (!skb)
return -ENOMEM;
pwifi_diag_rxtime_event = (struct wifi_diag_event_t *) skb->data;
pwifi_diag_rxtime_event->event_id = WIFI_DIAG_RX_TIME_EVENTID;
pwifi_diag_rxtime_event->seq_num = seq_num;
pwifi_diag_rxtime_event->len = sizeof(*prxtime_event_data);
prxtime_event_data = (struct wifi_diag_rxtime_event_t *)
pwifi_diag_rxtime_event->event_data;
rx_frame_cnt = *((u32 *)datap);
if (rx_frame_cnt >= vif->diag.pre_rx_frame_cnt)
prxtime_event_data->rx_frame_cnt =
rx_frame_cnt - vif->diag.pre_rx_frame_cnt;
else
prxtime_event_data->rx_frame_cnt =
0xFFFFFFFF - (vif->diag.pre_rx_frame_cnt - rx_frame_cnt);
vif->diag.pre_rx_frame_cnt = rx_frame_cnt;
if (vif->diag.diag_event_init) {
skb_queue_tail(&diag_events, skb);
schedule_work(&wifi_diag_event_work);
}
return 0;
}
void
wifi_diag_tx_stat_timer_handler(unsigned long ptr)
{
struct ath6kl_vif *vif = (struct ath6kl_vif *)ptr;
struct sk_buff *skb;
ath6kl_wmi_get_stats_cmd(globalwmi, 0);
skb = ath6kl_wmi_get_new_buf(sizeof(struct wmid_cmd_hdr));
if (skb)
ath6kl_wmi_cmd_send_diag(globalwmi, skb,
WMID_STAT_TX_RATE_CMDID,
NO_SYNC_WMIFLAG);
mod_timer(&vif->diag.tx_stat_timer,
jiffies + msecs_to_jiffies(vif->diag.tx_timer_val));
}
void
wifi_diag_rx_stat_timer_handler(unsigned long ptr)
{
struct ath6kl_vif *vif = (struct ath6kl_vif *)ptr;
struct sk_buff *skb;
ath6kl_wmi_get_stats_cmd(globalwmi, 0);
skb = ath6kl_wmi_get_new_buf(sizeof(struct wmid_cmd_hdr));
if (skb)
ath6kl_wmi_cmd_send_diag(globalwmi, skb,
WMID_STAT_RX_RATE_CMDID,
NO_SYNC_WMIFLAG);
mod_timer(&vif->diag.rx_stat_timer,
jiffies + msecs_to_jiffies(vif->diag.rx_timer_val));
}
void
wifi_diag_interference_timer_handler(unsigned long ptr)
{
struct ath6kl_vif *vif = (struct ath6kl_vif *)ptr;
ath6kl_wmi_interference_cmd(globalwmi);
mod_timer(&vif->diag.interference_timer,
jiffies + msecs_to_jiffies(1000));
return;
}
void
wifi_diag_rxtime_timer_handler(unsigned long ptr)
{
struct ath6kl_vif *vif = (struct ath6kl_vif *)ptr;
ath6kl_wmi_rxtime_cmd(globalwmi);
mod_timer(&vif->diag.rxtime_timer, jiffies + msecs_to_jiffies(1000));
return;
}
void
wifi_diag_timer_destroy(struct ath6kl_vif *vif)
{
del_timer(&vif->diag.tx_stat_timer);
del_timer(&vif->diag.rx_stat_timer);
del_timer(&vif->diag.interference_timer);
del_timer(&vif->diag.rxtime_timer);
if (vif->diag.diag_event_init) {
skb_queue_purge(&diag_events);
vif->diag.diag_event_init = false;
}
}
void
wifi_diag_init(void)
{
struct ath6kl_vif *vif = ath6kl_get_vif_by_index(
globalwmi->parent_dev, 0);
if (vif == NULL)
return;
skb_queue_head_init(&diag_events);
vif->diag.diag_event_init = true;
if (diag_local_test & WIFI_DIAG_MAC_FSM_EVENTENABLE)
ath6kl_wmi_fsm_cmd(globalwmi, true);
if (diag_local_test & WIFI_DIAG_PWR_SAVE_EVENTENABLE)
ath6kl_wmi_pwrsave_cmd(globalwmi, true);
if (diag_local_test & WIFI_DIAG_INTERFERENCE_EVENTENABLE) {
del_timer(&vif->diag.interference_timer);
init_timer(&vif->diag.interference_timer);
setup_timer(&vif->diag.interference_timer,
wifi_diag_interference_timer_handler,
(unsigned long) vif);
mod_timer(&vif->diag.interference_timer,
jiffies + msecs_to_jiffies(1000));
}
if (diag_local_test & WIFI_DIAG_RX_TIME_EVENTENABLE) {
del_timer(&vif->diag.rxtime_timer);
init_timer(&vif->diag.rxtime_timer);
setup_timer(&vif->diag.rxtime_timer,
wifi_diag_rxtime_timer_handler, (unsigned long) vif);
mod_timer(&vif->diag.rxtime_timer,
jiffies + msecs_to_jiffies(1000));
}
if (diag_local_test & WIFI_DIAG_TX_STAT_EVENTENABLE) {
del_timer(&vif->diag.tx_stat_timer);
init_timer(&vif->diag.tx_stat_timer);
setup_timer(&vif->diag.tx_stat_timer,
wifi_diag_tx_stat_timer_handler, (unsigned long) vif);
vif->diag.tx_timer_val = 2000;
mod_timer(&vif->diag.tx_stat_timer,
jiffies + msecs_to_jiffies(vif->diag.tx_timer_val));
}
if (diag_local_test & WIFI_DIAG_RX_STAT_EVENTENABLE) {
del_timer(&vif->diag.rx_stat_timer);
init_timer(&vif->diag.rx_stat_timer);
setup_timer(&vif->diag.rx_stat_timer,
wifi_diag_rx_stat_timer_handler, (unsigned long) vif);
vif->diag.rx_timer_val = 2000;
mod_timer(&vif->diag.rx_stat_timer,
jiffies + msecs_to_jiffies(vif->diag.rx_timer_val));
}
if ((diag_local_test & WIFI_DIAG_MAC_TX_FRAME_EVENTENABLE) ||
(diag_local_test & WIFI_DIAG_MAC_RX_FRAME_EVENTENABLE)) {
if ((diag_local_test & 0x00000200) &&
(diag_local_test & 0xFFFF0000)) {
ath6kl_wmi_macfilter_cmd(globalwmi,
WMI_PKTLOG_EVENT_TX | WMI_PKTLOG_EVENT_RX,
((diag_local_test & 0xFFFF0000)>>16) &
WIFI_DIAG_MACFILTER_LOW_MASK,
WIFI_DIAG_MACFILTER_DISABLEALL &
WIFI_DIAG_MACFILTER_HIGH_MASK);
} else if ((diag_local_test & 0x00000800) &&
(diag_local_test & 0xFFFF0000)) {
ath6kl_wmi_macfilter_cmd(globalwmi,
WMI_PKTLOG_EVENT_TX | WMI_PKTLOG_EVENT_RX,
WIFI_DIAG_MACFILTER_DISABLEALL &
WIFI_DIAG_MACFILTER_LOW_MASK,
((diag_local_test & 0xFFFF0000)>>16) &
WIFI_DIAG_MACFILTER_HIGH_MASK);
} else {
ath6kl_wmi_macfilter_cmd(globalwmi,
WMI_PKTLOG_EVENT_TX | WMI_PKTLOG_EVENT_RX,
WIFI_DIAG_MACFILTER_ENABLEALL &
WIFI_DIAG_MACFILTER_LOW_MASK,
WIFI_DIAG_MACFILTER_ENABLEALL &
WIFI_DIAG_MACFILTER_HIGH_MASK);
}
{
struct wmi_enable_pktlog_cmd cmd;
cmd.option = WMI_PKTLOG_OPTION_LOG_DIAGNOSTIC;
cmd.evlist = WMI_PKTLOG_EVENT_TX | WMI_PKTLOG_EVENT_RX;
cmd.trigger_interval = 0;
cmd.trigger_tail_count = 0;
cmd.trigger_thresh = 0;
cmd.buffer_size = 1500;
ath6kl_wmi_pktlog_enable_cmd(globalwmi, &cmd);
}
}
}
#endif /* ATH6KL_DIAGNOSTIC */