aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStone Piao <piaoyun@marvell.com>2012-09-25 23:23:36 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-09-28 13:54:04 -0400
commit7feb4c48313d58b445a91a598d99c025029ce00b (patch)
treeb77c5922101df50081442a96335a0730a235ca45
parent2dbaf751b1dec3a603130a475f94cc4d3f404362 (diff)
mwifiex: implement remain_on_channel and cancel_remain_on_channel
Add a new command to implement remain_on_channel and cancel_remain_on_channel. Signed-off-by: Stone Piao <piaoyun@marvell.com> Signed-off-by: Kiran Divekar <dkiran@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c82
-rw-r--r--drivers/net/wireless/mwifiex/fw.h12
-rw-r--r--drivers/net/wireless/mwifiex/init.c2
-rw-r--r--drivers/net/wireless/mwifiex/main.h15
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c8
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c19
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c29
-rw-r--r--drivers/net/wireless/mwifiex/util.c2
8 files changed, 163 insertions, 6 deletions
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index f86043df8d4d..261d7c548a5e 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -77,8 +77,7 @@ static const struct ieee80211_regdomain mwifiex_world_regdom_custom = {
77 * NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW 77 * NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW
78 * Others -> IEEE80211_HT_PARAM_CHA_SEC_NONE 78 * Others -> IEEE80211_HT_PARAM_CHA_SEC_NONE
79 */ 79 */
80static u8 80u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)
81mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)
82{ 81{
83 switch (chan_type) { 82 switch (chan_type) {
84 case NL80211_CHAN_NO_HT: 83 case NL80211_CHAN_NO_HT:
@@ -248,6 +247,79 @@ mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
248} 247}
249 248
250/* 249/*
250 * CFG802.11 operation handler to remain on channel.
251 */
252static int
253mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
254 struct wireless_dev *wdev,
255 struct ieee80211_channel *chan,
256 enum nl80211_channel_type channel_type,
257 unsigned int duration, u64 *cookie)
258{
259 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
260 int ret;
261
262 if (!chan || !cookie) {
263 wiphy_err(wiphy, "Invalid parameter for ROC\n");
264 return -EINVAL;
265 }
266
267 if (priv->roc_cfg.cookie) {
268 wiphy_dbg(wiphy, "info: ongoing ROC, cookie = 0x%llu\n",
269 priv->roc_cfg.cookie);
270 return -EBUSY;
271 }
272
273 ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan,
274 &channel_type, duration);
275
276 if (!ret) {
277 *cookie = random32() | 1;
278 priv->roc_cfg.cookie = *cookie;
279 priv->roc_cfg.chan = *chan;
280 priv->roc_cfg.chan_type = channel_type;
281
282 cfg80211_ready_on_channel(wdev, *cookie, chan, channel_type,
283 duration, GFP_ATOMIC);
284
285 wiphy_dbg(wiphy, "info: ROC, cookie = 0x%llx\n", *cookie);
286 }
287
288 return ret;
289}
290
291/*
292 * CFG802.11 operation handler to cancel remain on channel.
293 */
294static int
295mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
296 struct wireless_dev *wdev, u64 cookie)
297{
298 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
299 int ret;
300
301 if (cookie != priv->roc_cfg.cookie)
302 return -ENOENT;
303
304 ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,
305 &priv->roc_cfg.chan,
306 &priv->roc_cfg.chan_type, 0);
307
308 if (!ret) {
309 cfg80211_remain_on_channel_expired(wdev, cookie,
310 &priv->roc_cfg.chan,
311 priv->roc_cfg.chan_type,
312 GFP_ATOMIC);
313
314 memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg));
315
316 wiphy_dbg(wiphy, "info: cancel ROC, cookie = 0x%llx\n", cookie);
317 }
318
319 return ret;
320}
321
322/*
251 * CFG802.11 operation handler to set Tx power. 323 * CFG802.11 operation handler to set Tx power.
252 */ 324 */
253static int 325static int
@@ -1950,6 +2022,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
1950 .del_key = mwifiex_cfg80211_del_key, 2022 .del_key = mwifiex_cfg80211_del_key,
1951 .mgmt_tx = mwifiex_cfg80211_mgmt_tx, 2023 .mgmt_tx = mwifiex_cfg80211_mgmt_tx,
1952 .mgmt_frame_register = mwifiex_cfg80211_mgmt_frame_register, 2024 .mgmt_frame_register = mwifiex_cfg80211_mgmt_frame_register,
2025 .remain_on_channel = mwifiex_cfg80211_remain_on_channel,
2026 .cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel,
1953 .set_default_key = mwifiex_cfg80211_set_default_key, 2027 .set_default_key = mwifiex_cfg80211_set_default_key,
1954 .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, 2028 .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,
1955 .set_tx_power = mwifiex_cfg80211_set_tx_power, 2029 .set_tx_power = mwifiex_cfg80211_set_tx_power,
@@ -1987,6 +2061,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
1987 wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH; 2061 wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
1988 wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; 2062 wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
1989 wiphy->mgmt_stypes = mwifiex_mgmt_stypes; 2063 wiphy->mgmt_stypes = mwifiex_mgmt_stypes;
2064 wiphy->max_remain_on_channel_duration = 5000;
1990 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | 2065 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
1991 BIT(NL80211_IFTYPE_ADHOC) | 2066 BIT(NL80211_IFTYPE_ADHOC) |
1992 BIT(NL80211_IFTYPE_AP); 2067 BIT(NL80211_IFTYPE_AP);
@@ -2008,7 +2083,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
2008 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 2083 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
2009 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | 2084 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
2010 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | 2085 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
2011 WIPHY_FLAG_CUSTOM_REGULATORY; 2086 WIPHY_FLAG_CUSTOM_REGULATORY |
2087 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
2012 2088
2013 wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); 2089 wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom);
2014 2090
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index b587ea3feffa..9818cae7faf7 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -265,6 +265,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
265#define HostCmd_CMD_SET_BSS_MODE 0x00f7 265#define HostCmd_CMD_SET_BSS_MODE 0x00f7
266#define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa 266#define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa
267#define HostCmd_CMD_MGMT_FRAME_REG 0x010c 267#define HostCmd_CMD_MGMT_FRAME_REG 0x010c
268#define HostCmd_CMD_REMAIN_ON_CHAN 0x010d
268 269
269#define PROTOCOL_NO_SECURITY 0x01 270#define PROTOCOL_NO_SECURITY 0x01
270#define PROTOCOL_STATIC_WEP 0x02 271#define PROTOCOL_STATIC_WEP 0x02
@@ -293,6 +294,7 @@ enum ENH_PS_MODES {
293#define HostCmd_RET_BIT 0x8000 294#define HostCmd_RET_BIT 0x8000
294#define HostCmd_ACT_GEN_GET 0x0000 295#define HostCmd_ACT_GEN_GET 0x0000
295#define HostCmd_ACT_GEN_SET 0x0001 296#define HostCmd_ACT_GEN_SET 0x0001
297#define HostCmd_ACT_GEN_REMOVE 0x0004
296#define HostCmd_ACT_BITWISE_SET 0x0002 298#define HostCmd_ACT_BITWISE_SET 0x0002
297#define HostCmd_ACT_BITWISE_CLR 0x0003 299#define HostCmd_ACT_BITWISE_CLR 0x0003
298#define HostCmd_RESULT_OK 0x0000 300#define HostCmd_RESULT_OK 0x0000
@@ -1343,6 +1345,15 @@ struct host_cmd_ds_mgmt_frame_reg {
1343 __le32 mask; 1345 __le32 mask;
1344} __packed; 1346} __packed;
1345 1347
1348struct host_cmd_ds_remain_on_chan {
1349 __le16 action;
1350 u8 status;
1351 u8 reserved;
1352 u8 band_cfg;
1353 u8 channel;
1354 __le32 duration;
1355} __packed;
1356
1346struct host_cmd_ds_802_11_ibss_status { 1357struct host_cmd_ds_802_11_ibss_status {
1347 __le16 action; 1358 __le16 action;
1348 __le16 enable; 1359 __le16 enable;
@@ -1452,6 +1463,7 @@ struct host_cmd_ds_command {
1452 struct host_cmd_ds_802_11_key_material key_material; 1463 struct host_cmd_ds_802_11_key_material key_material;
1453 struct host_cmd_ds_version_ext verext; 1464 struct host_cmd_ds_version_ext verext;
1454 struct host_cmd_ds_mgmt_frame_reg reg_mask; 1465 struct host_cmd_ds_mgmt_frame_reg reg_mask;
1466 struct host_cmd_ds_remain_on_chan roc_cfg;
1455 struct host_cmd_ds_802_11_ibss_status ibss_coalescing; 1467 struct host_cmd_ds_802_11_ibss_status ibss_coalescing;
1456 struct host_cmd_ds_mac_reg_access mac_reg; 1468 struct host_cmd_ds_mac_reg_access mac_reg;
1457 struct host_cmd_ds_bbp_reg_access bbp_reg; 1469 struct host_cmd_ds_bbp_reg_access bbp_reg;
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 105a5c5d7d5d..fa96dc328a5b 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -214,7 +214,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv)
214 priv->wps_ie = NULL; 214 priv->wps_ie = NULL;
215 priv->wps_ie_len = 0; 215 priv->wps_ie_len = 0;
216 priv->ap_11n_enabled = 0; 216 priv->ap_11n_enabled = 0;
217 priv->mgmt_rx_freq = 2437; 217 memset(&priv->roc_cfg, 0, sizeof(priv->roc_cfg));
218 218
219 priv->scan_block = false; 219 priv->scan_block = false;
220 220
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index ec5794ef4366..89ba66e56143 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -370,6 +370,12 @@ struct wps {
370 u8 session_enable; 370 u8 session_enable;
371}; 371};
372 372
373struct mwifiex_roc_cfg {
374 u64 cookie;
375 struct ieee80211_channel chan;
376 enum nl80211_channel_type chan_type;
377};
378
373struct mwifiex_adapter; 379struct mwifiex_adapter;
374struct mwifiex_private; 380struct mwifiex_private;
375 381
@@ -497,7 +503,7 @@ struct mwifiex_private {
497 struct timer_list scan_delay_timer; 503 struct timer_list scan_delay_timer;
498 u8 ap_11n_enabled; 504 u8 ap_11n_enabled;
499 u32 mgmt_frame_mask; 505 u32 mgmt_frame_mask;
500 u32 mgmt_rx_freq; 506 struct mwifiex_roc_cfg roc_cfg;
501}; 507};
502 508
503enum mwifiex_ba_status { 509enum mwifiex_ba_status {
@@ -1007,6 +1013,11 @@ int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len);
1007 1013
1008int mwifiex_get_ver_ext(struct mwifiex_private *priv); 1014int mwifiex_get_ver_ext(struct mwifiex_private *priv);
1009 1015
1016int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
1017 struct ieee80211_channel *chan,
1018 enum nl80211_channel_type *channel_type,
1019 unsigned int duration);
1020
1010int mwifiex_get_stats_info(struct mwifiex_private *priv, 1021int mwifiex_get_stats_info(struct mwifiex_private *priv,
1011 struct mwifiex_ds_get_stats *log); 1022 struct mwifiex_ds_get_stats *log);
1012 1023
@@ -1049,6 +1060,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1049int mwifiex_check_network_compatibility(struct mwifiex_private *priv, 1060int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
1050 struct mwifiex_bssdescriptor *bss_desc); 1061 struct mwifiex_bssdescriptor *bss_desc);
1051 1062
1063u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type);
1064
1052struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, 1065struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
1053 const char *name, 1066 const char *name,
1054 enum nl80211_iftype type, 1067 enum nl80211_iftype type,
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index dc4fe8c320fd..025244639bfc 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -1176,6 +1176,14 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
1176 S_DS_GEN); 1176 S_DS_GEN);
1177 ret = 0; 1177 ret = 0;
1178 break; 1178 break;
1179 case HostCmd_CMD_REMAIN_ON_CHAN:
1180 cmd_ptr->command = cpu_to_le16(cmd_no);
1181 memcpy(&cmd_ptr->params, data_buf,
1182 sizeof(struct host_cmd_ds_remain_on_chan));
1183 cmd_ptr->size =
1184 cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) +
1185 S_DS_GEN);
1186 break;
1179 case HostCmd_CMD_FUNC_INIT: 1187 case HostCmd_CMD_FUNC_INIT:
1180 if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET) 1188 if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET)
1181 priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY; 1189 priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY;
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index d1f53e39028f..621d36e437f5 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -654,6 +654,22 @@ static int mwifiex_ret_ver_ext(struct mwifiex_private *priv,
654} 654}
655 655
656/* 656/*
657 * This function handles the command response of remain on channel.
658 */
659static int
660mwifiex_ret_remain_on_chan(struct mwifiex_private *priv,
661 struct host_cmd_ds_command *resp,
662 struct host_cmd_ds_remain_on_chan *roc_cfg)
663{
664 struct host_cmd_ds_remain_on_chan *resp_cfg = &resp->params.roc_cfg;
665
666 if (roc_cfg)
667 memcpy(roc_cfg, resp_cfg, sizeof(*roc_cfg));
668
669 return 0;
670}
671
672/*
657 * This function handles the command response of register access. 673 * This function handles the command response of register access.
658 * 674 *
659 * The register value and offset are returned to the user. For EEPROM 675 * The register value and offset are returned to the user. For EEPROM
@@ -875,6 +891,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
875 case HostCmd_CMD_VERSION_EXT: 891 case HostCmd_CMD_VERSION_EXT:
876 ret = mwifiex_ret_ver_ext(priv, resp, data_buf); 892 ret = mwifiex_ret_ver_ext(priv, resp, data_buf);
877 break; 893 break;
894 case HostCmd_CMD_REMAIN_ON_CHAN:
895 ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf);
896 break;
878 case HostCmd_CMD_MGMT_FRAME_REG: 897 case HostCmd_CMD_MGMT_FRAME_REG:
879 case HostCmd_CMD_FUNC_INIT: 898 case HostCmd_CMD_FUNC_INIT:
880 case HostCmd_CMD_FUNC_SHUTDOWN: 899 case HostCmd_CMD_FUNC_SHUTDOWN:
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 731562f026f5..fd09a21b8824 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -1043,6 +1043,35 @@ mwifiex_get_ver_ext(struct mwifiex_private *priv)
1043 return 0; 1043 return 0;
1044} 1044}
1045 1045
1046int
1047mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
1048 struct ieee80211_channel *chan,
1049 enum nl80211_channel_type *ct,
1050 unsigned int duration)
1051{
1052 struct host_cmd_ds_remain_on_chan roc_cfg;
1053 u8 sc;
1054
1055 memset(&roc_cfg, 0, sizeof(roc_cfg));
1056 roc_cfg.action = cpu_to_le16(action);
1057 if (action == HostCmd_ACT_GEN_SET) {
1058 roc_cfg.band_cfg = chan->band;
1059 sc = mwifiex_chan_type_to_sec_chan_offset(*ct);
1060 roc_cfg.band_cfg |= (sc << 2);
1061
1062 roc_cfg.channel =
1063 ieee80211_frequency_to_channel(chan->center_freq);
1064 roc_cfg.duration = cpu_to_le32(duration);
1065 }
1066 if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_REMAIN_ON_CHAN,
1067 action, 0, &roc_cfg)) {
1068 dev_err(priv->adapter->dev, "failed to remain on channel\n");
1069 return -1;
1070 }
1071
1072 return roc_cfg.status;
1073}
1074
1046/* 1075/*
1047 * Sends IOCTL request to get statistics information. 1076 * Sends IOCTL request to get statistics information.
1048 * 1077 *
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index e1dc3e41c65d..ae88f80cf86b 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -174,7 +174,7 @@ mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter,
174 pkt_len -= ETH_ALEN + sizeof(pkt_len); 174 pkt_len -= ETH_ALEN + sizeof(pkt_len);
175 rx_pd->rx_pkt_length = cpu_to_le16(pkt_len); 175 rx_pd->rx_pkt_length = cpu_to_le16(pkt_len);
176 176
177 cfg80211_rx_mgmt(priv->wdev, priv->mgmt_rx_freq, 177 cfg80211_rx_mgmt(priv->wdev, priv->roc_cfg.chan.center_freq,
178 CAL_RSSI(rx_pd->snr, rx_pd->nf), 178 CAL_RSSI(rx_pd->snr, rx_pd->nf),
179 skb->data, pkt_len, GFP_ATOMIC); 179 skb->data, pkt_len, GFP_ATOMIC);
180 180