aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c25
-rw-r--r--drivers/net/wireless/mwifiex/fw.h5
-rw-r--r--drivers/net/wireless/mwifiex/main.h1
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c71
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c13
-rw-r--r--drivers/net/wireless/mwifiex/tdls.c23
6 files changed, 137 insertions, 1 deletions
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index cac8aea69ce5..436ba437a4ba 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -2734,6 +2734,30 @@ mwifiex_cfg80211_add_station(struct wiphy *wiphy,
2734 return mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CREATE_LINK); 2734 return mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CREATE_LINK);
2735} 2735}
2736 2736
2737static int
2738mwifiex_cfg80211_change_station(struct wiphy *wiphy,
2739 struct net_device *dev,
2740 u8 *mac, struct station_parameters *params)
2741{
2742 int ret;
2743 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
2744
2745 /* we support change_station handler only for TDLS peers*/
2746 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
2747 return -ENOTSUPP;
2748
2749 /* make sure we are in station mode and connected */
2750 if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)
2751 return -ENOTSUPP;
2752
2753 priv->sta_params = params;
2754
2755 ret = mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CONFIG_LINK);
2756 priv->sta_params = NULL;
2757
2758 return ret;
2759}
2760
2737/* station cfg80211 operations */ 2761/* station cfg80211 operations */
2738static struct cfg80211_ops mwifiex_cfg80211_ops = { 2762static struct cfg80211_ops mwifiex_cfg80211_ops = {
2739 .add_virtual_intf = mwifiex_add_virtual_intf, 2763 .add_virtual_intf = mwifiex_add_virtual_intf,
@@ -2772,6 +2796,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
2772 .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt, 2796 .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt,
2773 .tdls_oper = mwifiex_cfg80211_tdls_oper, 2797 .tdls_oper = mwifiex_cfg80211_tdls_oper,
2774 .add_station = mwifiex_cfg80211_add_station, 2798 .add_station = mwifiex_cfg80211_add_station,
2799 .change_station = mwifiex_cfg80211_change_station,
2775}; 2800};
2776 2801
2777#ifdef CONFIG_PM 2802#ifdef CONFIG_PM
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 3180fc6b7c6d..8c119bc93899 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -1391,6 +1391,11 @@ struct mwifiex_ie_types_extcap {
1391 u8 ext_capab[0]; 1391 u8 ext_capab[0];
1392} __packed; 1392} __packed;
1393 1393
1394struct mwifiex_ie_types_qos_info {
1395 struct mwifiex_ie_types_header header;
1396 u8 qos_info;
1397} __packed;
1398
1394struct host_cmd_ds_mac_reg_access { 1399struct host_cmd_ds_mac_reg_access {
1395 __le16 action; 1400 __le16 action;
1396 __le16 offset; 1401 __le16 offset;
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index d35c9950efba..c8c30a4c9a73 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -529,6 +529,7 @@ struct mwifiex_private {
529 unsigned long csa_expire_time; 529 unsigned long csa_expire_time;
530 u8 del_list_idx; 530 u8 del_list_idx;
531 bool hs2_enabled; 531 bool hs2_enabled;
532 struct station_parameters *sta_params;
532}; 533};
533 534
534enum mwifiex_ba_status { 535enum mwifiex_ba_status {
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 1e36fa7a6463..8f1bcc3255dd 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -1288,14 +1288,24 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
1288 struct host_cmd_ds_tdls_oper *tdls_oper = &cmd->params.tdls_oper; 1288 struct host_cmd_ds_tdls_oper *tdls_oper = &cmd->params.tdls_oper;
1289 struct mwifiex_ds_tdls_oper *oper = data_buf; 1289 struct mwifiex_ds_tdls_oper *oper = data_buf;
1290 struct mwifiex_sta_node *sta_ptr; 1290 struct mwifiex_sta_node *sta_ptr;
1291 struct host_cmd_tlv_rates *tlv_rates;
1292 struct mwifiex_ie_types_htcap *ht_capab;
1293 struct mwifiex_ie_types_qos_info *wmm_qos_info;
1294 struct mwifiex_ie_types_extcap *extcap;
1295 u8 *pos, qos_info;
1296 u16 config_len = 0;
1297 struct station_parameters *params = priv->sta_params;
1291 1298
1292 cmd->command = cpu_to_le16(HostCmd_CMD_TDLS_OPER); 1299 cmd->command = cpu_to_le16(HostCmd_CMD_TDLS_OPER);
1293 cmd->size = cpu_to_le16(S_DS_GEN); 1300 cmd->size = cpu_to_le16(S_DS_GEN);
1301 le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_tdls_oper));
1294 1302
1295 tdls_oper->reason = 0; 1303 tdls_oper->reason = 0;
1296 memcpy(tdls_oper->peer_mac, oper->peer_mac, ETH_ALEN); 1304 memcpy(tdls_oper->peer_mac, oper->peer_mac, ETH_ALEN);
1297 sta_ptr = mwifiex_get_sta_entry(priv, oper->peer_mac); 1305 sta_ptr = mwifiex_get_sta_entry(priv, oper->peer_mac);
1298 1306
1307 pos = (u8 *)tdls_oper + sizeof(struct host_cmd_ds_tdls_oper);
1308
1299 switch (oper->tdls_action) { 1309 switch (oper->tdls_action) {
1300 case MWIFIEX_TDLS_DISABLE_LINK: 1310 case MWIFIEX_TDLS_DISABLE_LINK:
1301 tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_DELETE); 1311 tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_DELETE);
@@ -1303,12 +1313,71 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
1303 case MWIFIEX_TDLS_CREATE_LINK: 1313 case MWIFIEX_TDLS_CREATE_LINK:
1304 tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CREATE); 1314 tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CREATE);
1305 break; 1315 break;
1316 case MWIFIEX_TDLS_CONFIG_LINK:
1317 tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CONFIG);
1318
1319 if (!params) {
1320 dev_err(priv->adapter->dev,
1321 "TDLS config params not available for %pM\n",
1322 oper->peer_mac);
1323 return -ENODATA;
1324 }
1325
1326 *(__le16 *)pos = cpu_to_le16(params->capability);
1327 config_len += sizeof(params->capability);
1328
1329 qos_info = params->uapsd_queues | (params->max_sp << 5);
1330 wmm_qos_info = (struct mwifiex_ie_types_qos_info *)(pos +
1331 config_len);
1332 wmm_qos_info->header.type = cpu_to_le16(WLAN_EID_QOS_CAPA);
1333 wmm_qos_info->header.len = cpu_to_le16(sizeof(qos_info));
1334 wmm_qos_info->qos_info = qos_info;
1335 config_len += sizeof(struct mwifiex_ie_types_qos_info);
1336
1337 if (params->ht_capa) {
1338 ht_capab = (struct mwifiex_ie_types_htcap *)(pos +
1339 config_len);
1340 ht_capab->header.type =
1341 cpu_to_le16(WLAN_EID_HT_CAPABILITY);
1342 ht_capab->header.len =
1343 cpu_to_le16(sizeof(struct ieee80211_ht_cap));
1344 memcpy(&ht_capab->ht_cap, params->ht_capa,
1345 sizeof(struct ieee80211_ht_cap));
1346 config_len += sizeof(struct mwifiex_ie_types_htcap);
1347 }
1348
1349 if (params->supported_rates && params->supported_rates_len) {
1350 tlv_rates = (struct host_cmd_tlv_rates *)(pos +
1351 config_len);
1352 tlv_rates->header.type =
1353 cpu_to_le16(WLAN_EID_SUPP_RATES);
1354 tlv_rates->header.len =
1355 cpu_to_le16(params->supported_rates_len);
1356 memcpy(tlv_rates->rates, params->supported_rates,
1357 params->supported_rates_len);
1358 config_len += sizeof(struct host_cmd_tlv_rates) +
1359 params->supported_rates_len;
1360 }
1361
1362 if (params->ext_capab && params->ext_capab_len) {
1363 extcap = (struct mwifiex_ie_types_extcap *)(pos +
1364 config_len);
1365 extcap->header.type =
1366 cpu_to_le16(WLAN_EID_EXT_CAPABILITY);
1367 extcap->header.len = cpu_to_le16(params->ext_capab_len);
1368 memcpy(extcap->ext_capab, params->ext_capab,
1369 params->ext_capab_len);
1370 config_len += sizeof(struct mwifiex_ie_types_extcap) +
1371 params->ext_capab_len;
1372 }
1373
1374 break;
1306 default: 1375 default:
1307 dev_err(priv->adapter->dev, "Unknown TDLS operation\n"); 1376 dev_err(priv->adapter->dev, "Unknown TDLS operation\n");
1308 return -ENOTSUPP; 1377 return -ENOTSUPP;
1309 } 1378 }
1310 1379
1311 le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_tdls_oper)); 1380 le16_add_cpu(&cmd->size, config_len);
1312 1381
1313 return 0; 1382 return 0;
1314} 1383}
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 396b93682bd8..48abab6bfce9 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -834,6 +834,19 @@ static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv,
834 cmd_tdls_oper->peer_mac); 834 cmd_tdls_oper->peer_mac);
835 } 835 }
836 break; 836 break;
837 case ACT_TDLS_CONFIG:
838 if (reason) {
839 dev_err(priv->adapter->dev,
840 "TDLS link config for %pM failed, reason %d\n",
841 cmd_tdls_oper->peer_mac, reason);
842 if (node)
843 node->tdls_status = TDLS_SETUP_FAILURE;
844 } else {
845 dev_dbg(priv->adapter->dev,
846 "TDLS link config for %pM successful\n",
847 cmd_tdls_oper->peer_mac);
848 }
849 break;
837 default: 850 default:
838 dev_err(priv->adapter->dev, 851 dev_err(priv->adapter->dev,
839 "Unknown TDLS command action respnse %d", action); 852 "Unknown TDLS command action respnse %d", action);
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c
index 1d5ed70432d6..f37862b5fabb 100644
--- a/drivers/net/wireless/mwifiex/tdls.c
+++ b/drivers/net/wireless/mwifiex/tdls.c
@@ -544,6 +544,27 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
544} 544}
545 545
546static int 546static int
547mwifiex_tdls_process_config_link(struct mwifiex_private *priv, u8 *peer)
548{
549 struct mwifiex_sta_node *sta_ptr;
550 struct mwifiex_ds_tdls_oper tdls_oper;
551
552 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
553 sta_ptr = mwifiex_get_sta_entry(priv, peer);
554
555 if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) {
556 dev_err(priv->adapter->dev,
557 "link absent for peer %pM; cannot config\n", peer);
558 return -EINVAL;
559 }
560
561 memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
562 tdls_oper.tdls_action = MWIFIEX_TDLS_CONFIG_LINK;
563 return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TDLS_OPER,
564 HostCmd_ACT_GEN_SET, 0, &tdls_oper);
565}
566
567static int
547mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer) 568mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer)
548{ 569{
549 struct mwifiex_sta_node *sta_ptr; 570 struct mwifiex_sta_node *sta_ptr;
@@ -662,6 +683,8 @@ int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action)
662 return mwifiex_tdls_process_disable_link(priv, peer); 683 return mwifiex_tdls_process_disable_link(priv, peer);
663 case MWIFIEX_TDLS_CREATE_LINK: 684 case MWIFIEX_TDLS_CREATE_LINK:
664 return mwifiex_tdls_process_create_link(priv, peer); 685 return mwifiex_tdls_process_create_link(priv, peer);
686 case MWIFIEX_TDLS_CONFIG_LINK:
687 return mwifiex_tdls_process_config_link(priv, peer);
665 } 688 }
666 return 0; 689 return 0;
667} 690}