mwifiex: support for channel report for radar detection
authorAvinash Patil <patila@marvell.com>
Wed, 28 Jan 2015 10:24:22 +0000 (15:54 +0530)
committerKalle Valo <kvalo@codeaurora.org>
Thu, 29 Jan 2015 08:22:05 +0000 (10:22 +0200)
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>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/mwifiex/11h.c
drivers/net/wireless/mwifiex/fw.h
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/sta_event.c
drivers/net/wireless/mwifiex/uap_event.c

index 8832c83816eeca1acd4ac6ab0ed8663958ac022e..e44cac72712e0632aecaed4a43c82671b12220f1 100644 (file)
@@ -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;
+}
index 739151c13f15ec0b7d6c95757039ebc43a158d4f..324ef298bea6c3b99f257e7fb347af30fad9c7a6 100644 (file)
@@ -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;
index e266d99ac2b2945f715e40b6e4ff4a1b9d5c0a12..281a30a8d857137ec78ed06914434721539b875e 100644 (file)
@@ -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);
index c37e8cb2dd32a8255de5db21d68b9c3c2e867d94..ad5c5e0deac06bd680eb189f30905340628172aa 100644 (file)
@@ -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);
index 9b4ca6ff79312de6dbbc8cb79b7305d249b603fd..e0bdf6a79916dc962613178a4599141be154ce4a 100644 (file)
@@ -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",