M7350/external/compat-wireless/drivers/net/wireless/ath/ath6kl/wmiconfig.c
2024-09-09 08:52:07 +00:00

538 lines
18 KiB
C

/*
* Copyright (c) 2010-2011 Atheros Communications Inc.
* Copyright (c) 2011 Qualcomm Atheros, 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/printk.h>
#include <asm/unaligned.h>
#include "core.h"
#include "cfg80211.h"
#include "debug.h"
#include "hif-ops.h"
#include "testmode.h"
#include "wmiconfig.h"
#include "wmi.h"
#include <net/netlink.h>
enum ath6kl_tm_attr {
__ATH6KL_TM_ATTR_INVALID = 0,
ATH6KL_TM_ATTR_CMD = 1,
ATH6KL_TM_ATTR_DATA = 2,
/* keep last */
__ATH6KL_TM_ATTR_AFTER_LAST,
ATH6KL_TM_ATTR_MAX = __ATH6KL_TM_ATTR_AFTER_LAST - 1,
};
enum ath6kl_tm_cmd {
ATH6KL_TM_CMD_TCMD = 0,
ATH6KL_TM_CMD_RX_REPORT = 1, /* not used anymore */
ATH6KL_TM_CMD_WMI_CMD = 0xF000,
};
#define AP_ACS_NONE AP_ACS_POLICY_MAX
#define ATH6KL_WWAN_FDD 0x0F
#define ATH6KL_WWAN_TDD 0xF0
#define ATH6KL_WWAN_BAND 0xFF
struct app_lte_coex_wwan_data_t {
uint32_t cmd;
uint32_t band_info_valid;
uint32_t ul_freq;
uint32_t ul_bw;
uint32_t dl_freq;
uint32_t dl_bw;
uint32_t tdd_info_valid;
uint32_t fr_offset;
uint32_t tdd_cfg;
uint32_t sub_fr_cfg;
uint32_t ul_cfg;
uint32_t dl_cfg;
uint32_t off_period_valid;
uint32_t off_period;
};
#define CHAN1 BIT(0)
#define CHAN2 BIT(1)
#define CHAN3 BIT(2)
#define CHAN4 BIT(3)
#define CHAN5 BIT(4)
#define CHAN6 BIT(5)
#define CHAN7 BIT(6)
#define CHAN8 BIT(7)
#define CHAN9 BIT(8)
#define CHAN10 BIT(9)
#define CHAN11 BIT(10)
#define CHAN12 BIT(11)
#define CHAN13 BIT(12)
#define LTE_COEX_REF_TDD_ROWS 4
#define LTE_COEX_REF_FDD_ROWS 20
struct _lte_coex_chk {
int wwan_min_freq;
int wwan_max_freq;
int wwan_bw;
u32 margin_0_acs_chan_mask; /* margin 0 4db - 8db */
u32 margin_1_acs_chan_mask; /* margin 1 < 4db */
u32 margin_2_acs_chan_mask; /* margin 2 > 8db */
};
struct _lte_coex_chk lte_coex_tdd_lookup_table[LTE_COEX_REF_TDD_ROWS] = {
/* wwan_min_freq wwan_max_freq wwan_bw
* margin_0_chan_mask
* margin_1_chan_mask
* margin_2_chan_mask
*/
/*
* For TDD bands margin value is ignored, so all the margins should have the
* same channel lists
*
* */
/* band 40 tdd */
{2300, 2350, 0,
(CHAN5 | CHAN6 | CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13),
(CHAN5 | CHAN6 | CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13),
(CHAN5 | CHAN6 | CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13)},
{2350, 2370, 0,
(CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13),
(CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13),
(CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13)},
{2370, 2401, 0,
(CHAN10 | CHAN11 | CHAN12 | CHAN13),
(CHAN10 | CHAN11 | CHAN12 | CHAN13),
(CHAN10 | CHAN11 | CHAN12 | CHAN13)},
/* band 41 tdd */
{2496, 2691, 0,
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6 | CHAN7 | CHAN8 | CHAN9),
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6 | CHAN7 | CHAN8 | CHAN9),
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6 | CHAN7 | CHAN8 | CHAN9)}
};
/* Coex mode same for FDD B20 and B7 */
struct _lte_coex_chk lte_coex_fdd_lookup_table[LTE_COEX_REF_FDD_ROWS] = {
/* band 7 10 MHz */
{2500, 2525, 10,
/* margin 0 4db - 8db channel list */
(CHAN2 | CHAN3 | CHAN4| CHAN5 | CHAN6 | CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13),
/* margin 1 < 4db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4| CHAN5 | CHAN6 | CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13),
/* margin 2 > 8db channel list*/
(CHAN4 | CHAN5 | CHAN6 | CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13)},
{2525, 2552, 10,
(CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 0 4db - 8db channel list */
(CHAN6 | CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 1 < 4db channel list */
(CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13)}, /* margin 2 > 8db channel list*/
{2552, 2562, 10,
(CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 0 4db - 8db channel list */
(CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 1 < 4db channel list */
(CHAN11 | CHAN12 | CHAN13)}, /* margin 2 > 8db channel list*/
{2562, 2568, 10,
(CHAN1 | CHAN2 | CHAN3 | CHAN4| CHAN5 | CHAN11 | CHAN12 | CHAN13), /* margin 0 4db - 8db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4| CHAN5 | CHAN6 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 1 < 4db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN13)}, /* margin 2 > 8db channel list*/
{2568, 2570, 10,
(CHAN1 | CHAN2 | CHAN3 | CHAN4| CHAN5 | CHAN6), /* margin 0 4db - 8db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4| CHAN5 | CHAN6 | CHAN7), /* margin 1 < 4db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4)}, /* margin 2 > 8db channel list*/
/* band 7 20 MHz */
{2500, 2525, 20,
(CHAN4 | CHAN5 | CHAN6 | CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 0 4db - 8db channel list */
(CHAN3 | CHAN4 | CHAN5 | CHAN6 | CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 1 < 4db channel list */
(CHAN6 | CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13)}, /* margin 2 > 8db channel list */
{2525, 2552, 20,
(CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13),/* margin 0 4db - 8db channel list */
(CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 1 < 4db channel list */
(CHAN11 | CHAN12 | CHAN13)}, /* margin 2 > 8db channel list */
{2552, 2562, 20,
(CHAN11 | CHAN12 | CHAN13), /* margin 0 4db - 8db channel list */
(CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 1 < 4db channel list */
(CHAN13)}, /* margin 2 > 8db channel list */
{2562, 2568, 20,
(CHAN1 | CHAN2 | CHAN3 | CHAN13), /* margin 0 4db - 8db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN12 | CHAN13), /* margin 1 < 4db channel list */
(CHAN1 | CHAN13)}, /* margin 2 > 8db channel list */
{2568, 2570, 20,
(CHAN1 | CHAN2 | CHAN3 | CHAN4), /* margin 0 4db - 8db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5), /* margin 1 < 4db channel list */
(CHAN1 | CHAN2)}, /* margin 2 > 8db channel list */
/* band 20 10 MHz */
{832, 837, 10,
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6), /* margin 0 4db - 8db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6 | CHAN7 | CHAN10 | CHAN13), /* margin 1 < 4db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4)}, /* margin 2 > 8db channel list */
{837, 844, 10,
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6 | CHAN7 | CHAN8 | CHAN9), /* margin 0 4db - 8db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6 | CHAN7 | CHAN8 | CHAN9 | CHAN10), /* margin 1 < 4db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6 | CHAN7)}, /* margin 2 > 8db channel list */
{845, 852, 10,
(CHAN6 | CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 0 4db - 8db channel list */
(CHAN6 | CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 1 < 4db channel list */
(CHAN6 | CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12)}, /* margin 2 > 8db channel list */
{852, 857, 10,
(CHAN1 | CHAN2 | CHAN3 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 0 4db - 8db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 1 < 4db channel list */
(CHAN1 | CHAN2 | CHAN11 | CHAN12 | CHAN13)}, /* margin 2 > 8db channel list */
{857, 862, 10,
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6 | CHAN7 | CHAN12 | CHAN13), /* margin 0 4db - 8db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6 | CHAN7 | CHAN12 | CHAN13), /* margin 1 < 4db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6 | CHAN7 | CHAN12 | CHAN13)}, /* margin 2 > 8db channel list */
/* band 20 20 MHz */
{832, 837, 20,
(CHAN1 | CHAN2 | CHAN3 | CHAN4), /* margin 0 4db - 8db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5), /* margin 1 < 4db channel list */
(CHAN1 | CHAN2)}, /* margin 2 > 8db channel list */
{837, 844, 20,
(CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6 | CHAN7), /* margin 0 4db - 8db channel list */
(CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6 | CHAN7 | CHAN8), /* margin 1 < 4db channel list */
(CHAN2 | CHAN3 | CHAN4 | CHAN5)}, /* margin 2 > 8db channel list */
{845, 852, 20,
(CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12), /* margin 0 4db - 8db channel list */
(CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 1 < 4db channel list */
(CHAN7 | CHAN8 | CHAN9 | CHAN10)}, /* margin 2 > 8db channel list */
{852, 857, 20,
(CHAN1 | CHAN2 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 0 4db - 8db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN7 | CHAN8 | CHAN9 | CHAN10 | CHAN11 | CHAN12 | CHAN13), /* margin 1 < 4db channel list */
(CHAN1 | CHAN2 | CHAN10 | CHAN11 | CHAN12 | CHAN13)}, /* margin 2 > 8db channel list */
{857, 862, 20,
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6), /* margin 0 4db - 8db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6), /* margin 1 < 4db channel list */
(CHAN1 | CHAN2 | CHAN3 | CHAN4 | CHAN5 | CHAN6)}, /* margin 2 > 8db channel list */
/* No lte_coex needed for TDD B38
*{ATH6KL_WWAN_FREQ_2570, ATH6KL_WWAN_FREQ_2620, CH1, CH14,
* LTE_COEX_MODE_DISABLED,
* LTE_COEX_MODE_DISABLED, AP_ACS_NONE,
* ATH6KL_WWAN_B38},
*/
};
struct sk_buff *ath6kl_wmi_get_buf(u32 size)
{
struct sk_buff *skb;
skb = ath6kl_buf_alloc(size);
if (!skb)
return NULL;
skb_put(skb, size);
if (size)
memset(skb->data, 0, size);
return skb;
}
static u32 ath6kl_get_lte_acs_chan_mask(struct ath6kl *ar, u8 index,
struct _lte_coex_chk lte_coex_chk[])
{
if (ar->lte_margin == 0)
return lte_coex_chk[index].margin_0_acs_chan_mask;
else if (ar->lte_margin == 1)
return lte_coex_chk[index].margin_1_acs_chan_mask;
else if (ar->lte_margin == 2)
return lte_coex_chk[index].margin_2_acs_chan_mask;
return 0;
}
static void ath6kl_lte_coex_config_acs_mask(struct ath6kl_vif *vif,
uint32_t ap_oper_chan_mask, uint8_t index,
struct _lte_coex_chk lte_coex_chk[])
{
struct ath6kl *ar = vif->ar;
uint8_t vif_idx = vif->fw_vif_idx;
if (!(ar->lte_coex->acs_chan_mask & ap_oper_chan_mask)) {
/* AP up */
if (ar->acs_in_prog) {
vif->ap_hold_conn = 1;
mod_timer(&vif->ap_restart_timer, jiffies +
msecs_to_jiffies(1 * AP_RESTART_TIMER_INVAL));
} else {
ar->acs_in_prog = 1;
ath6kl_wmi_ap_profile_commit(ar->wmi, vif_idx,
&vif->profile);
}
}
}
static void ath6kl_lte_coex_set_ap_mode(struct ath6kl *ar, uint8_t index,
struct _lte_coex_chk lte_coex_chk[])
{
struct ath6kl_vif *vif;
uint32_t ap_oper_chan_mask;
uint8_t vif_idx = 0;
spin_lock_bh(&ar->list_lock);
list_for_each_entry(vif, &ar->vif_list, list) {
ar->lte_coex->acs_chan_mask =
ath6kl_get_lte_acs_chan_mask(ar, index,
lte_coex_chk);;
if (vif->nw_type != AP_NETWORK ||
!test_bit(CONNECTED, &vif->flags) )
continue;
vif_idx = vif->fw_vif_idx;
ap_oper_chan_mask = ar->lte_coex->dev_ctx[vif_idx].ap_oper_chan_mask;
/* select wlan band */
if (ap_oper_chan_mask && !ar->sta_bh_override &&
vif->phy_mode != WMI_11A_MODE) {
ath6kl_lte_coex_config_acs_mask(vif, ap_oper_chan_mask, index,
lte_coex_chk);
}
}
spin_unlock_bh(&ar->list_lock);
}
static void ath6kl_setup_wlan_ap_lte_coex_mode(struct ath6kl *ar,
int table_look_up_entries,
struct _lte_coex_chk lte_coex_chk[])
{
int i;
if (ar->lte_coex->wwan_operational == 0)
return ;
ar->lte_coex->acs_chan_mask = AP_ACS_NONE;
/* Select wwan band */
for (i = 0; i < table_look_up_entries; i++) {
if (ar->lte_coex->wwan_freq >= lte_coex_chk[i].wwan_min_freq &&
ar->lte_coex->wwan_freq < lte_coex_chk[i].wwan_max_freq) {
if (ar->lte_coex->wwan_band == ATH6KL_WWAN_FDD &&
(ar->lte_coex->wwan_bw != lte_coex_chk[i].wwan_bw))
continue;
ath6kl_lte_coex_set_ap_mode(ar, i, lte_coex_chk);
break;
}
}
}
void ath6kl_lte_coex_update_wwan_data(struct ath6kl *ar, void *wmi_buf)
{
int table_look_up_entries = 0;
struct app_lte_coex_wwan_data_t *wwan =
(struct app_lte_coex_wwan_data_t *)wmi_buf;
ath6kl_info("LTE_COEX: QMI LTE band info:%d %d %d",
wwan->band_info_valid, wwan->ul_freq, wwan->dl_freq);
ath6kl_info("LTE_COEX: QMI TDD CFG:%d %d",
wwan->tdd_info_valid, wwan->tdd_cfg);
ath6kl_info("LTE_COEX: QMI off period:%d %d",
wwan->off_period_valid, wwan->off_period);
if (!(wwan->band_info_valid == 1 || wwan->tdd_info_valid == 1 ||
wwan->off_period_valid == 1))
return;
ar->lte_coex->wwan_operational = 1;
if (wwan->band_info_valid == 1) {
ar->lte_coex->wwan_freq = wwan->ul_freq;
ar->lte_coex->wwan_bw = wwan->ul_bw;
if (wwan->ul_freq == 0) {
if (wwan->dl_freq == 0) {
ath6kl_dbg(ATH6KL_DBG_LTE_COEX,
"LTE_COEX: LTE deactivated. Disable lte_coex");
ar->lte_coex->wwan_state =
LTE_COEX_WWAN_STATE_DEACTIVATED;
ar->lte_coex->wwan_band = 0;
} else {
ath6kl_dbg(ATH6KL_DBG_LTE_COEX,
"LTE_COEX: LTE Idle Rx");
ar->lte_coex->wwan_freq = wwan->dl_freq;
ar->lte_coex->wwan_state =
LTE_COEX_WWAN_STATE_IDLE;
ar->lte_coex->wwan_band = ATH6KL_WWAN_BAND;
}
} else {
ath6kl_dbg(ATH6KL_DBG_LTE_COEX, "LTE_COEX: LTE Active");
if (wwan->ul_freq == wwan->dl_freq) {
ar->lte_coex->wwan_band = ATH6KL_WWAN_TDD;
table_look_up_entries = LTE_COEX_REF_TDD_ROWS;
} else {
ar->lte_coex->wwan_band = ATH6KL_WWAN_FDD;
table_look_up_entries = LTE_COEX_REF_FDD_ROWS;
}
ar->lte_coex->wwan_state =
LTE_COEX_WWAN_STATE_CONNECTED;
}
}
if (ar->lte_coex->wwan_state != LTE_COEX_WWAN_STATE_IDLE) {
ath6kl_info("wwan state=%d, wwan_band=%d wwan_freq=%d\n",
ar->lte_coex->wwan_state,
ar->lte_coex->wwan_band,
ar->lte_coex->wwan_freq);
ath6kl_setup_wlan_ap_lte_coex_mode(ar, table_look_up_entries,
(ar->lte_coex->wwan_band & ATH6KL_WWAN_TDD) ?
lte_coex_tdd_lookup_table :
lte_coex_fdd_lookup_table);
}
}
u32 ath6kl_set_ap_operating_chan_mask(uint32_t chan)
{
u32 chan_mask = 0, bit = 0;
bit = (chan - 2412) / 5;
chan_mask = BIT(bit);
if (!chan || chan_mask > 0x1fff)
chan_mask = 0;
return chan_mask;
}
void ath6kl_lte_coex_update_wlan_data(struct ath6kl_vif *vif, uint32_t chan)
{
struct ath6kl *ar = vif->ar;
int table_look_up_entries = (ar->lte_coex->wwan_band & ATH6KL_WWAN_TDD) ?
LTE_COEX_REF_TDD_ROWS :
LTE_COEX_REF_FDD_ROWS;
if (vif->nw_type == AP_NETWORK) {
if (chan && vif->phy_mode != WMI_11A_MODE) {
ar->lte_coex->dev_ctx[vif->fw_vif_idx].ap_oper_chan_mask =
ath6kl_set_ap_operating_chan_mask(chan);
ath6kl_setup_wlan_ap_lte_coex_mode(ar,
table_look_up_entries,
(ar->lte_coex->wwan_band & ATH6KL_WWAN_TDD) ?
lte_coex_tdd_lookup_table :
lte_coex_fdd_lookup_table);
} else
ar->lte_coex->dev_ctx[vif->fw_vif_idx].ap_oper_chan_mask = 0;
}
}
bool ath6kl_check_lte_coex_acs(struct ath6kl *ar, uint16_t *ap_acs_ch,
struct ath6kl_vif *cur_vif)
{
struct ath6kl_vif *tmp_vif;
bool ret = false;
if (ar->lte_coex && ar->lte_coex->acs_chan_mask != AP_ACS_NONE) {
list_for_each_entry(tmp_vif, &ar->vif_list, list) {
if (tmp_vif->nw_type == AP_NETWORK) {
if (test_bit(CONNECTED, &tmp_vif->flags)) {
if (tmp_vif->fw_vif_idx != cur_vif->fw_vif_idx &&
(tmp_vif->phy_mode != WMI_11A_MODE)) {
if (ar->lte_coex->acs_chan_mask &
ar->lte_coex->dev_ctx[tmp_vif->fw_vif_idx].ap_oper_chan_mask)
*ap_acs_ch =
tmp_vif->bss_ch;
}
}
}
}
if (!*ap_acs_ch) {
*ap_acs_ch = cpu_to_le16(AP_ACS_USER_DEFINED);
cur_vif->acs_chan_mask = ar->lte_coex->acs_chan_mask;
}
ar->lte_coex->dev_ctx[cur_vif->fw_vif_idx].ap_oper_chan_mask = 0;
ret = true;
}
return ret;
}
int ath6kl_lte_coex_init(struct ath6kl *ar)
{
ath6kl_dbg(ATH6KL_DBG_LTE_COEX, "LTE_COEX: WWAN Coex Module Init");
ar->lte_coex = (struct ath6kl_lte_coex_priv *)
kzalloc(sizeof(struct ath6kl_lte_coex_priv), GFP_KERNEL);
if (!ar->lte_coex)
return -ENOMEM;
ar->lte_coex->ar = ar;
ar->lte_coex->acs_chan_mask = AP_ACS_NONE;
return 0;
}
void ath6kl_lte_coex_deinit(struct ath6kl *ar)
{
ath6kl_dbg(ATH6KL_DBG_LTE_COEX, "LTE_COEX: WWAN Coex Module Deinit");
kfree(ar->lte_coex);
ar->lte_coex = NULL;
}
void ath6kl_tm_rx_wmi_event(struct ath6kl *ar, void *buf, size_t buf_len)
{
struct sk_buff *skb;
if (!buf || buf_len == 0)
return;
skb = cfg80211_testmode_alloc_event_skb(ar->wiphy, buf_len, GFP_KERNEL);
if (!skb) {
ath6kl_warn("failed to allocate testmode rx skb!\n");
return;
}
NLA_PUT_U32(skb, ATH6KL_TM_ATTR_CMD, ATH6KL_TM_CMD_WMI_CMD);
NLA_PUT(skb, ATH6KL_TM_ATTR_DATA, buf_len, buf);
cfg80211_testmode_event(skb, GFP_KERNEL);
return;
nla_put_failure:
kfree_skb(skb);
ath6kl_warn("nla_put failed on testmode rx skb!\n");
}
void ath6kl_wmicfg_send_stats(struct ath6kl_vif *vif,
struct target_stats *stats)
{
u32 *buff = kzalloc(sizeof(*stats) + 4, GFP_KERNEL);
if (buff == NULL)
return;
buff[0] = WMI_REPORT_STATISTICS_EVENTID;
memcpy(buff+1, stats, sizeof(struct target_stats));
ath6kl_tm_rx_wmi_event(vif->ar->wmi->parent_dev, buff,
sizeof(struct target_stats)+4);
kfree(buff);
}