Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for 4.18. Major changes: ath10k * add memory dump support for QCA9888 and QCA99X0 * add support to configure channel dwell time * support new DFS host confirmation feature in the firmware ath * update various regulatory mappings wcn36xx * various fixes to improve reliability * add Factory Test Mode support
This commit is contained in:
commit
76606886c9
|
@ -180,14 +180,11 @@ static void ath10k_ahb_clock_disable(struct ath10k *ar)
|
|||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
|
||||
if (!IS_ERR_OR_NULL(ar_ahb->cmd_clk))
|
||||
clk_disable_unprepare(ar_ahb->cmd_clk);
|
||||
clk_disable_unprepare(ar_ahb->cmd_clk);
|
||||
|
||||
if (!IS_ERR_OR_NULL(ar_ahb->ref_clk))
|
||||
clk_disable_unprepare(ar_ahb->ref_clk);
|
||||
clk_disable_unprepare(ar_ahb->ref_clk);
|
||||
|
||||
if (!IS_ERR_OR_NULL(ar_ahb->rtc_clk))
|
||||
clk_disable_unprepare(ar_ahb->rtc_clk);
|
||||
clk_disable_unprepare(ar_ahb->rtc_clk);
|
||||
}
|
||||
|
||||
static int ath10k_ahb_rst_ctrl_init(struct ath10k *ar)
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#define WO(_f) ((_f##_OFFSET) >> 2)
|
||||
|
||||
#define ATH10K_SCAN_ID 0
|
||||
#define ATH10K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD 10 /* msec */
|
||||
#define WMI_READY_TIMEOUT (5 * HZ)
|
||||
#define ATH10K_FLUSH_TIMEOUT_HZ (5 * HZ)
|
||||
#define ATH10K_CONNECTION_LOSS_HZ (3 * HZ)
|
||||
|
@ -175,6 +176,7 @@ struct ath10k_wmi {
|
|||
struct completion service_ready;
|
||||
struct completion unified_ready;
|
||||
struct completion barrier;
|
||||
struct completion radar_confirm;
|
||||
wait_queue_head_t tx_credits_wq;
|
||||
DECLARE_BITMAP(svc_map, WMI_SERVICE_MAX);
|
||||
struct wmi_cmd_map *cmd;
|
||||
|
@ -377,6 +379,21 @@ struct ath10k_dfs_stats {
|
|||
u32 radar_detected;
|
||||
};
|
||||
|
||||
enum ath10k_radar_confirmation_state {
|
||||
ATH10K_RADAR_CONFIRMATION_IDLE = 0,
|
||||
ATH10K_RADAR_CONFIRMATION_INPROGRESS,
|
||||
ATH10K_RADAR_CONFIRMATION_STOPPED,
|
||||
};
|
||||
|
||||
struct ath10k_radar_found_info {
|
||||
u32 pri_min;
|
||||
u32 pri_max;
|
||||
u32 width_min;
|
||||
u32 width_max;
|
||||
u32 sidx_min;
|
||||
u32 sidx_max;
|
||||
};
|
||||
|
||||
#define ATH10K_MAX_NUM_PEER_IDS (1 << 11) /* htt rx_desc limit */
|
||||
|
||||
struct ath10k_peer {
|
||||
|
@ -1109,6 +1126,11 @@ struct ath10k {
|
|||
|
||||
u32 sta_tid_stats_mask;
|
||||
|
||||
/* protected by data_lock */
|
||||
enum ath10k_radar_confirmation_state radar_conf_state;
|
||||
struct ath10k_radar_found_info last_radar_info;
|
||||
struct work_struct radar_confirmation_work;
|
||||
|
||||
/* must be last */
|
||||
u8 drv_priv[0] __aligned(sizeof(void *));
|
||||
};
|
||||
|
|
|
@ -701,6 +701,89 @@ static const struct ath10k_mem_region qca988x_hw20_mem_regions[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static const struct ath10k_mem_region qca99x0_hw20_mem_regions[] = {
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_DRAM,
|
||||
.start = 0x400000,
|
||||
.len = 0x60000,
|
||||
.name = "DRAM",
|
||||
.section_table = {
|
||||
.sections = NULL,
|
||||
.size = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_REG,
|
||||
.start = 0x98000,
|
||||
.len = 0x50000,
|
||||
.name = "IRAM",
|
||||
.section_table = {
|
||||
.sections = NULL,
|
||||
.size = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_IOSRAM,
|
||||
.start = 0xC0000,
|
||||
.len = 0x40000,
|
||||
.name = "SRAM",
|
||||
.section_table = {
|
||||
.sections = NULL,
|
||||
.size = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_IOREG,
|
||||
.start = 0x30000,
|
||||
.len = 0x7000,
|
||||
.name = "APB REG 1",
|
||||
.section_table = {
|
||||
.sections = NULL,
|
||||
.size = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_IOREG,
|
||||
.start = 0x3f000,
|
||||
.len = 0x3000,
|
||||
.name = "APB REG 2",
|
||||
.section_table = {
|
||||
.sections = NULL,
|
||||
.size = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_IOREG,
|
||||
.start = 0x43000,
|
||||
.len = 0x3000,
|
||||
.name = "WIFI REG",
|
||||
.section_table = {
|
||||
.sections = NULL,
|
||||
.size = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_IOREG,
|
||||
.start = 0x4A000,
|
||||
.len = 0x5000,
|
||||
.name = "CE REG",
|
||||
.section_table = {
|
||||
.sections = NULL,
|
||||
.size = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_IOREG,
|
||||
.start = 0x80000,
|
||||
.len = 0x6000,
|
||||
.name = "SOC REG",
|
||||
.section_table = {
|
||||
.sections = NULL,
|
||||
.size = 0,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ath10k_mem_region qca9984_hw10_mem_regions[] = {
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_DRAM,
|
||||
|
@ -848,6 +931,21 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
|||
.size = ARRAY_SIZE(qca9984_hw10_mem_regions),
|
||||
},
|
||||
},
|
||||
{
|
||||
.hw_id = QCA9888_HW_2_0_DEV_VERSION,
|
||||
.region_table = {
|
||||
.regions = qca9984_hw10_mem_regions,
|
||||
.size = ARRAY_SIZE(qca9984_hw10_mem_regions),
|
||||
},
|
||||
},
|
||||
{
|
||||
.hw_id = QCA99X0_HW_2_0_DEV_VERSION,
|
||||
.region_table = {
|
||||
.regions = qca99x0_hw20_mem_regions,
|
||||
.size = ARRAY_SIZE(qca99x0_hw20_mem_regions),
|
||||
},
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar)
|
||||
|
|
|
@ -3217,6 +3217,15 @@ static void ath10k_reg_notifier(struct wiphy *wiphy,
|
|||
ar->hw->wiphy->bands[NL80211_BAND_5GHZ]);
|
||||
}
|
||||
|
||||
static void ath10k_stop_radar_confirmation(struct ath10k *ar)
|
||||
{
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->radar_conf_state = ATH10K_RADAR_CONFIRMATION_STOPPED;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
cancel_work_sync(&ar->radar_confirmation_work);
|
||||
}
|
||||
|
||||
/***************/
|
||||
/* TX handlers */
|
||||
/***************/
|
||||
|
@ -4333,6 +4342,7 @@ void ath10k_halt(struct ath10k *ar)
|
|||
|
||||
ath10k_scan_finish(ar);
|
||||
ath10k_peer_cleanup_all(ar);
|
||||
ath10k_stop_radar_confirmation(ar);
|
||||
ath10k_core_stop(ar);
|
||||
ath10k_hif_power_down(ar);
|
||||
|
||||
|
@ -4758,6 +4768,8 @@ static int ath10k_start(struct ieee80211_hw *hw)
|
|||
ath10k_spectral_start(ar);
|
||||
ath10k_thermal_set_throttling(ar);
|
||||
|
||||
ar->radar_conf_state = ATH10K_RADAR_CONFIRMATION_IDLE;
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return 0;
|
||||
|
||||
|
@ -5675,6 +5687,7 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
|
|||
struct wmi_start_scan_arg arg;
|
||||
int ret = 0;
|
||||
int i;
|
||||
u32 scan_timeout;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
|
@ -5736,6 +5749,22 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
|
|||
arg.channels[i] = req->channels[i]->center_freq;
|
||||
}
|
||||
|
||||
/* if duration is set, default dwell times will be overwritten */
|
||||
if (req->duration) {
|
||||
arg.dwell_time_active = req->duration;
|
||||
arg.dwell_time_passive = req->duration;
|
||||
arg.burst_duration_ms = req->duration;
|
||||
|
||||
scan_timeout = min_t(u32, arg.max_rest_time *
|
||||
(arg.n_channels - 1) + (req->duration +
|
||||
ATH10K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) *
|
||||
arg.n_channels, arg.max_scan_time + 200);
|
||||
|
||||
} else {
|
||||
/* Add a 200ms margin to account for event/command processing */
|
||||
scan_timeout = arg.max_scan_time + 200;
|
||||
}
|
||||
|
||||
ret = ath10k_start_scan(ar, &arg);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to start hw scan: %d\n", ret);
|
||||
|
@ -5744,10 +5773,8 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
|
|||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
/* Add a 200ms margin to account for event/command processing */
|
||||
ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
|
||||
msecs_to_jiffies(arg.max_scan_time +
|
||||
200));
|
||||
msecs_to_jiffies(scan_timeout));
|
||||
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
@ -8364,6 +8391,8 @@ int ath10k_mac_register(struct ath10k *ar)
|
|||
}
|
||||
|
||||
wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
|
||||
wiphy_ext_feature_set(ar->hw->wiphy,
|
||||
NL80211_EXT_FEATURE_SET_SCAN_DWELL);
|
||||
|
||||
/*
|
||||
* on LL hardware queues are managed entirely by the FW
|
||||
|
|
|
@ -55,6 +55,8 @@ struct wmi_ops {
|
|||
struct wmi_wow_ev_arg *arg);
|
||||
int (*pull_echo_ev)(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_echo_ev_arg *arg);
|
||||
int (*pull_dfs_status_ev)(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_dfs_status_ev_arg *arg);
|
||||
int (*pull_svc_avail)(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_svc_avail_ev_arg *arg);
|
||||
|
||||
|
@ -188,6 +190,9 @@ struct wmi_ops {
|
|||
const struct wmi_tdls_peer_update_cmd_arg *arg,
|
||||
const struct wmi_tdls_peer_capab_arg *cap,
|
||||
const struct wmi_channel_arg *chan);
|
||||
struct sk_buff *(*gen_radar_found)
|
||||
(struct ath10k *ar,
|
||||
const struct ath10k_radar_found_info *arg);
|
||||
struct sk_buff *(*gen_adaptive_qcs)(struct ath10k *ar, bool enable);
|
||||
struct sk_buff *(*gen_pdev_get_tpc_config)(struct ath10k *ar,
|
||||
u32 param);
|
||||
|
@ -395,6 +400,16 @@ ath10k_wmi_pull_echo_ev(struct ath10k *ar, struct sk_buff *skb,
|
|||
return ar->wmi.ops->pull_echo_ev(ar, skb, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_pull_dfs_status(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_dfs_status_ev_arg *arg)
|
||||
{
|
||||
if (!ar->wmi.ops->pull_dfs_status_ev)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ar->wmi.ops->pull_dfs_status_ev(ar, skb, arg);
|
||||
}
|
||||
|
||||
static inline enum wmi_txbf_conf
|
||||
ath10k_wmi_get_txbf_conf_scheme(struct ath10k *ar)
|
||||
{
|
||||
|
@ -1511,4 +1526,21 @@ ath10k_wmi_pdev_get_tpc_table_cmdid(struct ath10k *ar, u32 param)
|
|||
ar->wmi.cmd->pdev_get_tpc_table_cmdid);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_report_radar_found(struct ath10k *ar,
|
||||
const struct ath10k_radar_found_info *arg)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!ar->wmi.ops->gen_radar_found)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
skb = ar->wmi.ops->gen_radar_found(ar, arg);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
return ath10k_wmi_cmd_send(ar, skb,
|
||||
ar->wmi.cmd->radar_found_cmdid);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#define ATH10K_WMI_BARRIER_ECHO_ID 0xBA991E9
|
||||
#define ATH10K_WMI_BARRIER_TIMEOUT_HZ (3 * HZ)
|
||||
#define ATH10K_WMI_DFS_CONF_TIMEOUT_HZ (HZ / 6)
|
||||
|
||||
/* MAIN WMI cmd track */
|
||||
static struct wmi_cmd_map wmi_cmd_map = {
|
||||
|
@ -199,6 +200,7 @@ static struct wmi_cmd_map wmi_cmd_map = {
|
|||
.set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.radar_found_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
};
|
||||
|
||||
/* 10.X WMI cmd track */
|
||||
|
@ -367,6 +369,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = {
|
|||
.set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.radar_found_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
};
|
||||
|
||||
/* 10.2.4 WMI cmd track */
|
||||
|
@ -535,6 +538,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd_map = {
|
|||
.pdev_bss_chan_info_request_cmdid =
|
||||
WMI_10_2_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
|
||||
.pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.radar_found_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
};
|
||||
|
||||
/* 10.4 WMI cmd track */
|
||||
|
@ -745,6 +749,7 @@ static struct wmi_cmd_map wmi_10_4_cmd_map = {
|
|||
.tdls_set_state_cmdid = WMI_10_4_TDLS_SET_STATE_CMDID,
|
||||
.tdls_peer_update_cmdid = WMI_10_4_TDLS_PEER_UPDATE_CMDID,
|
||||
.tdls_set_offchan_mode_cmdid = WMI_10_4_TDLS_SET_OFFCHAN_MODE_CMDID,
|
||||
.radar_found_cmdid = WMI_10_4_RADAR_FOUND_CMDID,
|
||||
};
|
||||
|
||||
/* MAIN WMI VDEV param map */
|
||||
|
@ -1490,6 +1495,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = {
|
|||
.pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.radar_found_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
};
|
||||
|
||||
static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
|
||||
|
@ -3683,6 +3689,68 @@ void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, struct sk_buff *skb)
|
|||
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TBTTOFFSET_UPDATE_EVENTID\n");
|
||||
}
|
||||
|
||||
static void ath10k_radar_detected(struct ath10k *ar)
|
||||
{
|
||||
ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs radar detected\n");
|
||||
ATH10K_DFS_STAT_INC(ar, radar_detected);
|
||||
|
||||
/* Control radar events reporting in debugfs file
|
||||
* dfs_block_radar_events
|
||||
*/
|
||||
if (ar->dfs_block_radar_events)
|
||||
ath10k_info(ar, "DFS Radar detected, but ignored as requested\n");
|
||||
else
|
||||
ieee80211_radar_detected(ar->hw);
|
||||
}
|
||||
|
||||
static void ath10k_radar_confirmation_work(struct work_struct *work)
|
||||
{
|
||||
struct ath10k *ar = container_of(work, struct ath10k,
|
||||
radar_confirmation_work);
|
||||
struct ath10k_radar_found_info radar_info;
|
||||
int ret, time_left;
|
||||
|
||||
reinit_completion(&ar->wmi.radar_confirm);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
memcpy(&radar_info, &ar->last_radar_info, sizeof(radar_info));
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ret = ath10k_wmi_report_radar_found(ar, &radar_info);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to send radar found %d\n", ret);
|
||||
goto wait_complete;
|
||||
}
|
||||
|
||||
time_left = wait_for_completion_timeout(&ar->wmi.radar_confirm,
|
||||
ATH10K_WMI_DFS_CONF_TIMEOUT_HZ);
|
||||
if (time_left) {
|
||||
/* DFS Confirmation status event received and
|
||||
* necessary action completed.
|
||||
*/
|
||||
goto wait_complete;
|
||||
} else {
|
||||
/* DFS Confirmation event not received from FW.Considering this
|
||||
* as real radar.
|
||||
*/
|
||||
ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
|
||||
"dfs confirmation not received from fw, considering as radar\n");
|
||||
goto radar_detected;
|
||||
}
|
||||
|
||||
radar_detected:
|
||||
ath10k_radar_detected(ar);
|
||||
|
||||
/* Reset state to allow sending confirmation on consecutive radar
|
||||
* detections, unless radar confirmation is disabled/stopped.
|
||||
*/
|
||||
wait_complete:
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
if (ar->radar_conf_state != ATH10K_RADAR_CONFIRMATION_STOPPED)
|
||||
ar->radar_conf_state = ATH10K_RADAR_CONFIRMATION_IDLE;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
static void ath10k_dfs_radar_report(struct ath10k *ar,
|
||||
struct wmi_phyerr_ev_arg *phyerr,
|
||||
const struct phyerr_radar_report *rr,
|
||||
|
@ -3691,8 +3759,10 @@ static void ath10k_dfs_radar_report(struct ath10k *ar,
|
|||
u32 reg0, reg1, tsf32l;
|
||||
struct ieee80211_channel *ch;
|
||||
struct pulse_event pe;
|
||||
struct radar_detector_specs rs;
|
||||
u64 tsf64;
|
||||
u8 rssi, width;
|
||||
struct ath10k_radar_found_info *radar_info;
|
||||
|
||||
reg0 = __le32_to_cpu(rr->reg0);
|
||||
reg1 = __le32_to_cpu(rr->reg1);
|
||||
|
@ -3757,25 +3827,46 @@ static void ath10k_dfs_radar_report(struct ath10k *ar,
|
|||
|
||||
ATH10K_DFS_STAT_INC(ar, pulses_detected);
|
||||
|
||||
if (!ar->dfs_detector->add_pulse(ar->dfs_detector, &pe)) {
|
||||
if (!ar->dfs_detector->add_pulse(ar->dfs_detector, &pe, &rs)) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
|
||||
"dfs no pulse pattern detected, yet\n");
|
||||
return;
|
||||
}
|
||||
|
||||
radar_detected:
|
||||
ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs radar detected\n");
|
||||
ATH10K_DFS_STAT_INC(ar, radar_detected);
|
||||
if ((test_bit(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT, ar->wmi.svc_map)) &&
|
||||
ar->dfs_detector->region == NL80211_DFS_FCC) {
|
||||
/* Consecutive radar indications need not be
|
||||
* sent to the firmware until we get confirmation
|
||||
* for the previous detected radar.
|
||||
*/
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
if (ar->radar_conf_state != ATH10K_RADAR_CONFIRMATION_IDLE) {
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
return;
|
||||
}
|
||||
ar->radar_conf_state = ATH10K_RADAR_CONFIRMATION_INPROGRESS;
|
||||
radar_info = &ar->last_radar_info;
|
||||
|
||||
/* Control radar events reporting in debugfs file
|
||||
* dfs_block_radar_events
|
||||
*/
|
||||
if (ar->dfs_block_radar_events) {
|
||||
ath10k_info(ar, "DFS Radar detected, but ignored as requested\n");
|
||||
radar_info->pri_min = rs.pri_min;
|
||||
radar_info->pri_max = rs.pri_max;
|
||||
radar_info->width_min = rs.width_min;
|
||||
radar_info->width_max = rs.width_max;
|
||||
/*TODO Find sidx_min and sidx_max */
|
||||
radar_info->sidx_min = MS(reg0, RADAR_REPORT_REG0_PULSE_SIDX);
|
||||
radar_info->sidx_max = MS(reg0, RADAR_REPORT_REG0_PULSE_SIDX);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
|
||||
"sending wmi radar found cmd pri_min %d pri_max %d width_min %d width_max %d sidx_min %d sidx_max %d\n",
|
||||
radar_info->pri_min, radar_info->pri_max,
|
||||
radar_info->width_min, radar_info->width_max,
|
||||
radar_info->sidx_min, radar_info->sidx_max);
|
||||
ieee80211_queue_work(ar->hw, &ar->radar_confirmation_work);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
ieee80211_radar_detected(ar->hw);
|
||||
radar_detected:
|
||||
ath10k_radar_detected(ar);
|
||||
}
|
||||
|
||||
static int ath10k_dfs_fft_report(struct ath10k *ar,
|
||||
|
@ -4125,6 +4216,47 @@ void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ath10k_wmi_10_4_op_pull_dfs_status_ev(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_dfs_status_ev_arg *arg)
|
||||
{
|
||||
struct wmi_dfs_status_ev_arg *ev = (void *)skb->data;
|
||||
|
||||
if (skb->len < sizeof(*ev))
|
||||
return -EPROTO;
|
||||
|
||||
arg->status = ev->status;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ath10k_wmi_event_dfs_status_check(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_dfs_status_ev_arg status_arg = {};
|
||||
int ret;
|
||||
|
||||
ret = ath10k_wmi_pull_dfs_status(ar, skb, &status_arg);
|
||||
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to parse dfs status event: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
|
||||
"dfs status event received from fw: %d\n",
|
||||
status_arg.status);
|
||||
|
||||
/* Even in case of radar detection failure we follow the same
|
||||
* behaviour as if radar is detected i.e to switch to a different
|
||||
* channel.
|
||||
*/
|
||||
if (status_arg.status == WMI_HW_RADAR_DETECTED ||
|
||||
status_arg.status == WMI_RADAR_DETECTION_FAIL)
|
||||
ath10k_radar_detected(ar);
|
||||
complete(&ar->wmi.radar_confirm);
|
||||
}
|
||||
|
||||
void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_roam_ev_arg arg = {};
|
||||
|
@ -5876,6 +6008,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
case WMI_10_4_PDEV_TPC_TABLE_EVENTID:
|
||||
ath10k_wmi_event_tpc_final_table(ar, skb);
|
||||
break;
|
||||
case WMI_10_4_DFS_STATUS_CHECK_EVENTID:
|
||||
ath10k_wmi_event_dfs_status_check(ar, skb);
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "Unknown eventid: %d\n", id);
|
||||
break;
|
||||
|
@ -8461,6 +8596,32 @@ ath10k_wmi_10_4_gen_tdls_peer_update(struct ath10k *ar,
|
|||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_10_4_gen_radar_found(struct ath10k *ar,
|
||||
const struct ath10k_radar_found_info *arg)
|
||||
{
|
||||
struct wmi_radar_found_info *cmd;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
|
||||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
cmd = (struct wmi_radar_found_info *)skb->data;
|
||||
cmd->pri_min = __cpu_to_le32(arg->pri_min);
|
||||
cmd->pri_max = __cpu_to_le32(arg->pri_max);
|
||||
cmd->width_min = __cpu_to_le32(arg->width_min);
|
||||
cmd->width_max = __cpu_to_le32(arg->width_max);
|
||||
cmd->sidx_min = __cpu_to_le32(arg->sidx_min);
|
||||
cmd->sidx_max = __cpu_to_le32(arg->sidx_max);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi radar found pri_min %d pri_max %d width_min %d width_max %d sidx_min %d sidx_max %d\n",
|
||||
arg->pri_min, arg->pri_max, arg->width_min,
|
||||
arg->width_max, arg->sidx_min, arg->sidx_max);
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_op_gen_echo(struct ath10k *ar, u32 value)
|
||||
{
|
||||
|
@ -8798,6 +8959,7 @@ static const struct wmi_ops wmi_10_4_ops = {
|
|||
.pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev,
|
||||
.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
|
||||
.pull_roam_ev = ath10k_wmi_op_pull_roam_ev,
|
||||
.pull_dfs_status_ev = ath10k_wmi_10_4_op_pull_dfs_status_ev,
|
||||
.get_txbf_conf_scheme = ath10k_wmi_10_4_txbf_conf_scheme,
|
||||
|
||||
.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
|
||||
|
@ -8844,6 +9006,7 @@ static const struct wmi_ops wmi_10_4_ops = {
|
|||
.gen_tdls_peer_update = ath10k_wmi_10_4_gen_tdls_peer_update,
|
||||
.gen_pdev_get_tpc_table_cmdid =
|
||||
ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid,
|
||||
.gen_radar_found = ath10k_wmi_10_4_gen_radar_found,
|
||||
|
||||
/* shared with 10.2 */
|
||||
.pull_echo_ev = ath10k_wmi_op_pull_echo_ev,
|
||||
|
@ -8906,8 +9069,11 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
|||
init_completion(&ar->wmi.service_ready);
|
||||
init_completion(&ar->wmi.unified_ready);
|
||||
init_completion(&ar->wmi.barrier);
|
||||
init_completion(&ar->wmi.radar_confirm);
|
||||
|
||||
INIT_WORK(&ar->svc_rdy_work, ath10k_wmi_event_service_ready_work);
|
||||
INIT_WORK(&ar->radar_confirmation_work,
|
||||
ath10k_radar_confirmation_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -969,6 +969,7 @@ struct wmi_cmd_map {
|
|||
u32 vdev_sifs_trigger_time_cmdid;
|
||||
u32 pdev_wds_entry_list_cmdid;
|
||||
u32 tdls_set_offchan_mode_cmdid;
|
||||
u32 radar_found_cmdid;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1803,6 +1804,11 @@ enum wmi_10_4_cmd_id {
|
|||
WMI_10_4_TDLS_SET_STATE_CMDID,
|
||||
WMI_10_4_TDLS_PEER_UPDATE_CMDID,
|
||||
WMI_10_4_TDLS_SET_OFFCHAN_MODE_CMDID,
|
||||
WMI_10_4_PDEV_SEND_FD_CMDID,
|
||||
WMI_10_4_ENABLE_FILS_CMDID,
|
||||
WMI_10_4_PDEV_SET_BRIDGE_MACADDR_CMDID,
|
||||
WMI_10_4_ATF_GROUP_WMM_AC_CONFIG_REQUEST_CMDID,
|
||||
WMI_10_4_RADAR_FOUND_CMDID,
|
||||
WMI_10_4_PDEV_UTF_CMDID = WMI_10_4_END_CMDID - 1,
|
||||
};
|
||||
|
||||
|
@ -1878,6 +1884,9 @@ enum wmi_10_4_event_id {
|
|||
WMI_10_4_PDEV_TPC_TABLE_EVENTID,
|
||||
WMI_10_4_PDEV_WDS_ENTRY_LIST_EVENTID,
|
||||
WMI_10_4_TDLS_PEER_EVENTID,
|
||||
WMI_10_4_HOST_SWFDA_EVENTID,
|
||||
WMI_10_4_ESP_ESTIMATE_EVENTID,
|
||||
WMI_10_4_DFS_STATUS_CHECK_EVENTID,
|
||||
WMI_10_4_PDEV_UTF_EVENTID = WMI_10_4_END_EVENTID - 1,
|
||||
};
|
||||
|
||||
|
@ -3398,6 +3407,25 @@ struct wmi_10_4_phyerr_event {
|
|||
u8 buf[0];
|
||||
} __packed;
|
||||
|
||||
struct wmi_radar_found_info {
|
||||
__le32 pri_min;
|
||||
__le32 pri_max;
|
||||
__le32 width_min;
|
||||
__le32 width_max;
|
||||
__le32 sidx_min;
|
||||
__le32 sidx_max;
|
||||
} __packed;
|
||||
|
||||
enum wmi_radar_confirmation_status {
|
||||
/* Detected radar was due to SW pulses */
|
||||
WMI_SW_RADAR_DETECTED = 0,
|
||||
|
||||
WMI_RADAR_DETECTION_FAIL = 1,
|
||||
|
||||
/* Real radar detected */
|
||||
WMI_HW_RADAR_DETECTED = 2,
|
||||
};
|
||||
|
||||
#define PHYERR_TLV_SIG 0xBB
|
||||
#define PHYERR_TLV_TAG_SEARCH_FFT_REPORT 0xFB
|
||||
#define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY 0xF8
|
||||
|
@ -6631,6 +6659,10 @@ struct wmi_phyerr_hdr_arg {
|
|||
const void *phyerrs;
|
||||
};
|
||||
|
||||
struct wmi_dfs_status_ev_arg {
|
||||
u32 status;
|
||||
};
|
||||
|
||||
struct wmi_svc_rdy_ev_arg {
|
||||
__le32 min_tx_power;
|
||||
__le32 max_tx_power;
|
||||
|
|
|
@ -277,7 +277,7 @@ ath9k_dfs_process_radar_pulse(struct ath_softc *sc, struct pulse_event *pe)
|
|||
DFS_STAT_INC(sc, pulses_processed);
|
||||
if (pd == NULL)
|
||||
return;
|
||||
if (!pd->add_pulse(pd, pe))
|
||||
if (!pd->add_pulse(pd, pe, NULL))
|
||||
return;
|
||||
DFS_STAT_INC(sc, radar_detected);
|
||||
ieee80211_radar_detected(sc->hw);
|
||||
|
|
|
@ -268,7 +268,8 @@ static void dpd_exit(struct dfs_pattern_detector *dpd)
|
|||
}
|
||||
|
||||
static bool
|
||||
dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event)
|
||||
dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event,
|
||||
struct radar_detector_specs *rs)
|
||||
{
|
||||
u32 i;
|
||||
struct channel_detector *cd;
|
||||
|
@ -294,6 +295,8 @@ dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event)
|
|||
struct pri_detector *pd = cd->detectors[i];
|
||||
struct pri_sequence *ps = pd->add_pulse(pd, event);
|
||||
if (ps != NULL) {
|
||||
if (rs != NULL)
|
||||
memcpy(rs, pd->rs, sizeof(*rs));
|
||||
ath_dbg(dpd->common, DFS,
|
||||
"DFS: radar found on freq=%d: id=%d, pri=%d, "
|
||||
"count=%d, count_false=%d\n",
|
||||
|
|
|
@ -97,7 +97,8 @@ struct dfs_pattern_detector {
|
|||
bool (*set_dfs_domain)(struct dfs_pattern_detector *dpd,
|
||||
enum nl80211_dfs_regions region);
|
||||
bool (*add_pulse)(struct dfs_pattern_detector *dpd,
|
||||
struct pulse_event *pe);
|
||||
struct pulse_event *pe,
|
||||
struct radar_detector_specs *rs);
|
||||
|
||||
struct ath_dfs_pool_stats (*get_stats)(struct dfs_pattern_detector *dpd);
|
||||
enum nl80211_dfs_regions region;
|
||||
|
|
|
@ -62,8 +62,9 @@ struct pri_detector {
|
|||
(*add_pulse)(struct pri_detector *de, struct pulse_event *e);
|
||||
void (*reset) (struct pri_detector *de, u64 ts);
|
||||
|
||||
/* private: internal use only */
|
||||
const struct radar_detector_specs *rs;
|
||||
|
||||
/* private: internal use only */
|
||||
u64 last_ts;
|
||||
struct list_head sequences;
|
||||
struct list_head pulses;
|
||||
|
|
|
@ -68,12 +68,14 @@ enum CountryCode {
|
|||
CTRY_AUSTRALIA = 36,
|
||||
CTRY_AUSTRIA = 40,
|
||||
CTRY_AZERBAIJAN = 31,
|
||||
CTRY_BAHAMAS = 44,
|
||||
CTRY_BAHRAIN = 48,
|
||||
CTRY_BANGLADESH = 50,
|
||||
CTRY_BARBADOS = 52,
|
||||
CTRY_BELARUS = 112,
|
||||
CTRY_BELGIUM = 56,
|
||||
CTRY_BELIZE = 84,
|
||||
CTRY_BERMUDA = 60,
|
||||
CTRY_BOLIVIA = 68,
|
||||
CTRY_BOSNIA_HERZ = 70,
|
||||
CTRY_BRAZIL = 76,
|
||||
|
@ -136,8 +138,10 @@ enum CountryCode {
|
|||
CTRY_MACEDONIA = 807,
|
||||
CTRY_MALAYSIA = 458,
|
||||
CTRY_MALTA = 470,
|
||||
CTRY_MAURITIUS = 480,
|
||||
CTRY_MEXICO = 484,
|
||||
CTRY_MONACO = 492,
|
||||
CTRY_MONTENEGRO = 499,
|
||||
CTRY_MOROCCO = 504,
|
||||
CTRY_NEPAL = 524,
|
||||
CTRY_NETHERLANDS = 528,
|
||||
|
@ -159,6 +163,7 @@ enum CountryCode {
|
|||
CTRY_ROMANIA = 642,
|
||||
CTRY_RUSSIA = 643,
|
||||
CTRY_SAUDI_ARABIA = 682,
|
||||
CTRY_SERBIA = 688,
|
||||
CTRY_SERBIA_MONTENEGRO = 891,
|
||||
CTRY_SINGAPORE = 702,
|
||||
CTRY_SLOVAKIA = 703,
|
||||
|
@ -170,11 +175,13 @@ enum CountryCode {
|
|||
CTRY_SWITZERLAND = 756,
|
||||
CTRY_SYRIA = 760,
|
||||
CTRY_TAIWAN = 158,
|
||||
CTRY_TANZANIA = 834,
|
||||
CTRY_THAILAND = 764,
|
||||
CTRY_TRINIDAD_Y_TOBAGO = 780,
|
||||
CTRY_TUNISIA = 788,
|
||||
CTRY_TURKEY = 792,
|
||||
CTRY_UAE = 784,
|
||||
CTRY_UGANDA = 800,
|
||||
CTRY_UKRAINE = 804,
|
||||
CTRY_UNITED_KINGDOM = 826,
|
||||
CTRY_UNITED_STATES = 840,
|
||||
|
|
|
@ -35,6 +35,7 @@ enum EnumRd {
|
|||
FRANCE_RES = 0x31,
|
||||
FCC3_FCCA = 0x3A,
|
||||
FCC3_WORLD = 0x3B,
|
||||
FCC3_ETSIC = 0x3F,
|
||||
|
||||
ETSI1_WORLD = 0x37,
|
||||
ETSI3_ETSIA = 0x32,
|
||||
|
@ -44,6 +45,8 @@ enum EnumRd {
|
|||
ETSI4_ETSIC = 0x38,
|
||||
ETSI5_WORLD = 0x39,
|
||||
ETSI6_WORLD = 0x34,
|
||||
ETSI8_WORLD = 0x3D,
|
||||
ETSI9_WORLD = 0x3E,
|
||||
ETSI_RESERVED = 0x33,
|
||||
|
||||
MKK1_MKKA = 0x40,
|
||||
|
@ -59,6 +62,7 @@ enum EnumRd {
|
|||
MKK1_MKKA1 = 0x4A,
|
||||
MKK1_MKKA2 = 0x4B,
|
||||
MKK1_MKKC = 0x4C,
|
||||
APL2_FCCA = 0x4D,
|
||||
|
||||
APL3_FCCA = 0x50,
|
||||
APL1_WORLD = 0x52,
|
||||
|
@ -67,6 +71,7 @@ enum EnumRd {
|
|||
APL1_ETSIC = 0x55,
|
||||
APL2_ETSIC = 0x56,
|
||||
APL5_WORLD = 0x58,
|
||||
APL13_WORLD = 0x5A,
|
||||
APL6_WORLD = 0x5B,
|
||||
APL7_FCCA = 0x5C,
|
||||
APL8_WORLD = 0x5D,
|
||||
|
@ -168,6 +173,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = {
|
|||
{FCC2_ETSIC, CTL_FCC, CTL_ETSI},
|
||||
{FCC3_FCCA, CTL_FCC, CTL_FCC},
|
||||
{FCC3_WORLD, CTL_FCC, CTL_ETSI},
|
||||
{FCC3_ETSIC, CTL_FCC, CTL_ETSI},
|
||||
{FCC4_FCCA, CTL_FCC, CTL_FCC},
|
||||
{FCC5_FCCA, CTL_FCC, CTL_FCC},
|
||||
{FCC6_FCCA, CTL_FCC, CTL_FCC},
|
||||
|
@ -179,6 +185,8 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = {
|
|||
{ETSI4_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
{ETSI5_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
{ETSI6_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
{ETSI8_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
{ETSI9_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
|
||||
/* XXX: For ETSI3_ETSIA, Was NO_CTL meant for the 2 GHz band ? */
|
||||
{ETSI3_ETSIA, CTL_ETSI, CTL_ETSI},
|
||||
|
@ -188,9 +196,11 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = {
|
|||
{FCC1_FCCA, CTL_FCC, CTL_FCC},
|
||||
{APL1_WORLD, CTL_FCC, CTL_ETSI},
|
||||
{APL2_WORLD, CTL_FCC, CTL_ETSI},
|
||||
{APL2_FCCA, CTL_FCC, CTL_FCC},
|
||||
{APL3_WORLD, CTL_FCC, CTL_ETSI},
|
||||
{APL4_WORLD, CTL_FCC, CTL_ETSI},
|
||||
{APL5_WORLD, CTL_FCC, CTL_ETSI},
|
||||
{APL13_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
{APL6_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
{APL8_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
{APL9_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
|
@ -289,37 +299,39 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = {
|
|||
static struct country_code_to_enum_rd allCountries[] = {
|
||||
{CTRY_DEBUG, NO_ENUMRD, "DB"},
|
||||
{CTRY_DEFAULT, FCC1_FCCA, "CO"},
|
||||
{CTRY_ALBANIA, NULL1_WORLD, "AL"},
|
||||
{CTRY_ALGERIA, NULL1_WORLD, "DZ"},
|
||||
{CTRY_ALBANIA, ETSI1_WORLD, "AL"},
|
||||
{CTRY_ALGERIA, APL13_WORLD, "DZ"},
|
||||
{CTRY_ARGENTINA, FCC3_WORLD, "AR"},
|
||||
{CTRY_ARMENIA, ETSI4_WORLD, "AM"},
|
||||
{CTRY_ARUBA, ETSI1_WORLD, "AW"},
|
||||
{CTRY_AUSTRALIA, FCC2_WORLD, "AU"},
|
||||
{CTRY_AUSTRALIA, FCC3_WORLD, "AU"},
|
||||
{CTRY_AUSTRALIA2, FCC6_WORLD, "AU"},
|
||||
{CTRY_AUSTRIA, ETSI1_WORLD, "AT"},
|
||||
{CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"},
|
||||
{CTRY_BAHAMAS, FCC3_WORLD, "BS"},
|
||||
{CTRY_BAHRAIN, APL6_WORLD, "BH"},
|
||||
{CTRY_BANGLADESH, NULL1_WORLD, "BD"},
|
||||
{CTRY_BANGLADESH, APL1_WORLD, "BD"},
|
||||
{CTRY_BARBADOS, FCC2_WORLD, "BB"},
|
||||
{CTRY_BELARUS, ETSI1_WORLD, "BY"},
|
||||
{CTRY_BELGIUM, ETSI1_WORLD, "BE"},
|
||||
{CTRY_BELGIUM2, ETSI4_WORLD, "BL"},
|
||||
{CTRY_BELIZE, APL1_ETSIC, "BZ"},
|
||||
{CTRY_BERMUDA, FCC3_FCCA, "BM"},
|
||||
{CTRY_BOLIVIA, APL1_ETSIC, "BO"},
|
||||
{CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA"},
|
||||
{CTRY_BRAZIL, FCC3_WORLD, "BR"},
|
||||
{CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"},
|
||||
{CTRY_BULGARIA, ETSI6_WORLD, "BG"},
|
||||
{CTRY_BRUNEI_DARUSSALAM, APL6_WORLD, "BN"},
|
||||
{CTRY_BULGARIA, ETSI1_WORLD, "BG"},
|
||||
{CTRY_CAMBODIA, ETSI1_WORLD, "KH"},
|
||||
{CTRY_CANADA, FCC3_FCCA, "CA"},
|
||||
{CTRY_CANADA2, FCC6_FCCA, "CA"},
|
||||
{CTRY_CHILE, APL6_WORLD, "CL"},
|
||||
{CTRY_CHINA, APL1_WORLD, "CN"},
|
||||
{CTRY_COLOMBIA, FCC1_FCCA, "CO"},
|
||||
{CTRY_COLOMBIA, FCC3_WORLD, "CO"},
|
||||
{CTRY_COSTA_RICA, FCC1_WORLD, "CR"},
|
||||
{CTRY_CROATIA, ETSI1_WORLD, "HR"},
|
||||
{CTRY_CYPRUS, ETSI1_WORLD, "CY"},
|
||||
{CTRY_CZECH, ETSI3_WORLD, "CZ"},
|
||||
{CTRY_CZECH, ETSI1_WORLD, "CZ"},
|
||||
{CTRY_DENMARK, ETSI1_WORLD, "DK"},
|
||||
{CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO"},
|
||||
{CTRY_ECUADOR, FCC1_WORLD, "EC"},
|
||||
|
@ -336,7 +348,7 @@ static struct country_code_to_enum_rd allCountries[] = {
|
|||
{CTRY_GUAM, FCC1_FCCA, "GU"},
|
||||
{CTRY_GUATEMALA, FCC1_FCCA, "GT"},
|
||||
{CTRY_HAITI, ETSI1_WORLD, "HT"},
|
||||
{CTRY_HONDURAS, NULL1_WORLD, "HN"},
|
||||
{CTRY_HONDURAS, FCC3_WORLD, "HN"},
|
||||
{CTRY_HONG_KONG, FCC3_WORLD, "HK"},
|
||||
{CTRY_HUNGARY, ETSI1_WORLD, "HU"},
|
||||
{CTRY_ICELAND, ETSI1_WORLD, "IS"},
|
||||
|
@ -344,7 +356,7 @@ static struct country_code_to_enum_rd allCountries[] = {
|
|||
{CTRY_INDONESIA, NULL1_WORLD, "ID"},
|
||||
{CTRY_IRAN, APL1_WORLD, "IR"},
|
||||
{CTRY_IRELAND, ETSI1_WORLD, "IE"},
|
||||
{CTRY_ISRAEL, NULL1_WORLD, "IL"},
|
||||
{CTRY_ISRAEL, ETSI3_WORLD, "IL"},
|
||||
{CTRY_ITALY, ETSI1_WORLD, "IT"},
|
||||
{CTRY_JAMAICA, FCC3_WORLD, "JM"},
|
||||
|
||||
|
@ -409,6 +421,7 @@ static struct country_code_to_enum_rd allCountries[] = {
|
|||
|
||||
{CTRY_JORDAN, ETSI2_WORLD, "JO"},
|
||||
{CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ"},
|
||||
{CTRY_KENYA, APL1_WORLD, "KE"},
|
||||
{CTRY_KOREA_NORTH, APL9_WORLD, "KP"},
|
||||
{CTRY_KOREA_ROC, APL9_WORLD, "KR"},
|
||||
{CTRY_KOREA_ROC2, APL2_WORLD, "K2"},
|
||||
|
@ -420,32 +433,37 @@ static struct country_code_to_enum_rd allCountries[] = {
|
|||
{CTRY_LITHUANIA, ETSI1_WORLD, "LT"},
|
||||
{CTRY_LUXEMBOURG, ETSI1_WORLD, "LU"},
|
||||
{CTRY_MACAU, FCC2_WORLD, "MO"},
|
||||
{CTRY_MACEDONIA, NULL1_WORLD, "MK"},
|
||||
{CTRY_MALAYSIA, APL8_WORLD, "MY"},
|
||||
{CTRY_MACEDONIA, ETSI1_WORLD, "MK"},
|
||||
{CTRY_MALAYSIA, FCC1_WORLD, "MY"},
|
||||
{CTRY_MALTA, ETSI1_WORLD, "MT"},
|
||||
{CTRY_MAURITIUS, ETSI1_WORLD, "MU"},
|
||||
{CTRY_MEXICO, FCC1_FCCA, "MX"},
|
||||
{CTRY_MONACO, ETSI4_WORLD, "MC"},
|
||||
{CTRY_MONTENEGRO, ETSI1_WORLD, "ME"},
|
||||
{CTRY_MOROCCO, APL4_WORLD, "MA"},
|
||||
{CTRY_NEPAL, APL1_WORLD, "NP"},
|
||||
{CTRY_NETHERLANDS, ETSI1_WORLD, "NL"},
|
||||
{CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"},
|
||||
{CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"},
|
||||
{CTRY_NEW_ZEALAND, FCC3_ETSIC, "NZ"},
|
||||
{CTRY_NICARAGUA, FCC3_FCCA, "NI"},
|
||||
{CTRY_NORWAY, ETSI1_WORLD, "NO"},
|
||||
{CTRY_OMAN, FCC3_WORLD, "OM"},
|
||||
{CTRY_PAKISTAN, NULL1_WORLD, "PK"},
|
||||
{CTRY_PANAMA, FCC1_FCCA, "PA"},
|
||||
{CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"},
|
||||
{CTRY_PERU, APL1_WORLD, "PE"},
|
||||
{CTRY_PHILIPPINES, APL1_WORLD, "PH"},
|
||||
{CTRY_PARAGUAY, FCC3_WORLD, "PY"},
|
||||
{CTRY_PERU, FCC3_WORLD, "PE"},
|
||||
{CTRY_PHILIPPINES, FCC3_WORLD, "PH"},
|
||||
{CTRY_POLAND, ETSI1_WORLD, "PL"},
|
||||
{CTRY_PORTUGAL, ETSI1_WORLD, "PT"},
|
||||
{CTRY_PUERTO_RICO, FCC1_FCCA, "PR"},
|
||||
{CTRY_QATAR, APL1_WORLD, "QA"},
|
||||
{CTRY_ROMANIA, NULL1_WORLD, "RO"},
|
||||
{CTRY_RUSSIA, NULL1_WORLD, "RU"},
|
||||
{CTRY_ROMANIA, ETSI1_WORLD, "RO"},
|
||||
{CTRY_RUSSIA, ETSI8_WORLD, "RU"},
|
||||
{CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"},
|
||||
{CTRY_SERBIA, ETSI1_WORLD, "RS"},
|
||||
{CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS"},
|
||||
{CTRY_SINGAPORE, APL6_WORLD, "SG"},
|
||||
{CTRY_SINGAPORE, FCC3_WORLD, "SG"},
|
||||
{CTRY_SLOVAKIA, ETSI1_WORLD, "SK"},
|
||||
{CTRY_SLOVENIA, ETSI1_WORLD, "SI"},
|
||||
{CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA"},
|
||||
|
@ -455,11 +473,13 @@ static struct country_code_to_enum_rd allCountries[] = {
|
|||
{CTRY_SWITZERLAND, ETSI1_WORLD, "CH"},
|
||||
{CTRY_SYRIA, NULL1_WORLD, "SY"},
|
||||
{CTRY_TAIWAN, APL3_FCCA, "TW"},
|
||||
{CTRY_TANZANIA, APL1_WORLD, "TZ"},
|
||||
{CTRY_THAILAND, FCC3_WORLD, "TH"},
|
||||
{CTRY_TRINIDAD_Y_TOBAGO, FCC3_WORLD, "TT"},
|
||||
{CTRY_TUNISIA, ETSI3_WORLD, "TN"},
|
||||
{CTRY_TURKEY, ETSI3_WORLD, "TR"},
|
||||
{CTRY_UKRAINE, NULL1_WORLD, "UA"},
|
||||
{CTRY_UGANDA, FCC3_WORLD, "UG"},
|
||||
{CTRY_UKRAINE, ETSI9_WORLD, "UA"},
|
||||
{CTRY_UAE, NULL1_WORLD, "AE"},
|
||||
{CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"},
|
||||
{CTRY_UNITED_STATES, FCC3_FCCA, "US"},
|
||||
|
@ -472,7 +492,7 @@ static struct country_code_to_enum_rd allCountries[] = {
|
|||
{CTRY_VENEZUELA, APL2_ETSIC, "VE"},
|
||||
{CTRY_VIET_NAM, NULL1_WORLD, "VN"},
|
||||
{CTRY_YEMEN, NULL1_WORLD, "YE"},
|
||||
{CTRY_ZIMBABWE, NULL1_WORLD, "ZW"},
|
||||
{CTRY_ZIMBABWE, ETSI1_WORLD, "ZW"},
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,3 +6,5 @@ wcn36xx-y += main.o \
|
|||
smd.o \
|
||||
pmc.o \
|
||||
debug.o
|
||||
|
||||
wcn36xx-$(CONFIG_NL80211_TESTMODE) += testmode.o
|
||||
|
|
|
@ -370,7 +370,9 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch)
|
|||
do {
|
||||
if (READ_ONCE(ctl->desc->ctrl) & WCN36xx_DXE_CTRL_VLD)
|
||||
break;
|
||||
if (ctl->skb) {
|
||||
|
||||
if (ctl->skb &&
|
||||
READ_ONCE(ctl->desc->ctrl) & WCN36xx_DXE_CTRL_EOP) {
|
||||
dma_unmap_single(wcn->dev, ctl->desc->src_addr_l,
|
||||
ctl->skb->len, DMA_TO_DEVICE);
|
||||
info = IEEE80211_SKB_CB(ctl->skb);
|
||||
|
@ -430,8 +432,12 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
|
|||
WCN36XX_INT_MASK_CHAN_TX_H);
|
||||
}
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high\n");
|
||||
reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch);
|
||||
wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high, reason %08x\n",
|
||||
int_reason);
|
||||
|
||||
if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK |
|
||||
WCN36XX_CH_STAT_INT_ED_MASK))
|
||||
reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch);
|
||||
}
|
||||
|
||||
if (int_src & WCN36XX_INT_MASK_CHAN_TX_L) {
|
||||
|
@ -465,8 +471,12 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
|
|||
WCN36XX_INT_MASK_CHAN_TX_L);
|
||||
}
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low\n");
|
||||
reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch);
|
||||
wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low, reason %08x\n",
|
||||
int_reason);
|
||||
|
||||
if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK |
|
||||
WCN36XX_CH_STAT_INT_ED_MASK))
|
||||
reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -476,9 +486,8 @@ static irqreturn_t wcn36xx_irq_rx_ready(int irq, void *dev)
|
|||
{
|
||||
struct wcn36xx *wcn = (struct wcn36xx *)dev;
|
||||
|
||||
disable_irq_nosync(wcn->rx_irq);
|
||||
wcn36xx_dxe_rx_frame(wcn);
|
||||
enable_irq(wcn->rx_irq);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -512,23 +521,49 @@ out_err:
|
|||
}
|
||||
|
||||
static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn,
|
||||
struct wcn36xx_dxe_ch *ch)
|
||||
struct wcn36xx_dxe_ch *ch,
|
||||
u32 ctrl,
|
||||
u32 en_mask,
|
||||
u32 int_mask,
|
||||
u32 status_reg)
|
||||
{
|
||||
struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl;
|
||||
struct wcn36xx_dxe_desc *dxe = ctl->desc;
|
||||
struct wcn36xx_dxe_desc *dxe;
|
||||
struct wcn36xx_dxe_ctl *ctl;
|
||||
dma_addr_t dma_addr;
|
||||
struct sk_buff *skb;
|
||||
int ret = 0, int_mask;
|
||||
u32 value;
|
||||
u32 int_reason;
|
||||
int ret;
|
||||
|
||||
if (ch->ch_type == WCN36XX_DXE_CH_RX_L) {
|
||||
value = WCN36XX_DXE_CTRL_RX_L;
|
||||
int_mask = WCN36XX_DXE_INT_CH1_MASK;
|
||||
} else {
|
||||
value = WCN36XX_DXE_CTRL_RX_H;
|
||||
int_mask = WCN36XX_DXE_INT_CH3_MASK;
|
||||
wcn36xx_dxe_read_register(wcn, status_reg, &int_reason);
|
||||
wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, int_mask);
|
||||
|
||||
if (int_reason & WCN36XX_CH_STAT_INT_ERR_MASK) {
|
||||
wcn36xx_dxe_write_register(wcn,
|
||||
WCN36XX_DXE_0_INT_ERR_CLR,
|
||||
int_mask);
|
||||
|
||||
wcn36xx_err("DXE IRQ reported error on RX channel\n");
|
||||
}
|
||||
|
||||
if (int_reason & WCN36XX_CH_STAT_INT_DONE_MASK)
|
||||
wcn36xx_dxe_write_register(wcn,
|
||||
WCN36XX_DXE_0_INT_DONE_CLR,
|
||||
int_mask);
|
||||
|
||||
if (int_reason & WCN36XX_CH_STAT_INT_ED_MASK)
|
||||
wcn36xx_dxe_write_register(wcn,
|
||||
WCN36XX_DXE_0_INT_ED_CLR,
|
||||
int_mask);
|
||||
|
||||
if (!(int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK |
|
||||
WCN36XX_CH_STAT_INT_ED_MASK)))
|
||||
return 0;
|
||||
|
||||
spin_lock(&ch->lock);
|
||||
|
||||
ctl = ch->head_blk_ctl;
|
||||
dxe = ctl->desc;
|
||||
|
||||
while (!(READ_ONCE(dxe->ctrl) & WCN36xx_DXE_CTRL_VLD)) {
|
||||
skb = ctl->skb;
|
||||
dma_addr = dxe->dst_addr_l;
|
||||
|
@ -542,13 +577,16 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn,
|
|||
wcn36xx_rx_skb(wcn, skb);
|
||||
} /* else keep old skb not submitted and use it for rx DMA */
|
||||
|
||||
dxe->ctrl = value;
|
||||
dxe->ctrl = ctrl;
|
||||
ctl = ctl->next;
|
||||
dxe = ctl->desc;
|
||||
}
|
||||
wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, int_mask);
|
||||
wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, en_mask);
|
||||
|
||||
ch->head_blk_ctl = ctl;
|
||||
|
||||
spin_unlock(&ch->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -559,19 +597,20 @@ void wcn36xx_dxe_rx_frame(struct wcn36xx *wcn)
|
|||
wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src);
|
||||
|
||||
/* RX_LOW_PRI */
|
||||
if (int_src & WCN36XX_DXE_INT_CH1_MASK) {
|
||||
wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR,
|
||||
WCN36XX_DXE_INT_CH1_MASK);
|
||||
wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_l_ch));
|
||||
}
|
||||
if (int_src & WCN36XX_DXE_INT_CH1_MASK)
|
||||
wcn36xx_rx_handle_packets(wcn, &wcn->dxe_rx_l_ch,
|
||||
WCN36XX_DXE_CTRL_RX_L,
|
||||
WCN36XX_DXE_INT_CH1_MASK,
|
||||
WCN36XX_INT_MASK_CHAN_RX_L,
|
||||
WCN36XX_DXE_CH_STATUS_REG_ADDR_RX_L);
|
||||
|
||||
/* RX_HIGH_PRI */
|
||||
if (int_src & WCN36XX_DXE_INT_CH3_MASK) {
|
||||
/* Clean up all the INT within this channel */
|
||||
wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR,
|
||||
WCN36XX_DXE_INT_CH3_MASK);
|
||||
wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_h_ch));
|
||||
}
|
||||
if (int_src & WCN36XX_DXE_INT_CH3_MASK)
|
||||
wcn36xx_rx_handle_packets(wcn, &wcn->dxe_rx_h_ch,
|
||||
WCN36XX_DXE_CTRL_RX_H,
|
||||
WCN36XX_DXE_INT_CH3_MASK,
|
||||
WCN36XX_INT_MASK_CHAN_RX_H,
|
||||
WCN36XX_DXE_CH_STATUS_REG_ADDR_RX_H);
|
||||
|
||||
if (!int_src)
|
||||
wcn36xx_warn("No DXE interrupt pending\n");
|
||||
|
@ -642,8 +681,8 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
|
|||
struct sk_buff *skb,
|
||||
bool is_low)
|
||||
{
|
||||
struct wcn36xx_dxe_ctl *ctl = NULL;
|
||||
struct wcn36xx_dxe_desc *desc = NULL;
|
||||
struct wcn36xx_dxe_desc *desc_bd, *desc_skb;
|
||||
struct wcn36xx_dxe_ctl *ctl_bd, *ctl_skb;
|
||||
struct wcn36xx_dxe_ch *ch = NULL;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
@ -651,74 +690,75 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
|
|||
ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch;
|
||||
|
||||
spin_lock_irqsave(&ch->lock, flags);
|
||||
ctl = ch->head_blk_ctl;
|
||||
ctl_bd = ch->head_blk_ctl;
|
||||
ctl_skb = ctl_bd->next;
|
||||
|
||||
/*
|
||||
* If skb is not null that means that we reached the tail of the ring
|
||||
* hence ring is full. Stop queues to let mac80211 back off until ring
|
||||
* has an empty slot again.
|
||||
*/
|
||||
if (NULL != ctl->next->skb) {
|
||||
if (NULL != ctl_skb->skb) {
|
||||
ieee80211_stop_queues(wcn->hw);
|
||||
wcn->queues_stopped = true;
|
||||
spin_unlock_irqrestore(&ch->lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ctl->skb = NULL;
|
||||
desc = ctl->desc;
|
||||
|
||||
/* write buffer descriptor */
|
||||
memcpy(ctl->bd_cpu_addr, bd, sizeof(*bd));
|
||||
|
||||
/* Set source address of the BD we send */
|
||||
desc->src_addr_l = ctl->bd_phy_addr;
|
||||
|
||||
desc->dst_addr_l = ch->dxe_wq;
|
||||
desc->fr_len = sizeof(struct wcn36xx_tx_bd);
|
||||
desc->ctrl = ch->ctrl_bd;
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_DXE, "DXE TX\n");
|
||||
|
||||
wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC1 >>> ",
|
||||
(char *)desc, sizeof(*desc));
|
||||
wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP,
|
||||
"BD >>> ", (char *)ctl->bd_cpu_addr,
|
||||
sizeof(struct wcn36xx_tx_bd));
|
||||
|
||||
/* Set source address of the SKB we send */
|
||||
ctl = ctl->next;
|
||||
desc = ctl->desc;
|
||||
if (ctl->bd_cpu_addr) {
|
||||
if (unlikely(ctl_skb->bd_cpu_addr)) {
|
||||
wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n");
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
desc->src_addr_l = dma_map_single(wcn->dev,
|
||||
skb->data,
|
||||
skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(wcn->dev, desc->src_addr_l)) {
|
||||
desc_bd = ctl_bd->desc;
|
||||
desc_skb = ctl_skb->desc;
|
||||
|
||||
ctl_bd->skb = NULL;
|
||||
|
||||
/* write buffer descriptor */
|
||||
memcpy(ctl_bd->bd_cpu_addr, bd, sizeof(*bd));
|
||||
|
||||
/* Set source address of the BD we send */
|
||||
desc_bd->src_addr_l = ctl_bd->bd_phy_addr;
|
||||
desc_bd->dst_addr_l = ch->dxe_wq;
|
||||
desc_bd->fr_len = sizeof(struct wcn36xx_tx_bd);
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_DXE, "DXE TX\n");
|
||||
|
||||
wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC1 >>> ",
|
||||
(char *)desc_bd, sizeof(*desc_bd));
|
||||
wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP,
|
||||
"BD >>> ", (char *)ctl_bd->bd_cpu_addr,
|
||||
sizeof(struct wcn36xx_tx_bd));
|
||||
|
||||
desc_skb->src_addr_l = dma_map_single(wcn->dev,
|
||||
skb->data,
|
||||
skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(wcn->dev, desc_skb->src_addr_l)) {
|
||||
dev_err(wcn->dev, "unable to DMA map src_addr_l\n");
|
||||
ret = -ENOMEM;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ctl->skb = skb;
|
||||
desc->dst_addr_l = ch->dxe_wq;
|
||||
desc->fr_len = ctl->skb->len;
|
||||
|
||||
/* set dxe descriptor to VALID */
|
||||
desc->ctrl = ch->ctrl_skb;
|
||||
ctl_skb->skb = skb;
|
||||
desc_skb->dst_addr_l = ch->dxe_wq;
|
||||
desc_skb->fr_len = ctl_skb->skb->len;
|
||||
|
||||
wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC2 >>> ",
|
||||
(char *)desc, sizeof(*desc));
|
||||
(char *)desc_skb, sizeof(*desc_skb));
|
||||
wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "SKB >>> ",
|
||||
(char *)ctl->skb->data, ctl->skb->len);
|
||||
(char *)ctl_skb->skb->data, ctl_skb->skb->len);
|
||||
|
||||
/* Move the head of the ring to the next empty descriptor */
|
||||
ch->head_blk_ctl = ctl->next;
|
||||
ch->head_blk_ctl = ctl_skb->next;
|
||||
|
||||
/* Commit all previous writes and set descriptors to VALID */
|
||||
wmb();
|
||||
desc_skb->ctrl = ch->ctrl_skb;
|
||||
wmb();
|
||||
desc_bd->ctrl = ch->ctrl_bd;
|
||||
|
||||
/*
|
||||
* When connected and trying to send data frame chip can be in sleep
|
||||
|
|
|
@ -2236,6 +2236,22 @@ struct wcn36xx_hal_switch_channel_rsp_msg {
|
|||
|
||||
} __packed;
|
||||
|
||||
struct wcn36xx_hal_process_ptt_msg_req_msg {
|
||||
struct wcn36xx_hal_msg_header header;
|
||||
|
||||
/* Actual FTM Command body */
|
||||
u8 ptt_msg[0];
|
||||
} __packed;
|
||||
|
||||
struct wcn36xx_hal_process_ptt_msg_rsp_msg {
|
||||
struct wcn36xx_hal_msg_header header;
|
||||
|
||||
/* FTM Command response status */
|
||||
u32 ptt_msg_resp_status;
|
||||
/* Actual FTM Command body */
|
||||
u8 ptt_msg[0];
|
||||
} __packed;
|
||||
|
||||
struct update_edca_params_req_msg {
|
||||
struct wcn36xx_hal_msg_header header;
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/soc/qcom/smem_state.h>
|
||||
#include <linux/soc/qcom/wcnss_ctrl.h>
|
||||
#include "wcn36xx.h"
|
||||
#include "testmode.h"
|
||||
|
||||
unsigned int wcn36xx_dbg_mask;
|
||||
module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644);
|
||||
|
@ -798,6 +799,8 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
|||
if (!is_zero_ether_addr(bss_conf->bssid)) {
|
||||
vif_priv->is_joining = true;
|
||||
vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
|
||||
wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr,
|
||||
WCN36XX_HAL_LINK_PREASSOC_STATE);
|
||||
wcn36xx_smd_join(wcn, bss_conf->bssid,
|
||||
vif->addr, WCN36XX_HW_CHANNEL(wcn));
|
||||
wcn36xx_smd_config_bss(wcn, vif, NULL,
|
||||
|
@ -805,6 +808,8 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
|||
} else {
|
||||
vif_priv->is_joining = false;
|
||||
wcn36xx_smd_delete_bss(wcn, vif);
|
||||
wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr,
|
||||
WCN36XX_HAL_LINK_IDLE_STATE);
|
||||
vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
|
||||
}
|
||||
}
|
||||
|
@ -1142,6 +1147,8 @@ static const struct ieee80211_ops wcn36xx_ops = {
|
|||
.sta_add = wcn36xx_sta_add,
|
||||
.sta_remove = wcn36xx_sta_remove,
|
||||
.ampdu_action = wcn36xx_ampdu_action,
|
||||
|
||||
CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd)
|
||||
};
|
||||
|
||||
static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
|
||||
|
@ -1309,6 +1316,12 @@ static int wcn36xx_probe(struct platform_device *pdev)
|
|||
mutex_init(&wcn->hal_mutex);
|
||||
mutex_init(&wcn->scan_lock);
|
||||
|
||||
ret = dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32));
|
||||
if (ret < 0) {
|
||||
wcn36xx_err("failed to set DMA mask: %d\n", ret);
|
||||
goto out_wq;
|
||||
}
|
||||
|
||||
INIT_WORK(&wcn->scan_work, wcn36xx_hw_scan_worker);
|
||||
|
||||
wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process, hw);
|
||||
|
|
|
@ -252,23 +252,29 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
|
|||
{
|
||||
int ret = 0;
|
||||
unsigned long start;
|
||||
struct wcn36xx_hal_msg_header *hdr =
|
||||
(struct wcn36xx_hal_msg_header *)wcn->hal_buf;
|
||||
u16 req_type = hdr->msg_type;
|
||||
|
||||
wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len);
|
||||
|
||||
init_completion(&wcn->hal_rsp_compl);
|
||||
start = jiffies;
|
||||
ret = rpmsg_send(wcn->smd_channel, wcn->hal_buf, len);
|
||||
if (ret) {
|
||||
wcn36xx_err("HAL TX failed\n");
|
||||
wcn36xx_err("HAL TX failed for req %d\n", req_type);
|
||||
goto out;
|
||||
}
|
||||
if (wait_for_completion_timeout(&wcn->hal_rsp_compl,
|
||||
msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) {
|
||||
wcn36xx_err("Timeout! No SMD response in %dms\n",
|
||||
HAL_MSG_TIMEOUT);
|
||||
wcn36xx_err("Timeout! No SMD response to req %d in %dms\n",
|
||||
req_type, HAL_MSG_TIMEOUT);
|
||||
ret = -ETIME;
|
||||
goto out;
|
||||
}
|
||||
wcn36xx_dbg(WCN36XX_DBG_SMD, "SMD command completed in %dms",
|
||||
wcn36xx_dbg(WCN36XX_DBG_SMD,
|
||||
"SMD command (req %d, rsp %d) completed in %dms\n",
|
||||
req_type, hdr->msg_type,
|
||||
jiffies_to_msecs(jiffies - start));
|
||||
out:
|
||||
return ret;
|
||||
|
@ -292,12 +298,26 @@ static void init_hal_msg(struct wcn36xx_hal_msg_header *hdr,
|
|||
msg_body.header.len = sizeof(msg_body); \
|
||||
} while (0) \
|
||||
|
||||
#define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \
|
||||
do { \
|
||||
memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \
|
||||
p_msg_body->header.msg_type = WCN36XX_HAL_PROCESS_PTT_REQ; \
|
||||
p_msg_body->header.msg_version = WCN36XX_HAL_MSG_VERSION0; \
|
||||
p_msg_body->header.len = sizeof(*p_msg_body) + ppt_msg_len; \
|
||||
} while (0)
|
||||
|
||||
#define PREPARE_HAL_BUF(send_buf, msg_body) \
|
||||
do { \
|
||||
memset(send_buf, 0, msg_body.header.len); \
|
||||
memcpy(send_buf, &msg_body, sizeof(msg_body)); \
|
||||
} while (0) \
|
||||
|
||||
#define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \
|
||||
do { \
|
||||
memset(send_buf, 0, p_msg_body->header.len); \
|
||||
memcpy(send_buf, p_msg_body, p_msg_body->header.len); \
|
||||
} while (0)
|
||||
|
||||
static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
|
||||
{
|
||||
struct wcn36xx_fw_msg_status_rsp *rsp;
|
||||
|
@ -754,6 +774,71 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int wcn36xx_smd_process_ptt_msg_rsp(void *buf, size_t len,
|
||||
void **p_ptt_rsp_msg)
|
||||
{
|
||||
struct wcn36xx_hal_process_ptt_msg_rsp_msg *rsp;
|
||||
int ret;
|
||||
|
||||
ret = wcn36xx_smd_rsp_status_check(buf, len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rsp = (struct wcn36xx_hal_process_ptt_msg_rsp_msg *)buf;
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_HAL, "process ptt msg responded with length %d\n",
|
||||
rsp->header.len);
|
||||
wcn36xx_dbg_dump(WCN36XX_DBG_HAL_DUMP, "HAL_PTT_MSG_RSP:", rsp->ptt_msg,
|
||||
rsp->header.len - sizeof(rsp->ptt_msg_resp_status));
|
||||
|
||||
if (rsp->header.len > 0) {
|
||||
*p_ptt_rsp_msg = kmalloc(rsp->header.len, GFP_ATOMIC);
|
||||
if (!*p_ptt_rsp_msg)
|
||||
return -ENOMEM;
|
||||
memcpy(*p_ptt_rsp_msg, rsp->ptt_msg, rsp->header.len);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wcn36xx_smd_process_ptt_msg(struct wcn36xx *wcn,
|
||||
struct ieee80211_vif *vif, void *ptt_msg, size_t len,
|
||||
void **ptt_rsp_msg)
|
||||
{
|
||||
struct wcn36xx_hal_process_ptt_msg_req_msg *p_msg_body;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
p_msg_body = kmalloc(
|
||||
sizeof(struct wcn36xx_hal_process_ptt_msg_req_msg) + len,
|
||||
GFP_ATOMIC);
|
||||
if (!p_msg_body) {
|
||||
ret = -ENOMEM;
|
||||
goto out_nomem;
|
||||
}
|
||||
INIT_HAL_PTT_MSG(p_msg_body, len);
|
||||
|
||||
memcpy(&p_msg_body->ptt_msg, ptt_msg, len);
|
||||
|
||||
PREPARE_HAL_PTT_MSG_BUF(wcn->hal_buf, p_msg_body);
|
||||
|
||||
ret = wcn36xx_smd_send_and_wait(wcn, p_msg_body->header.len);
|
||||
if (ret) {
|
||||
wcn36xx_err("Sending hal_process_ptt_msg failed\n");
|
||||
goto out;
|
||||
}
|
||||
ret = wcn36xx_smd_process_ptt_msg_rsp(wcn->hal_buf, wcn->hal_rsp_len,
|
||||
ptt_rsp_msg);
|
||||
if (ret) {
|
||||
wcn36xx_err("process_ptt_msg response failed err=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
kfree(p_msg_body);
|
||||
out_nomem:
|
||||
mutex_unlock(&wcn->hal_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len)
|
||||
{
|
||||
struct wcn36xx_hal_update_scan_params_resp *rsp;
|
||||
|
@ -2390,6 +2475,7 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
|
|||
case WCN36XX_HAL_JOIN_RSP:
|
||||
case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP:
|
||||
case WCN36XX_HAL_CH_SWITCH_RSP:
|
||||
case WCN36XX_HAL_PROCESS_PTT_RSP:
|
||||
case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
|
||||
case WCN36XX_HAL_8023_MULTICAST_LIST_RSP:
|
||||
case WCN36XX_HAL_START_SCAN_OFFLOAD_RSP:
|
||||
|
@ -2430,6 +2516,7 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wcn36xx_ind_smd_work(struct work_struct *work)
|
||||
{
|
||||
struct wcn36xx *wcn =
|
||||
|
@ -2494,24 +2581,24 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
|
|||
}
|
||||
int wcn36xx_smd_open(struct wcn36xx *wcn)
|
||||
{
|
||||
int ret = 0;
|
||||
wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind");
|
||||
if (!wcn->hal_ind_wq) {
|
||||
wcn36xx_err("failed to allocate wq\n");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!wcn->hal_ind_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
|
||||
INIT_LIST_HEAD(&wcn->hal_ind_queue);
|
||||
spin_lock_init(&wcn->hal_ind_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void wcn36xx_smd_close(struct wcn36xx *wcn)
|
||||
{
|
||||
struct wcn36xx_hal_ind_msg *msg, *tmp;
|
||||
|
||||
cancel_work_sync(&wcn->hal_ind_work);
|
||||
destroy_workqueue(wcn->hal_ind_wq);
|
||||
|
||||
list_for_each_entry_safe(msg, tmp, &wcn->hal_ind_queue, list)
|
||||
kfree(msg);
|
||||
}
|
||||
|
|
|
@ -86,6 +86,10 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
|
|||
u16 p2p_off);
|
||||
int wcn36xx_smd_switch_channel(struct wcn36xx *wcn,
|
||||
struct ieee80211_vif *vif, int ch);
|
||||
int wcn36xx_smd_process_ptt_msg(struct wcn36xx *wcn,
|
||||
struct ieee80211_vif *vif,
|
||||
void *ptt_msg, size_t len,
|
||||
void **ptt_rsp_msg);
|
||||
int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn,
|
||||
struct ieee80211_vif *vif,
|
||||
struct sk_buff *skb);
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* 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 <net/netlink.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include "wcn36xx.h"
|
||||
|
||||
#include "testmode.h"
|
||||
#include "testmode_i.h"
|
||||
#include "hal.h"
|
||||
#include "smd.h"
|
||||
|
||||
static const struct nla_policy wcn36xx_tm_policy[WCN36XX_TM_ATTR_MAX + 1] = {
|
||||
[WCN36XX_TM_ATTR_CMD] = { .type = NLA_U16 },
|
||||
[WCN36XX_TM_ATTR_DATA] = { .type = NLA_BINARY,
|
||||
.len = WCN36XX_TM_DATA_MAX_LEN },
|
||||
};
|
||||
|
||||
struct build_release_number {
|
||||
u16 drv_major;
|
||||
u16 drv_minor;
|
||||
u16 drv_patch;
|
||||
u16 drv_build;
|
||||
u16 ptt_max;
|
||||
u16 ptt_min;
|
||||
u16 fw_ver;
|
||||
} __packed;
|
||||
|
||||
static int wcn36xx_tm_cmd_ptt(struct wcn36xx *wcn, struct ieee80211_vif *vif,
|
||||
struct nlattr *tb[])
|
||||
{
|
||||
int ret = 0, buf_len;
|
||||
void *buf;
|
||||
struct ftm_rsp_msg *msg, *rsp = NULL;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!tb[WCN36XX_TM_ATTR_DATA])
|
||||
return -EINVAL;
|
||||
|
||||
buf = nla_data(tb[WCN36XX_TM_ATTR_DATA]);
|
||||
buf_len = nla_len(tb[WCN36XX_TM_ATTR_DATA]);
|
||||
msg = (struct ftm_rsp_msg *)buf;
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_TESTMODE,
|
||||
"testmode cmd wmi msg_id 0x%04X msg_len %d buf %pK buf_len %d\n",
|
||||
msg->msg_id, msg->msg_body_length,
|
||||
buf, buf_len);
|
||||
|
||||
wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP, "REQ ", buf, buf_len);
|
||||
|
||||
if (msg->msg_id == MSG_GET_BUILD_RELEASE_NUMBER) {
|
||||
struct build_release_number *body =
|
||||
(struct build_release_number *)
|
||||
msg->msg_response;
|
||||
|
||||
body->drv_major = wcn->fw_major;
|
||||
body->drv_minor = wcn->fw_minor;
|
||||
body->drv_patch = wcn->fw_version;
|
||||
body->drv_build = wcn->fw_revision;
|
||||
body->ptt_max = 10;
|
||||
body->ptt_min = 0;
|
||||
|
||||
rsp = msg;
|
||||
rsp->resp_status = 0;
|
||||
} else {
|
||||
wcn36xx_dbg(WCN36XX_DBG_TESTMODE,
|
||||
"PPT Request >> HAL size %d\n",
|
||||
msg->msg_body_length);
|
||||
|
||||
msg->resp_status = wcn36xx_smd_process_ptt_msg(wcn, vif, msg,
|
||||
msg->msg_body_length, (void *)(&rsp));
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_TESTMODE,
|
||||
"Response status = %d\n",
|
||||
msg->resp_status);
|
||||
if (rsp)
|
||||
wcn36xx_dbg(WCN36XX_DBG_TESTMODE,
|
||||
"PPT Response << HAL size %d\n",
|
||||
rsp->msg_body_length);
|
||||
}
|
||||
|
||||
if (!rsp) {
|
||||
rsp = msg;
|
||||
wcn36xx_warn("No response! Echoing request with response status %d\n",
|
||||
rsp->resp_status);
|
||||
}
|
||||
wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP, "RSP ",
|
||||
rsp, rsp->msg_body_length);
|
||||
|
||||
skb = cfg80211_testmode_alloc_reply_skb(wcn->hw->wiphy,
|
||||
nla_total_size(msg->msg_body_length));
|
||||
if (!skb) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = nla_put(skb, WCN36XX_TM_ATTR_DATA, rsp->msg_body_length, rsp);
|
||||
if (ret) {
|
||||
kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = cfg80211_testmode_reply(skb);
|
||||
|
||||
out:
|
||||
if (rsp != msg)
|
||||
kfree(rsp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wcn36xx_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
void *data, int len)
|
||||
{
|
||||
struct wcn36xx *wcn = hw->priv;
|
||||
struct nlattr *tb[WCN36XX_TM_ATTR_MAX + 1];
|
||||
int ret = 0;
|
||||
unsigned short attr;
|
||||
|
||||
wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP, "Data:", data, len);
|
||||
ret = nla_parse(tb, WCN36XX_TM_ATTR_MAX, data, len,
|
||||
wcn36xx_tm_policy, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!tb[WCN36XX_TM_ATTR_CMD])
|
||||
return -EINVAL;
|
||||
|
||||
attr = nla_get_u16(tb[WCN36XX_TM_ATTR_CMD]);
|
||||
|
||||
if (attr != WCN36XX_TM_CMD_PTT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return wcn36xx_tm_cmd_ptt(wcn, vif, tb);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* 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 "wcn36xx.h"
|
||||
|
||||
struct ftm_rsp_msg {
|
||||
u16 msg_id;
|
||||
u16 msg_body_length;
|
||||
u32 resp_status;
|
||||
u8 msg_response[0];
|
||||
} __packed;
|
||||
|
||||
/* The request buffer of FTM which contains a byte of command and the request */
|
||||
struct ftm_payload {
|
||||
u16 ftm_cmd_type;
|
||||
struct ftm_rsp_msg ftm_cmd_msg;
|
||||
} __packed;
|
||||
|
||||
#define MSG_GET_BUILD_RELEASE_NUMBER 0x32A2
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
int wcn36xx_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
void *data, int len);
|
||||
|
||||
#else
|
||||
static inline int wcn36xx_tm_cmd(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
void *data, int len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define WCN36XX_TM_DATA_MAX_LEN 5000
|
||||
|
||||
enum wcn36xx_tm_attr {
|
||||
__WCN36XX_TM_ATTR_INVALID = 0,
|
||||
WCN36XX_TM_ATTR_CMD = 1,
|
||||
WCN36XX_TM_ATTR_DATA = 2,
|
||||
|
||||
/* keep last */
|
||||
__WCN36XX_TM_ATTR_AFTER_LAST,
|
||||
WCN36XX_TM_ATTR_MAX = __WCN36XX_TM_ATTR_AFTER_LAST - 1,
|
||||
};
|
||||
|
||||
#define WCN36XX_TM_CMD_PTT 3
|
|
@ -50,6 +50,8 @@ enum wcn36xx_debug_mask {
|
|||
WCN36XX_DBG_BEACON_DUMP = 0x00001000,
|
||||
WCN36XX_DBG_PMC = 0x00002000,
|
||||
WCN36XX_DBG_PMC_DUMP = 0x00004000,
|
||||
WCN36XX_DBG_TESTMODE = 0x00008000,
|
||||
WCN36XX_DBG_TESTMODE_DUMP = 0x00010000,
|
||||
WCN36XX_DBG_ANY = 0xffffffff,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue