diff mbox

[v2,07/10] mwifiex: support for channel report for radar detection

Message ID 1422440665-3940-8-git-send-email-patila@marvell.com (mailing list archive)
State Accepted
Delegated to: Kalle Valo
Headers show

Commit Message

Avinash Patil Jan. 28, 2015, 10:24 a.m. UTC
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: Avinash Patil <patila@marvell.com>
Signed-off-by: Qingshui Gao <gaoqs@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
---
 drivers/net/wireless/mwifiex/11h.c       | 51 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/mwifiex/fw.h        | 23 ++++++++++++++
 drivers/net/wireless/mwifiex/main.h      |  2 ++
 drivers/net/wireless/mwifiex/sta_event.c |  5 ++++
 drivers/net/wireless/mwifiex/uap_event.c |  4 +++
 5 files changed, 85 insertions(+)
diff mbox

Patch

diff --git a/drivers/net/wireless/mwifiex/11h.c b/drivers/net/wireless/mwifiex/11h.c
index 8832c83..e44cac7 100644
--- a/drivers/net/wireless/mwifiex/11h.c
+++ b/drivers/net/wireless/mwifiex/11h.c
@@ -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;
+}
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 739151c..324ef29 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -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;
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index e266d99..281a30a 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -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);
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index c37e8cb..ad5c5e0 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -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);
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index 9b4ca6f..e0bdf6a 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -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",