mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-22 08:53:18 +07:00
wl18xx: add radar detection implementation
Add support for CAC start/stop commands, and pass radar detection events from the fw to mac80211. Bump fw name (to wl18xx-fw-4.bin) and min fw version (to 8.9.*.*.11), and align event mailbox accordingly. Signed-off-by: Guy Mishol <guym@ti.com> Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
parent
e2f1e50f62
commit
750e9d15e2
@ -167,3 +167,34 @@ int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl18xx_cmd_set_cac(struct wl1271 *wl, struct wl12xx_vif *wlvif, bool start)
|
||||
{
|
||||
struct wlcore_cmd_cac_start *cmd;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd cac (channel %d) %s",
|
||||
wlvif->channel, start ? "start" : "stop");
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd->role_id = wlvif->role_id;
|
||||
cmd->channel = wlvif->channel;
|
||||
if (wlvif->band == IEEE80211_BAND_5GHZ)
|
||||
cmd->band = WLCORE_BAND_5GHZ;
|
||||
cmd->bandwidth = wlcore_get_native_channel_type(wlvif->channel_type);
|
||||
|
||||
ret = wl1271_cmd_send(wl,
|
||||
start ? CMD_CAC_START : CMD_CAC_STOP,
|
||||
cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to send cac command");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
kfree(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
@ -59,6 +59,16 @@ struct wl18xx_cmd_smart_config_set_group_key {
|
||||
u8 key[16];
|
||||
} __packed;
|
||||
|
||||
/* cac_start and cac_stop share the same params */
|
||||
struct wlcore_cmd_cac_start {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
u8 role_id;
|
||||
u8 channel;
|
||||
u8 band;
|
||||
u8 bandwidth;
|
||||
} __packed;
|
||||
|
||||
int wl18xx_cmd_channel_switch(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
struct ieee80211_channel_switch *ch_switch);
|
||||
@ -66,4 +76,5 @@ int wl18xx_cmd_smart_config_start(struct wl1271 *wl, u32 group_bitmap);
|
||||
int wl18xx_cmd_smart_config_stop(struct wl1271 *wl);
|
||||
int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
|
||||
u8 key_len, u8 *key);
|
||||
int wl18xx_cmd_set_cac(struct wl1271 *wl, struct wl12xx_vif *wlvif, bool start);
|
||||
#endif
|
||||
|
@ -47,6 +47,19 @@ int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
|
||||
return wlcore_cmd_wait_for_event_or_timeout(wl, local_event, timeout);
|
||||
}
|
||||
|
||||
static const char *wl18xx_radar_type_decode(u8 radar_type)
|
||||
{
|
||||
switch (radar_type) {
|
||||
case RADAR_TYPE_REGULAR:
|
||||
return "REGULAR";
|
||||
case RADAR_TYPE_CHIRP:
|
||||
return "CHIRP";
|
||||
case RADAR_TYPE_NONE:
|
||||
default:
|
||||
return "N/A";
|
||||
}
|
||||
}
|
||||
|
||||
static int wlcore_smart_config_sync_event(struct wl1271 *wl, u8 sync_channel,
|
||||
u8 sync_band)
|
||||
{
|
||||
@ -115,6 +128,14 @@ int wl18xx_process_mailbox_events(struct wl1271 *wl)
|
||||
wl18xx_scan_completed(wl, wl->scan_wlvif);
|
||||
}
|
||||
|
||||
if (vector & RADAR_DETECTED_EVENT_ID) {
|
||||
wl1271_info("radar event: channel %d type %s",
|
||||
mbox->radar_channel,
|
||||
wl18xx_radar_type_decode(mbox->radar_type));
|
||||
|
||||
ieee80211_radar_detected(wl->hw);
|
||||
}
|
||||
|
||||
if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) {
|
||||
wl1271_debug(DEBUG_EVENT,
|
||||
"PERIODIC_SCAN_REPORT_EVENT (results %d)",
|
||||
|
@ -42,6 +42,12 @@ enum {
|
||||
SMART_CONFIG_DECODE_EVENT_ID = BIT(23),
|
||||
};
|
||||
|
||||
enum wl18xx_radar_types {
|
||||
RADAR_TYPE_NONE,
|
||||
RADAR_TYPE_REGULAR,
|
||||
RADAR_TYPE_CHIRP
|
||||
};
|
||||
|
||||
struct wl18xx_event_mailbox {
|
||||
__le32 events_vector;
|
||||
|
||||
@ -83,13 +89,19 @@ struct wl18xx_event_mailbox {
|
||||
u8 sc_token_len;
|
||||
u8 padding1;
|
||||
u8 sc_ssid[32];
|
||||
u8 sc_pwd[32];
|
||||
u8 sc_pwd[64];
|
||||
u8 sc_token[32];
|
||||
|
||||
/* smart config sync channel */
|
||||
u8 sc_sync_channel;
|
||||
u8 sc_sync_band;
|
||||
u8 padding2[2];
|
||||
|
||||
/* radar detect */
|
||||
u8 radar_channel;
|
||||
u8 radar_type;
|
||||
|
||||
u8 padding3[2];
|
||||
} __packed;
|
||||
|
||||
int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
|
||||
|
@ -655,7 +655,7 @@ static const struct wl18xx_clk_cfg wl18xx_clk_table[NUM_CLOCK_CONFIGS] = {
|
||||
};
|
||||
|
||||
/* TODO: maybe move to a new header file? */
|
||||
#define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw-3.bin"
|
||||
#define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw-4.bin"
|
||||
|
||||
static int wl18xx_identify_chip(struct wl1271 *wl)
|
||||
{
|
||||
@ -990,6 +990,7 @@ static int wl18xx_boot(struct wl1271 *wl)
|
||||
|
||||
wl->event_mask = BSS_LOSS_EVENT_ID |
|
||||
SCAN_COMPLETE_EVENT_ID |
|
||||
RADAR_DETECTED_EVENT_ID |
|
||||
RSSI_SNR_TRIGGER_0_EVENT_ID |
|
||||
PERIODIC_SCAN_COMPLETE_EVENT_ID |
|
||||
PERIODIC_SCAN_REPORT_EVENT_ID |
|
||||
@ -1703,6 +1704,7 @@ static struct wlcore_ops wl18xx_ops = {
|
||||
.interrupt_notify = wl18xx_acx_interrupt_notify_config,
|
||||
.rx_ba_filter = wl18xx_acx_rx_ba_filter,
|
||||
.ap_sleep = wl18xx_acx_ap_sleep,
|
||||
.set_cac = wl18xx_cmd_set_cac,
|
||||
};
|
||||
|
||||
/* HT cap appropriate for wide channels in 2Ghz */
|
||||
|
@ -26,10 +26,10 @@
|
||||
|
||||
/* minimum FW required for driver */
|
||||
#define WL18XX_CHIP_VER 8
|
||||
#define WL18XX_IFTYPE_VER 8
|
||||
#define WL18XX_IFTYPE_VER 9
|
||||
#define WL18XX_MAJOR_VER WLCORE_FW_VER_IGNORE
|
||||
#define WL18XX_SUBTYPE_VER WLCORE_FW_VER_IGNORE
|
||||
#define WL18XX_MINOR_VER 13
|
||||
#define WL18XX_MINOR_VER 11
|
||||
|
||||
#define WL18XX_CMD_MAX_SIZE 740
|
||||
|
||||
|
@ -403,7 +403,7 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
|
||||
WARN_ON_ONCE(wl->active_link_count < 0);
|
||||
}
|
||||
|
||||
static u8 wlcore_get_native_channel_type(u8 nl_channel_type)
|
||||
u8 wlcore_get_native_channel_type(u8 nl_channel_type)
|
||||
{
|
||||
switch (nl_channel_type) {
|
||||
case NL80211_CHAN_NO_HT:
|
||||
@ -419,6 +419,7 @@ static u8 wlcore_get_native_channel_type(u8 nl_channel_type)
|
||||
return WLCORE_CHAN_NO_HT;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wlcore_get_native_channel_type);
|
||||
|
||||
static int wl12xx_cmd_role_start_dev(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
|
@ -105,6 +105,7 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid);
|
||||
int wlcore_cmd_wait_for_event_or_timeout(struct wl1271 *wl,
|
||||
u32 mask, bool *timeout);
|
||||
u8 wlcore_get_native_channel_type(u8 nl_channel_type);
|
||||
|
||||
enum wl1271_commands {
|
||||
CMD_INTERROGATE = 1, /* use this to read information elements */
|
||||
@ -172,6 +173,11 @@ enum wl1271_commands {
|
||||
CMD_SMART_CONFIG_STOP = 62,
|
||||
CMD_SMART_CONFIG_SET_GROUP_KEY = 63,
|
||||
|
||||
CMD_CAC_START = 64,
|
||||
CMD_CAC_STOP = 65,
|
||||
CMD_DFS_MASTER_RESTART = 66,
|
||||
CMD_DFS_RADAR_DETECTION_DEBUG = 67,
|
||||
|
||||
MAX_COMMAND_ID = 0xFFFF,
|
||||
};
|
||||
|
||||
|
@ -311,4 +311,13 @@ wlcore_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
|
||||
|
||||
return wl->ops->smart_config_set_group_key(wl, group_id, key_len, key);
|
||||
}
|
||||
|
||||
static inline int
|
||||
wlcore_hw_set_cac(struct wl1271 *wl, struct wl12xx_vif *wlvif, bool start)
|
||||
{
|
||||
if (!wl->ops->set_cac)
|
||||
return -EINVAL;
|
||||
|
||||
return wl->ops->set_cac(wl, wlvif, start);
|
||||
}
|
||||
#endif
|
||||
|
@ -4629,10 +4629,46 @@ static void wlcore_op_change_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
u32 changed)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
struct wl12xx_vif *wlvif;
|
||||
int ret;
|
||||
int channel = ieee80211_frequency_to_channel(
|
||||
ctx->def.chan->center_freq);
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211,
|
||||
"mac80211 change chanctx %d (type %d) changed 0x%x",
|
||||
ieee80211_frequency_to_channel(ctx->def.chan->center_freq),
|
||||
cfg80211_get_chandef_type(&ctx->def), changed);
|
||||
channel, cfg80211_get_chandef_type(&ctx->def), changed);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
wl12xx_for_each_wlvif(wl, wlvif) {
|
||||
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
|
||||
|
||||
rcu_read_lock();
|
||||
if (rcu_access_pointer(vif->chanctx_conf) != ctx) {
|
||||
rcu_read_unlock();
|
||||
continue;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
/* start radar if needed */
|
||||
if (changed & IEEE80211_CHANCTX_CHANGE_RADAR &&
|
||||
wlvif->bss_type == BSS_TYPE_AP_BSS &&
|
||||
ctx->radar_enabled && !wlvif->radar_enabled &&
|
||||
ctx->def.chan->dfs_state == NL80211_DFS_USABLE) {
|
||||
wl1271_debug(DEBUG_MAC80211, "Start radar detection");
|
||||
wlcore_hw_set_cac(wl, wlvif, true);
|
||||
wlvif->radar_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
static int wlcore_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
@ -4643,13 +4679,26 @@ static int wlcore_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
|
||||
int channel = ieee80211_frequency_to_channel(
|
||||
ctx->def.chan->center_freq);
|
||||
int ret = -EINVAL;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211,
|
||||
"mac80211 assign chanctx (role %d) %d (type %d)",
|
||||
wlvif->role_id, channel, cfg80211_get_chandef_type(&ctx->def));
|
||||
"mac80211 assign chanctx (role %d) %d (type %d) (radar %d dfs_state %d)",
|
||||
wlvif->role_id, channel,
|
||||
cfg80211_get_chandef_type(&ctx->def),
|
||||
ctx->radar_enabled, ctx->def.chan->dfs_state);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
if (unlikely(!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
wlvif->band = ctx->def.chan->band;
|
||||
wlvif->channel = channel;
|
||||
wlvif->channel_type = cfg80211_get_chandef_type(&ctx->def);
|
||||
@ -4657,6 +4706,15 @@ static int wlcore_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
/* update default rates according to the band */
|
||||
wl1271_set_band_rate(wl, wlvif);
|
||||
|
||||
if (ctx->radar_enabled &&
|
||||
ctx->def.chan->dfs_state == NL80211_DFS_USABLE) {
|
||||
wl1271_debug(DEBUG_MAC80211, "Start radar detection");
|
||||
wlcore_hw_set_cac(wl, wlvif, true);
|
||||
wlvif->radar_enabled = true;
|
||||
}
|
||||
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
return 0;
|
||||
@ -4668,6 +4726,7 @@ static void wlcore_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211,
|
||||
"mac80211 unassign chanctx (role %d) %d (type %d)",
|
||||
@ -4676,6 +4735,97 @@ static void wlcore_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
cfg80211_get_chandef_type(&ctx->def));
|
||||
|
||||
wl1271_tx_flush(wl);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
if (unlikely(!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (wlvif->radar_enabled) {
|
||||
wl1271_debug(DEBUG_MAC80211, "Stop radar detection");
|
||||
wlcore_hw_set_cac(wl, wlvif, false);
|
||||
wlvif->radar_enabled = false;
|
||||
}
|
||||
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
static int __wlcore_switch_vif_chan(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
struct ieee80211_chanctx_conf *new_ctx)
|
||||
{
|
||||
int channel = ieee80211_frequency_to_channel(
|
||||
new_ctx->def.chan->center_freq);
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211,
|
||||
"switch vif (role %d) %d -> %d chan_type: %d",
|
||||
wlvif->role_id, wlvif->channel, channel,
|
||||
cfg80211_get_chandef_type(&new_ctx->def));
|
||||
|
||||
if (WARN_ON_ONCE(wlvif->bss_type != BSS_TYPE_AP_BSS))
|
||||
return 0;
|
||||
|
||||
if (wlvif->radar_enabled) {
|
||||
wl1271_debug(DEBUG_MAC80211, "Stop radar detection");
|
||||
wlcore_hw_set_cac(wl, wlvif, false);
|
||||
wlvif->radar_enabled = false;
|
||||
}
|
||||
|
||||
wlvif->band = new_ctx->def.chan->band;
|
||||
wlvif->channel = channel;
|
||||
wlvif->channel_type = cfg80211_get_chandef_type(&new_ctx->def);
|
||||
|
||||
/* start radar if needed */
|
||||
if (new_ctx->radar_enabled) {
|
||||
wl1271_debug(DEBUG_MAC80211, "Start radar detection");
|
||||
wlcore_hw_set_cac(wl, wlvif, true);
|
||||
wlvif->radar_enabled = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
wlcore_op_switch_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif_chanctx_switch *vifs,
|
||||
int n_vifs,
|
||||
enum ieee80211_chanctx_switch_mode mode)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
int i, ret;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211,
|
||||
"mac80211 switch chanctx n_vifs %d mode %d",
|
||||
n_vifs, mode);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < n_vifs; i++) {
|
||||
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vifs[i].vif);
|
||||
|
||||
ret = __wlcore_switch_vif_chan(wl, wlvif, vifs[i].new_ctx);
|
||||
if (ret)
|
||||
goto out_sleep;
|
||||
}
|
||||
out_sleep:
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_op_conf_tx(struct ieee80211_hw *hw,
|
||||
@ -5665,6 +5815,7 @@ static const struct ieee80211_ops wl1271_ops = {
|
||||
.change_chanctx = wlcore_op_change_chanctx,
|
||||
.assign_vif_chanctx = wlcore_op_assign_vif_chanctx,
|
||||
.unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx,
|
||||
.switch_vif_chanctx = wlcore_op_switch_vif_chanctx,
|
||||
.sta_rc_update = wlcore_op_sta_rc_update,
|
||||
.get_rssi = wlcore_op_get_rssi,
|
||||
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
|
||||
|
@ -123,6 +123,8 @@ struct wlcore_ops {
|
||||
int (*smart_config_stop)(struct wl1271 *wl);
|
||||
int (*smart_config_set_group_key)(struct wl1271 *wl, u16 group_id,
|
||||
u8 key_len, u8 *key);
|
||||
int (*set_cac)(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
bool start);
|
||||
};
|
||||
|
||||
enum wlcore_partitions {
|
||||
|
@ -434,6 +434,8 @@ struct wl12xx_vif {
|
||||
|
||||
bool wmm_enabled;
|
||||
|
||||
bool radar_enabled;
|
||||
|
||||
/* Rx Streaming */
|
||||
struct work_struct rx_streaming_enable_work;
|
||||
struct work_struct rx_streaming_disable_work;
|
||||
|
Loading…
Reference in New Issue
Block a user