aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex
diff options
context:
space:
mode:
authorAvinash Patil <patila@marvell.com>2015-01-28 05:24:21 -0500
committerKalle Valo <kvalo@codeaurora.org>2015-01-29 03:22:04 -0500
commit85afb18621be393f925ed85f96a80d52e3706578 (patch)
tree25c21a44942447a0b05519b07b19b4c1d1f2eeae /drivers/net/wireless/mwifiex
parent2ade5667e2e0244549818f16e2520141661e8bcd (diff)
mwifiex: add cfg80211 start_radar_detection handler
This patch adds support for cfg80211 start_radar_detection handler. Upon reception of start_radar_detection, driver prepares radar detect command to FW. Delayed work is queued for CAC time which sends radar detection finished event to cfg80211. 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>
Diffstat (limited to 'drivers/net/wireless/mwifiex')
-rw-r--r--drivers/net/wireless/mwifiex/11h.c66
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c59
-rw-r--r--drivers/net/wireless/mwifiex/decl.h6
-rw-r--r--drivers/net/wireless/mwifiex/fw.h13
-rw-r--r--drivers/net/wireless/mwifiex/init.c1
-rw-r--r--drivers/net/wireless/mwifiex/main.h10
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c4
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c2
-rw-r--r--drivers/net/wireless/mwifiex/uap_cmd.c5
9 files changed, 166 insertions, 0 deletions
diff --git a/drivers/net/wireless/mwifiex/11h.c b/drivers/net/wireless/mwifiex/11h.c
index f23b647a1411..8832c83816ee 100644
--- a/drivers/net/wireless/mwifiex/11h.c
+++ b/drivers/net/wireless/mwifiex/11h.c
@@ -99,3 +99,69 @@ void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer,
99 bss_desc->cap_info_bitmap &= ~WLAN_CAPABILITY_SPECTRUM_MGMT; 99 bss_desc->cap_info_bitmap &= ~WLAN_CAPABILITY_SPECTRUM_MGMT;
100 } 100 }
101} 101}
102
103/* This is DFS CAC work queue function.
104 * This delayed work emits CAC finished event for cfg80211 if
105 * CAC was started earlier.
106 */
107void mwifiex_dfs_cac_work_queue(struct work_struct *work)
108{
109 struct cfg80211_chan_def chandef;
110 struct delayed_work *delayed_work =
111 container_of(work, struct delayed_work, work);
112 struct mwifiex_private *priv =
113 container_of(delayed_work, struct mwifiex_private,
114 dfs_cac_work);
115
116 if (WARN_ON(!priv))
117 return;
118
119 chandef = priv->dfs_chandef;
120 if (priv->wdev.cac_started) {
121 dev_dbg(priv->adapter->dev,
122 "CAC timer finished; No radar detected\n");
123 cfg80211_cac_event(priv->netdev, &chandef,
124 NL80211_RADAR_CAC_FINISHED,
125 GFP_KERNEL);
126 }
127}
128
129/* This function prepares channel report request command to FW for
130 * starting radar detection.
131 */
132int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
133 struct host_cmd_ds_command *cmd,
134 void *data_buf)
135{
136 struct host_cmd_ds_chan_rpt_req *cr_req = &cmd->params.chan_rpt_req;
137 struct mwifiex_radar_params *radar_params = (void *)data_buf;
138
139 cmd->command = cpu_to_le16(HostCmd_CMD_CHAN_REPORT_REQUEST);
140 cmd->size = cpu_to_le16(S_DS_GEN);
141 le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_chan_rpt_req));
142
143 cr_req->chan_desc.start_freq = cpu_to_le16(MWIFIEX_A_BAND_START_FREQ);
144 cr_req->chan_desc.chan_num = radar_params->chandef->chan->hw_value;
145 cr_req->chan_desc.chan_width = radar_params->chandef->width;
146 cr_req->msec_dwell_time = cpu_to_le32(radar_params->cac_time_ms);
147
148 dev_dbg(priv->adapter->dev,
149 "11h: issuing DFS Radar check for channel=%d\n",
150 radar_params->chandef->chan->hw_value);
151
152 return 0;
153}
154
155/* This function is to abort ongoing CAC upon stopping AP operations
156 * or during unload.
157 */
158void mwifiex_abort_cac(struct mwifiex_private *priv)
159{
160 if (priv->wdev.cac_started) {
161 dev_dbg(priv->adapter->dev,
162 "Aborting delayed work for CAC.\n");
163 cancel_delayed_work_sync(&priv->dfs_cac_work);
164 cfg80211_cac_event(priv->netdev, &priv->dfs_chandef,
165 NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
166 }
167}
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 2e0834ca1cc0..7a969fd2f0cd 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1651,6 +1651,8 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1651{ 1651{
1652 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); 1652 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1653 1653
1654 mwifiex_abort_cac(priv);
1655
1654 if (mwifiex_del_mgmt_ies(priv)) 1656 if (mwifiex_del_mgmt_ies(priv))
1655 wiphy_err(wiphy, "Failed to delete mgmt IEs!\n"); 1657 wiphy_err(wiphy, "Failed to delete mgmt IEs!\n");
1656 1658
@@ -2383,6 +2385,7 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,
2383 ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; 2385 ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
2384} 2386}
2385 2387
2388#define MWIFIEX_MAX_WQ_LEN 30
2386/* 2389/*
2387 * create a new virtual interface with the given name 2390 * create a new virtual interface with the given name
2388 */ 2391 */
@@ -2396,6 +2399,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
2396 struct mwifiex_private *priv; 2399 struct mwifiex_private *priv;
2397 struct net_device *dev; 2400 struct net_device *dev;
2398 void *mdev_priv; 2401 void *mdev_priv;
2402 char dfs_cac_str[MWIFIEX_MAX_WQ_LEN];
2399 2403
2400 if (!adapter) 2404 if (!adapter)
2401 return ERR_PTR(-EFAULT); 2405 return ERR_PTR(-EFAULT);
@@ -2560,6 +2564,24 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
2560 return ERR_PTR(-EFAULT); 2564 return ERR_PTR(-EFAULT);
2561 } 2565 }
2562 2566
2567 strcpy(dfs_cac_str, "MWIFIEX_DFS_CAC");
2568 strcat(dfs_cac_str, name);
2569 priv->dfs_cac_workqueue = alloc_workqueue(dfs_cac_str,
2570 WQ_HIGHPRI |
2571 WQ_MEM_RECLAIM |
2572 WQ_UNBOUND, 1);
2573 if (!priv->dfs_cac_workqueue) {
2574 wiphy_err(wiphy, "cannot register virtual network device\n");
2575 free_netdev(dev);
2576 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
2577 priv->netdev = NULL;
2578 memset(&priv->wdev, 0, sizeof(priv->wdev));
2579 priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
2580 return ERR_PTR(-ENOMEM);
2581 }
2582
2583 INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue);
2584
2563 sema_init(&priv->async_sem, 1); 2585 sema_init(&priv->async_sem, 1);
2564 2586
2565 dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); 2587 dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);
@@ -2609,6 +2631,12 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
2609 if (wdev->netdev->reg_state == NETREG_REGISTERED) 2631 if (wdev->netdev->reg_state == NETREG_REGISTERED)
2610 unregister_netdevice(wdev->netdev); 2632 unregister_netdevice(wdev->netdev);
2611 2633
2634 if (priv->dfs_cac_workqueue) {
2635 flush_workqueue(priv->dfs_cac_workqueue);
2636 destroy_workqueue(priv->dfs_cac_workqueue);
2637 priv->dfs_cac_workqueue = NULL;
2638 }
2639
2612 /* Clear the priv in adapter */ 2640 /* Clear the priv in adapter */
2613 priv->netdev->ieee80211_ptr = NULL; 2641 priv->netdev->ieee80211_ptr = NULL;
2614 priv->netdev = NULL; 2642 priv->netdev = NULL;
@@ -3088,6 +3116,36 @@ mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
3088} 3116}
3089 3117
3090static int 3118static int
3119mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
3120 struct net_device *dev,
3121 struct cfg80211_chan_def *chandef,
3122 u32 cac_time_ms)
3123{
3124 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3125 struct mwifiex_radar_params radar_params;
3126
3127 if (priv->adapter->scan_processing) {
3128 dev_err(priv->adapter->dev,
3129 "radar detection: scan already in process...\n");
3130 return -EBUSY;
3131 }
3132
3133 memset(&radar_params, 0, sizeof(struct mwifiex_radar_params));
3134 radar_params.chandef = chandef;
3135 radar_params.cac_time_ms = cac_time_ms;
3136
3137 memcpy(&priv->dfs_chandef, chandef, sizeof(priv->dfs_chandef));
3138
3139 if (mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
3140 HostCmd_ACT_GEN_SET, 0, &radar_params, true))
3141 return -1;
3142
3143 queue_delayed_work(priv->dfs_cac_workqueue, &priv->dfs_cac_work,
3144 msecs_to_jiffies(cac_time_ms));
3145 return 0;
3146}
3147
3148static int
3091mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev, 3149mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,
3092 const u8 *mac, 3150 const u8 *mac,
3093 struct station_parameters *params) 3151 struct station_parameters *params)
@@ -3151,6 +3209,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
3151 .tdls_oper = mwifiex_cfg80211_tdls_oper, 3209 .tdls_oper = mwifiex_cfg80211_tdls_oper,
3152 .add_station = mwifiex_cfg80211_add_station, 3210 .add_station = mwifiex_cfg80211_add_station,
3153 .change_station = mwifiex_cfg80211_change_station, 3211 .change_station = mwifiex_cfg80211_change_station,
3212 .start_radar_detection = mwifiex_cfg80211_start_radar_detection,
3154}; 3213};
3155 3214
3156#ifdef CONFIG_PM 3215#ifdef CONFIG_PM
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 4481ac40c3eb..68aed4e5ad83 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -108,6 +108,8 @@
108#define MWIFIEX_MAX_UAP_NUM 1 108#define MWIFIEX_MAX_UAP_NUM 1
109#define MWIFIEX_MAX_P2P_NUM 1 109#define MWIFIEX_MAX_P2P_NUM 1
110 110
111#define MWIFIEX_A_BAND_START_FREQ 5000
112
111enum mwifiex_bss_type { 113enum mwifiex_bss_type {
112 MWIFIEX_BSS_TYPE_STA = 0, 114 MWIFIEX_BSS_TYPE_STA = 0,
113 MWIFIEX_BSS_TYPE_UAP = 1, 115 MWIFIEX_BSS_TYPE_UAP = 1,
@@ -242,4 +244,8 @@ struct mwifiex_iface_comb {
242 u8 p2p_intf; 244 u8 p2p_intf;
243}; 245};
244 246
247struct mwifiex_radar_params {
248 struct cfg80211_chan_def *chandef;
249 u32 cac_time_ms;
250} __packed;
245#endif /* !_MWIFIEX_DECL_H_ */ 251#endif /* !_MWIFIEX_DECL_H_ */
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 15ad776ae08e..739151c13f15 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -336,6 +336,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
336#define HostCmd_CMD_11N_ADDBA_RSP 0x00cf 336#define HostCmd_CMD_11N_ADDBA_RSP 0x00cf
337#define HostCmd_CMD_11N_DELBA 0x00d0 337#define HostCmd_CMD_11N_DELBA 0x00d0
338#define HostCmd_CMD_RECONFIGURE_TX_BUFF 0x00d9 338#define HostCmd_CMD_RECONFIGURE_TX_BUFF 0x00d9
339#define HostCmd_CMD_CHAN_REPORT_REQUEST 0x00dd
339#define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df 340#define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df
340#define HostCmd_CMD_TXPWR_CFG 0x00d1 341#define HostCmd_CMD_TXPWR_CFG 0x00d1
341#define HostCmd_CMD_TX_RATE_CFG 0x00d6 342#define HostCmd_CMD_TX_RATE_CFG 0x00d6
@@ -1216,6 +1217,17 @@ struct host_cmd_ds_tdls_oper {
1216 u8 peer_mac[ETH_ALEN]; 1217 u8 peer_mac[ETH_ALEN];
1217} __packed; 1218} __packed;
1218 1219
1220struct mwifiex_chan_desc {
1221 __le16 start_freq;
1222 u8 chan_width;
1223 u8 chan_num;
1224} __packed;
1225
1226struct host_cmd_ds_chan_rpt_req {
1227 struct mwifiex_chan_desc chan_desc;
1228 __le32 msec_dwell_time;
1229} __packed;
1230
1219struct mwifiex_fixed_bcn_param { 1231struct mwifiex_fixed_bcn_param {
1220 __le64 timestamp; 1232 __le64 timestamp;
1221 __le16 beacon_period; 1233 __le16 beacon_period;
@@ -1904,6 +1916,7 @@ struct host_cmd_ds_command {
1904 struct host_cmd_11ac_vht_cfg vht_cfg; 1916 struct host_cmd_11ac_vht_cfg vht_cfg;
1905 struct host_cmd_ds_coalesce_cfg coalesce_cfg; 1917 struct host_cmd_ds_coalesce_cfg coalesce_cfg;
1906 struct host_cmd_ds_tdls_oper tdls_oper; 1918 struct host_cmd_ds_tdls_oper tdls_oper;
1919 struct host_cmd_ds_chan_rpt_req chan_rpt_req;
1907 } params; 1920 } params;
1908} __packed; 1921} __packed;
1909 1922
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 1d1c3c8e516e..aa239a8826bc 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -681,6 +681,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
681 priv = adapter->priv[i]; 681 priv = adapter->priv[i];
682 682
683 mwifiex_clean_auto_tdls(priv); 683 mwifiex_clean_auto_tdls(priv);
684 mwifiex_abort_cac(priv);
684 mwifiex_clean_txrx(priv); 685 mwifiex_clean_txrx(priv);
685 mwifiex_delete_bss_prio_tbl(priv); 686 mwifiex_delete_bss_prio_tbl(priv);
686 } 687 }
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index c5ac20da273c..e266d99ac2b2 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -588,6 +588,9 @@ struct mwifiex_private {
588 spinlock_t ack_status_lock; 588 spinlock_t ack_status_lock;
589 /** rx histogram data */ 589 /** rx histogram data */
590 struct mwifiex_histogram_data *hist_data; 590 struct mwifiex_histogram_data *hist_data;
591 struct cfg80211_chan_def dfs_chandef;
592 struct workqueue_struct *dfs_cac_workqueue;
593 struct delayed_work dfs_cac_work;
591}; 594};
592 595
593enum mwifiex_ba_status { 596enum mwifiex_ba_status {
@@ -754,6 +757,8 @@ struct mwifiex_adapter {
754 struct work_struct main_work; 757 struct work_struct main_work;
755 struct workqueue_struct *rx_workqueue; 758 struct workqueue_struct *rx_workqueue;
756 struct work_struct rx_work; 759 struct work_struct rx_work;
760 struct workqueue_struct *dfs_workqueue;
761 struct work_struct dfs_work;
757 bool rx_work_enabled; 762 bool rx_work_enabled;
758 bool rx_processing; 763 bool rx_processing;
759 bool delay_main_work; 764 bool delay_main_work;
@@ -1376,6 +1381,9 @@ void mwifiex_check_auto_tdls(unsigned long context);
1376void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac); 1381void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac);
1377void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv); 1382void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv);
1378void mwifiex_clean_auto_tdls(struct mwifiex_private *priv); 1383void mwifiex_clean_auto_tdls(struct mwifiex_private *priv);
1384int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
1385 struct host_cmd_ds_command *cmd,
1386 void *data_buf);
1379 1387
1380void mwifiex_parse_tx_status_event(struct mwifiex_private *priv, 1388void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
1381 void *event_body); 1389 void *event_body);
@@ -1383,6 +1391,8 @@ void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
1383struct sk_buff * 1391struct sk_buff *
1384mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv, 1392mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
1385 struct sk_buff *skb, u8 flag, u64 *cookie); 1393 struct sk_buff *skb, u8 flag, u64 *cookie);
1394void mwifiex_dfs_cac_work_queue(struct work_struct *work);
1395void mwifiex_abort_cac(struct mwifiex_private *priv);
1386 1396
1387void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr, 1397void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr,
1388 s8 nflr); 1398 s8 nflr);
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 92a66e8b6636..f7d204ffd6e9 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -1897,6 +1897,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
1897 case HostCmd_CMD_TDLS_OPER: 1897 case HostCmd_CMD_TDLS_OPER:
1898 ret = mwifiex_cmd_tdls_oper(priv, cmd_ptr, data_buf); 1898 ret = mwifiex_cmd_tdls_oper(priv, cmd_ptr, data_buf);
1899 break; 1899 break;
1900 case HostCmd_CMD_CHAN_REPORT_REQUEST:
1901 ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr,
1902 data_buf);
1903 break;
1900 default: 1904 default:
1901 dev_err(priv->adapter->dev, 1905 dev_err(priv->adapter->dev,
1902 "PREP_CMD: unknown cmd- %#x\n", cmd_no); 1906 "PREP_CMD: unknown cmd- %#x\n", cmd_no);
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 65d10a33eab5..39f31766812f 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -1119,6 +1119,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
1119 case HostCmd_CMD_TDLS_OPER: 1119 case HostCmd_CMD_TDLS_OPER:
1120 ret = mwifiex_ret_tdls_oper(priv, resp); 1120 ret = mwifiex_ret_tdls_oper(priv, resp);
1121 break; 1121 break;
1122 case HostCmd_CMD_CHAN_REPORT_REQUEST:
1123 break;
1122 default: 1124 default:
1123 dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", 1125 dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
1124 resp->command); 1126 resp->command);
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index baf53145207e..f5c2af01ba0a 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -761,6 +761,11 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
761 if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf)) 761 if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf))
762 return -1; 762 return -1;
763 break; 763 break;
764 case HostCmd_CMD_CHAN_REPORT_REQUEST:
765 if (mwifiex_cmd_issue_chan_report_request(priv, cmd_buf,
766 data_buf))
767 return -1;
768 break;
764 default: 769 default:
765 dev_err(priv->adapter->dev, 770 dev_err(priv->adapter->dev,
766 "PREP_CMD: unknown cmd %#x\n", cmd_no); 771 "PREP_CMD: unknown cmd %#x\n", cmd_no);