Commit 0a694d68 authored by Avinash Patil's avatar Avinash Patil Committed by Kalle Valo

mwifiex: support for channel report for radar detection

This patch adds support for channel report enabling.
Channel report event happens if radar is detected on specified channel
after driver has issued radar detect command within CAC time.
Driver in turn sends RADAR_DETECTED event to cfg80211 to tell radar was
detected within CAC time.
Signed-off-by: default avatarAvinash Patil <patila@marvell.com>
Signed-off-by: default avatarQingshui Gao <gaoqs@marvell.com>
Signed-off-by: default avatarCathy Luo <cluo@marvell.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 85afb186
......@@ -165,3 +165,54 @@ void mwifiex_abort_cac(struct mwifiex_private *priv)
NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
}
}
/* This function handles channel report event from FW during CAC period.
* If radar is detected during CAC, driver indicates the same to cfg80211
* and also cancels ongoing delayed work.
*/
int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv,
struct sk_buff *skb)
{
struct host_cmd_ds_chan_rpt_event *rpt_event;
struct mwifiex_ie_types_chan_rpt_data *rpt;
u8 *evt_buf;
u16 event_len, tlv_len;
rpt_event = (void *)(skb->data + sizeof(u32));
event_len = skb->len - (sizeof(struct host_cmd_ds_chan_rpt_event)+
sizeof(u32));
if (le32_to_cpu(rpt_event->result) != HostCmd_RESULT_OK) {
dev_err(priv->adapter->dev, "Error in channel report event\n");
return -1;
}
evt_buf = (void *)&rpt_event->tlvbuf;
while (event_len >= sizeof(struct mwifiex_ie_types_header)) {
rpt = (void *)&rpt_event->tlvbuf;
tlv_len = le16_to_cpu(rpt->header.len);
switch (le16_to_cpu(rpt->header.type)) {
case TLV_TYPE_CHANRPT_11H_BASIC:
if (rpt->map.radar) {
dev_notice(priv->adapter->dev,
"RADAR Detected on channel %d!\n",
priv->dfs_chandef.chan->hw_value);
cancel_delayed_work_sync(&priv->dfs_cac_work);
cfg80211_cac_event(priv->netdev,
&priv->dfs_chandef,
NL80211_RADAR_DETECTED,
GFP_KERNEL);
}
break;
default:
break;
}
evt_buf += (tlv_len + sizeof(rpt->header));
event_len -= (tlv_len + sizeof(rpt->header));
}
return 0;
}
......@@ -158,6 +158,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84)
#define TLV_TYPE_BSS_SCAN_RSP (PROPRIETARY_TLV_BASE_ID + 86)
#define TLV_TYPE_BSS_SCAN_INFO (PROPRIETARY_TLV_BASE_ID + 87)
#define TLV_TYPE_CHANRPT_11H_BASIC (PROPRIETARY_TLV_BASE_ID + 91)
#define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93)
#define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94)
#define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104)
......@@ -494,6 +495,7 @@ enum P2P_MODES {
#define EVENT_HOSTWAKE_STAIE 0x0000004d
#define EVENT_CHANNEL_SWITCH_ANN 0x00000050
#define EVENT_TDLS_GENERIC_EVENT 0x00000052
#define EVENT_CHANNEL_REPORT_RDY 0x00000054
#define EVENT_EXT_SCAN_REPORT 0x00000058
#define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f
#define EVENT_TX_STATUS_REPORT 0x00000074
......@@ -1228,6 +1230,13 @@ struct host_cmd_ds_chan_rpt_req {
__le32 msec_dwell_time;
} __packed;
struct host_cmd_ds_chan_rpt_event {
__le32 result;
__le64 start_tsf;
__le32 duration;
u8 tlvbuf[0];
} __packed;
struct mwifiex_fixed_bcn_param {
__le64 timestamp;
__le16 beacon_period;
......@@ -1804,6 +1813,20 @@ struct mwifiex_ie_types_rssi_threshold {
u8 evt_freq;
} __packed;
struct meas_rpt_map {
u8 rssi:3;
u8 unmeasured:1;
u8 radar:1;
u8 unidentified_sig:1;
u8 ofdm_preamble:1;
u8 bss:1;
} __packed;
struct mwifiex_ie_types_chan_rpt_data {
struct mwifiex_ie_types_header header;
struct meas_rpt_map map;
} __packed;
struct host_cmd_ds_802_11_subsc_evt {
__le16 action;
__le16 events;
......
......@@ -1384,6 +1384,8 @@ void mwifiex_clean_auto_tdls(struct mwifiex_private *priv);
int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
void *data_buf);
int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv,
struct sk_buff *skb);
void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
void *event_body);
......
......@@ -516,6 +516,11 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
mwifiex_parse_tx_status_event(priv, adapter->event_body);
break;
case EVENT_CHANNEL_REPORT_RDY:
dev_dbg(adapter->dev, "event: Channel Report\n");
ret = mwifiex_11h_handle_chanrpt_ready(priv,
adapter->event_skb);
break;
default:
dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
eventcause);
......
......@@ -215,7 +215,11 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
adapter->ps_state = PS_STATE_AWAKE;
adapter->pm_wakeup_card_req = false;
adapter->pm_wakeup_fw_try = false;
break;
case EVENT_CHANNEL_REPORT_RDY:
dev_dbg(adapter->dev, "event: Channel Report\n");
mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb);
break;
default:
dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment