diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/p2p.c')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 288 |
1 files changed, 213 insertions, 75 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 4166e642068b..2b90da0d85f3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
18 | #include <linux/etherdevice.h> | ||
18 | #include <net/cfg80211.h> | 19 | #include <net/cfg80211.h> |
19 | 20 | ||
20 | #include <brcmu_wifi.h> | 21 | #include <brcmu_wifi.h> |
@@ -423,29 +424,6 @@ static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len) | |||
423 | 424 | ||
424 | 425 | ||
425 | /** | 426 | /** |
426 | * brcmf_p2p_chnr_to_chspec() - convert channel number to chanspec. | ||
427 | * | ||
428 | * @channel: channel number | ||
429 | */ | ||
430 | static u16 brcmf_p2p_chnr_to_chspec(u16 channel) | ||
431 | { | ||
432 | u16 chanspec; | ||
433 | |||
434 | chanspec = channel & WL_CHANSPEC_CHAN_MASK; | ||
435 | |||
436 | if (channel <= CH_MAX_2G_CHANNEL) | ||
437 | chanspec |= WL_CHANSPEC_BAND_2G; | ||
438 | else | ||
439 | chanspec |= WL_CHANSPEC_BAND_5G; | ||
440 | |||
441 | chanspec |= WL_CHANSPEC_BW_20; | ||
442 | chanspec |= WL_CHANSPEC_CTL_SB_NONE; | ||
443 | |||
444 | return chanspec; | ||
445 | } | ||
446 | |||
447 | |||
448 | /** | ||
449 | * brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation. | 427 | * brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation. |
450 | * | 428 | * |
451 | * @ifp: ifp to use for iovars (primary). | 429 | * @ifp: ifp to use for iovars (primary). |
@@ -455,7 +433,9 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac) | |||
455 | { | 433 | { |
456 | s32 ret = 0; | 434 | s32 ret = 0; |
457 | 435 | ||
436 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); | ||
458 | brcmf_fil_iovar_int_set(ifp, "apsta", 1); | 437 | brcmf_fil_iovar_int_set(ifp, "apsta", 1); |
438 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); | ||
459 | 439 | ||
460 | /* In case of COB type, firmware has default mac address | 440 | /* In case of COB type, firmware has default mac address |
461 | * After Initializing firmware, we have to set current mac address to | 441 | * After Initializing firmware, we have to set current mac address to |
@@ -473,28 +453,35 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac) | |||
473 | * brcmf_p2p_generate_bss_mac() - derive mac addresses for P2P. | 453 | * brcmf_p2p_generate_bss_mac() - derive mac addresses for P2P. |
474 | * | 454 | * |
475 | * @p2p: P2P specific data. | 455 | * @p2p: P2P specific data. |
456 | * @dev_addr: optional device address. | ||
476 | * | 457 | * |
477 | * P2P needs mac addresses for P2P device and interface. These are | 458 | * P2P needs mac addresses for P2P device and interface. If no device |
478 | * derived from the primary net device, ie. the permanent ethernet | 459 | * address it specified, these are derived from the primary net device, ie. |
479 | * address of the device. | 460 | * the permanent ethernet address of the device. |
480 | */ | 461 | */ |
481 | static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p) | 462 | static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr) |
482 | { | 463 | { |
483 | struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | 464 | struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; |
484 | struct brcmf_if *p2p_ifp = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp; | 465 | bool local_admin = false; |
466 | |||
467 | if (!dev_addr || is_zero_ether_addr(dev_addr)) { | ||
468 | dev_addr = pri_ifp->mac_addr; | ||
469 | local_admin = true; | ||
470 | } | ||
485 | 471 | ||
486 | /* Generate the P2P Device Address. This consists of the device's | 472 | /* Generate the P2P Device Address. This consists of the device's |
487 | * primary MAC address with the locally administered bit set. | 473 | * primary MAC address with the locally administered bit set. |
488 | */ | 474 | */ |
489 | memcpy(p2p->dev_addr, pri_ifp->mac_addr, ETH_ALEN); | 475 | memcpy(p2p->dev_addr, dev_addr, ETH_ALEN); |
490 | p2p->dev_addr[0] |= 0x02; | 476 | if (local_admin) |
491 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | 477 | p2p->dev_addr[0] |= 0x02; |
492 | 478 | ||
493 | /* Generate the P2P Interface Address. If the discovery and connection | 479 | /* Generate the P2P Interface Address. If the discovery and connection |
494 | * BSSCFGs need to simultaneously co-exist, then this address must be | 480 | * BSSCFGs need to simultaneously co-exist, then this address must be |
495 | * different from the P2P Device Address, but also locally administered. | 481 | * different from the P2P Device Address, but also locally administered. |
496 | */ | 482 | */ |
497 | memcpy(p2p->int_addr, p2p->dev_addr, ETH_ALEN); | 483 | memcpy(p2p->int_addr, p2p->dev_addr, ETH_ALEN); |
484 | p2p->int_addr[0] |= 0x02; | ||
498 | p2p->int_addr[4] ^= 0x80; | 485 | p2p->int_addr[4] ^= 0x80; |
499 | } | 486 | } |
500 | 487 | ||
@@ -773,7 +760,7 @@ exit: | |||
773 | * validates the channels in the request. | 760 | * validates the channels in the request. |
774 | */ | 761 | */ |
775 | static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, | 762 | static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, |
776 | struct net_device *ndev, | 763 | struct brcmf_if *ifp, |
777 | struct cfg80211_scan_request *request, | 764 | struct cfg80211_scan_request *request, |
778 | u16 action) | 765 | u16 action) |
779 | { | 766 | { |
@@ -827,7 +814,8 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, | |||
827 | IEEE80211_CHAN_PASSIVE_SCAN)) | 814 | IEEE80211_CHAN_PASSIVE_SCAN)) |
828 | continue; | 815 | continue; |
829 | 816 | ||
830 | chanspecs[i] = channel_to_chanspec(chan); | 817 | chanspecs[i] = channel_to_chanspec(&p2p->cfg->d11inf, |
818 | chan); | ||
831 | brcmf_dbg(INFO, "%d: chan=%d, channel spec=%x\n", | 819 | brcmf_dbg(INFO, "%d: chan=%d, channel spec=%x\n", |
832 | num_nodfs, chan->hw_value, chanspecs[i]); | 820 | num_nodfs, chan->hw_value, chanspecs[i]); |
833 | num_nodfs++; | 821 | num_nodfs++; |
@@ -935,8 +923,8 @@ static s32 | |||
935 | brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration) | 923 | brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration) |
936 | { | 924 | { |
937 | struct brcmf_cfg80211_vif *vif; | 925 | struct brcmf_cfg80211_vif *vif; |
926 | struct brcmu_chan ch; | ||
938 | s32 err = 0; | 927 | s32 err = 0; |
939 | u16 chanspec; | ||
940 | 928 | ||
941 | vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; | 929 | vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; |
942 | if (!vif) { | 930 | if (!vif) { |
@@ -951,9 +939,11 @@ brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration) | |||
951 | goto exit; | 939 | goto exit; |
952 | } | 940 | } |
953 | 941 | ||
954 | chanspec = brcmf_p2p_chnr_to_chspec(channel); | 942 | ch.chnum = channel; |
943 | ch.bw = BRCMU_CHAN_BW_20; | ||
944 | p2p->cfg->d11inf.encchspec(&ch); | ||
955 | err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN, | 945 | err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN, |
956 | chanspec, (u16)duration); | 946 | ch.chspec, (u16)duration); |
957 | if (!err) { | 947 | if (!err) { |
958 | set_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status); | 948 | set_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status); |
959 | p2p->remain_on_channel_cookie++; | 949 | p2p->remain_on_channel_cookie++; |
@@ -1065,6 +1055,7 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel) | |||
1065 | u32 channel_cnt; | 1055 | u32 channel_cnt; |
1066 | u16 *default_chan_list; | 1056 | u16 *default_chan_list; |
1067 | u32 i; | 1057 | u32 i; |
1058 | struct brcmu_chan ch; | ||
1068 | 1059 | ||
1069 | brcmf_dbg(TRACE, "Enter\n"); | 1060 | brcmf_dbg(TRACE, "Enter\n"); |
1070 | 1061 | ||
@@ -1079,15 +1070,23 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel) | |||
1079 | err = -ENOMEM; | 1070 | err = -ENOMEM; |
1080 | goto exit; | 1071 | goto exit; |
1081 | } | 1072 | } |
1073 | ch.bw = BRCMU_CHAN_BW_20; | ||
1082 | if (channel) { | 1074 | if (channel) { |
1075 | ch.chnum = channel; | ||
1076 | p2p->cfg->d11inf.encchspec(&ch); | ||
1083 | /* insert same channel to the chan_list */ | 1077 | /* insert same channel to the chan_list */ |
1084 | for (i = 0; i < channel_cnt; i++) | 1078 | for (i = 0; i < channel_cnt; i++) |
1085 | default_chan_list[i] = | 1079 | default_chan_list[i] = ch.chspec; |
1086 | brcmf_p2p_chnr_to_chspec(channel); | ||
1087 | } else { | 1080 | } else { |
1088 | default_chan_list[0] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_1); | 1081 | ch.chnum = SOCIAL_CHAN_1; |
1089 | default_chan_list[1] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_2); | 1082 | p2p->cfg->d11inf.encchspec(&ch); |
1090 | default_chan_list[2] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_3); | 1083 | default_chan_list[0] = ch.chspec; |
1084 | ch.chnum = SOCIAL_CHAN_2; | ||
1085 | p2p->cfg->d11inf.encchspec(&ch); | ||
1086 | default_chan_list[1] = ch.chspec; | ||
1087 | ch.chnum = SOCIAL_CHAN_3; | ||
1088 | p2p->cfg->d11inf.encchspec(&ch); | ||
1089 | default_chan_list[2] = ch.chspec; | ||
1091 | } | 1090 | } |
1092 | err = brcmf_p2p_escan(p2p, channel_cnt, default_chan_list, | 1091 | err = brcmf_p2p_escan(p2p, channel_cnt, default_chan_list, |
1093 | WL_P2P_DISC_ST_SEARCH, WL_ESCAN_ACTION_START, | 1092 | WL_P2P_DISC_ST_SEARCH, WL_ESCAN_ACTION_START, |
@@ -1217,6 +1216,7 @@ bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg, | |||
1217 | { | 1216 | { |
1218 | struct brcmf_p2p_info *p2p = &cfg->p2p; | 1217 | struct brcmf_p2p_info *p2p = &cfg->p2p; |
1219 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; | 1218 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; |
1219 | struct brcmu_chan ch; | ||
1220 | u8 *ie; | 1220 | u8 *ie; |
1221 | s32 err; | 1221 | s32 err; |
1222 | u8 p2p_dev_addr[ETH_ALEN]; | 1222 | u8 p2p_dev_addr[ETH_ALEN]; |
@@ -1242,8 +1242,12 @@ bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg, | |||
1242 | p2p_dev_addr, sizeof(p2p_dev_addr)); | 1242 | p2p_dev_addr, sizeof(p2p_dev_addr)); |
1243 | if ((err >= 0) && | 1243 | if ((err >= 0) && |
1244 | (!memcmp(p2p_dev_addr, afx_hdl->tx_dst_addr, ETH_ALEN))) { | 1244 | (!memcmp(p2p_dev_addr, afx_hdl->tx_dst_addr, ETH_ALEN))) { |
1245 | afx_hdl->peer_chan = bi->ctl_ch ? bi->ctl_ch : | 1245 | if (!bi->ctl_ch) { |
1246 | CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); | 1246 | ch.chspec = le16_to_cpu(bi->chanspec); |
1247 | cfg->d11inf.decchspec(&ch); | ||
1248 | bi->ctl_ch = ch.chnum; | ||
1249 | } | ||
1250 | afx_hdl->peer_chan = bi->ctl_ch; | ||
1247 | brcmf_dbg(TRACE, "ACTION FRAME SCAN : Peer %pM found, channel : %d\n", | 1251 | brcmf_dbg(TRACE, "ACTION FRAME SCAN : Peer %pM found, channel : %d\n", |
1248 | afx_hdl->tx_dst_addr, afx_hdl->peer_chan); | 1252 | afx_hdl->tx_dst_addr, afx_hdl->peer_chan); |
1249 | complete(&afx_hdl->act_frm_scan); | 1253 | complete(&afx_hdl->act_frm_scan); |
@@ -1261,7 +1265,7 @@ static void | |||
1261 | brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg) | 1265 | brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg) |
1262 | { | 1266 | { |
1263 | struct brcmf_p2p_info *p2p = &cfg->p2p; | 1267 | struct brcmf_p2p_info *p2p = &cfg->p2p; |
1264 | struct net_device *ndev = cfg->escan_info.ndev; | 1268 | struct brcmf_if *ifp = cfg->escan_info.ifp; |
1265 | 1269 | ||
1266 | if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) && | 1270 | if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) && |
1267 | (test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status) || | 1271 | (test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status) || |
@@ -1271,12 +1275,12 @@ brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg) | |||
1271 | * So abort scan for off channel completion. | 1275 | * So abort scan for off channel completion. |
1272 | */ | 1276 | */ |
1273 | if (p2p->af_sent_channel) | 1277 | if (p2p->af_sent_channel) |
1274 | brcmf_notify_escan_complete(cfg, ndev, true, true); | 1278 | brcmf_notify_escan_complete(cfg, ifp, true, true); |
1275 | } else if (test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN, | 1279 | } else if (test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN, |
1276 | &p2p->status)) { | 1280 | &p2p->status)) { |
1277 | brcmf_dbg(TRACE, "*** Wake UP ** abort listen for next af frame\n"); | 1281 | brcmf_dbg(TRACE, "*** Wake UP ** abort listen for next af frame\n"); |
1278 | /* So abort scan to cancel listen */ | 1282 | /* So abort scan to cancel listen */ |
1279 | brcmf_notify_escan_complete(cfg, ndev, true, true); | 1283 | brcmf_notify_escan_complete(cfg, ifp, true, true); |
1280 | } | 1284 | } |
1281 | } | 1285 | } |
1282 | 1286 | ||
@@ -1350,12 +1354,14 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, | |||
1350 | u8 *frame = (u8 *)(rxframe + 1); | 1354 | u8 *frame = (u8 *)(rxframe + 1); |
1351 | struct brcmf_p2p_pub_act_frame *act_frm; | 1355 | struct brcmf_p2p_pub_act_frame *act_frm; |
1352 | struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm; | 1356 | struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm; |
1353 | u16 chanspec = be16_to_cpu(rxframe->chanspec); | 1357 | struct brcmu_chan ch; |
1354 | struct ieee80211_mgmt *mgmt_frame; | 1358 | struct ieee80211_mgmt *mgmt_frame; |
1355 | s32 freq; | 1359 | s32 freq; |
1356 | u16 mgmt_type; | 1360 | u16 mgmt_type; |
1357 | u8 action; | 1361 | u8 action; |
1358 | 1362 | ||
1363 | ch.chspec = be16_to_cpu(rxframe->chanspec); | ||
1364 | cfg->d11inf.decchspec(&ch); | ||
1359 | /* Check if wpa_supplicant has registered for this frame */ | 1365 | /* Check if wpa_supplicant has registered for this frame */ |
1360 | brcmf_dbg(INFO, "ifp->vif->mgmt_rx_reg %04x\n", ifp->vif->mgmt_rx_reg); | 1366 | brcmf_dbg(INFO, "ifp->vif->mgmt_rx_reg %04x\n", ifp->vif->mgmt_rx_reg); |
1361 | mgmt_type = (IEEE80211_STYPE_ACTION & IEEE80211_FCTL_STYPE) >> 4; | 1367 | mgmt_type = (IEEE80211_STYPE_ACTION & IEEE80211_FCTL_STYPE) >> 4; |
@@ -1374,7 +1380,7 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, | |||
1374 | &p2p->status) && | 1380 | &p2p->status) && |
1375 | (memcmp(afx_hdl->tx_dst_addr, e->addr, | 1381 | (memcmp(afx_hdl->tx_dst_addr, e->addr, |
1376 | ETH_ALEN) == 0)) { | 1382 | ETH_ALEN) == 0)) { |
1377 | afx_hdl->peer_chan = CHSPEC_CHANNEL(chanspec); | 1383 | afx_hdl->peer_chan = ch.chnum; |
1378 | brcmf_dbg(INFO, "GON request: Peer found, channel=%d\n", | 1384 | brcmf_dbg(INFO, "GON request: Peer found, channel=%d\n", |
1379 | afx_hdl->peer_chan); | 1385 | afx_hdl->peer_chan); |
1380 | complete(&afx_hdl->act_frm_scan); | 1386 | complete(&afx_hdl->act_frm_scan); |
@@ -1384,7 +1390,7 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, | |||
1384 | /* After complete GO Negotiation, roll back to mpc mode */ | 1390 | /* After complete GO Negotiation, roll back to mpc mode */ |
1385 | if ((action == P2P_PAF_GON_CONF) || | 1391 | if ((action == P2P_PAF_GON_CONF) || |
1386 | (action == P2P_PAF_PROVDIS_RSP)) | 1392 | (action == P2P_PAF_PROVDIS_RSP)) |
1387 | brcmf_set_mpc(ifp->ndev, 1); | 1393 | brcmf_set_mpc(ifp, 1); |
1388 | if (action == P2P_PAF_GON_CONF) { | 1394 | if (action == P2P_PAF_GON_CONF) { |
1389 | brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status cleared\n"); | 1395 | brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status cleared\n"); |
1390 | clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status); | 1396 | clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status); |
@@ -1417,11 +1423,12 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, | |||
1417 | memcpy(&mgmt_frame->u, frame, mgmt_frame_len); | 1423 | memcpy(&mgmt_frame->u, frame, mgmt_frame_len); |
1418 | mgmt_frame_len += offsetof(struct ieee80211_mgmt, u); | 1424 | mgmt_frame_len += offsetof(struct ieee80211_mgmt, u); |
1419 | 1425 | ||
1420 | freq = ieee80211_channel_to_frequency(CHSPEC_CHANNEL(chanspec), | 1426 | freq = ieee80211_channel_to_frequency(ch.chnum, |
1421 | CHSPEC_IS2G(chanspec) ? | 1427 | ch.band == BRCMU_CHAN_BAND_2G ? |
1422 | IEEE80211_BAND_2GHZ : | 1428 | IEEE80211_BAND_2GHZ : |
1423 | IEEE80211_BAND_5GHZ); | 1429 | IEEE80211_BAND_5GHZ); |
1424 | wdev = ifp->ndev->ieee80211_ptr; | 1430 | |
1431 | wdev = &ifp->vif->wdev; | ||
1425 | cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len, | 1432 | cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len, |
1426 | GFP_ATOMIC); | 1433 | GFP_ATOMIC); |
1427 | 1434 | ||
@@ -1637,6 +1644,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, | |||
1637 | struct brcmf_fil_af_params_le *af_params) | 1644 | struct brcmf_fil_af_params_le *af_params) |
1638 | { | 1645 | { |
1639 | struct brcmf_p2p_info *p2p = &cfg->p2p; | 1646 | struct brcmf_p2p_info *p2p = &cfg->p2p; |
1647 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
1640 | struct brcmf_fil_action_frame_le *action_frame; | 1648 | struct brcmf_fil_action_frame_le *action_frame; |
1641 | struct brcmf_config_af_params config_af_params; | 1649 | struct brcmf_config_af_params config_af_params; |
1642 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; | 1650 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; |
@@ -1725,7 +1733,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, | |||
1725 | 1733 | ||
1726 | /* To make sure to send successfully action frame, turn off mpc */ | 1734 | /* To make sure to send successfully action frame, turn off mpc */ |
1727 | if (config_af_params.mpc_onoff == 0) | 1735 | if (config_af_params.mpc_onoff == 0) |
1728 | brcmf_set_mpc(ndev, 0); | 1736 | brcmf_set_mpc(ifp, 0); |
1729 | 1737 | ||
1730 | /* set status and destination address before sending af */ | 1738 | /* set status and destination address before sending af */ |
1731 | if (p2p->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) { | 1739 | if (p2p->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) { |
@@ -1753,7 +1761,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, | |||
1753 | * care of current piggback algo, lets abort the scan here | 1761 | * care of current piggback algo, lets abort the scan here |
1754 | * itself. | 1762 | * itself. |
1755 | */ | 1763 | */ |
1756 | brcmf_notify_escan_complete(cfg, ndev, true, true); | 1764 | brcmf_notify_escan_complete(cfg, ifp, true, true); |
1757 | 1765 | ||
1758 | /* update channel */ | 1766 | /* update channel */ |
1759 | af_params->channel = cpu_to_le32(afx_hdl->peer_chan); | 1767 | af_params->channel = cpu_to_le32(afx_hdl->peer_chan); |
@@ -1820,7 +1828,7 @@ exit: | |||
1820 | clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status); | 1828 | clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status); |
1821 | /* if all done, turn mpc on again */ | 1829 | /* if all done, turn mpc on again */ |
1822 | if (config_af_params.mpc_onoff == 1) | 1830 | if (config_af_params.mpc_onoff == 1) |
1823 | brcmf_set_mpc(ndev, 1); | 1831 | brcmf_set_mpc(ifp, 1); |
1824 | 1832 | ||
1825 | return ack; | 1833 | return ack; |
1826 | } | 1834 | } |
@@ -1839,10 +1847,10 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp, | |||
1839 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; | 1847 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; |
1840 | struct brcmf_p2p_info *p2p = &cfg->p2p; | 1848 | struct brcmf_p2p_info *p2p = &cfg->p2p; |
1841 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; | 1849 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; |
1842 | struct wireless_dev *wdev; | ||
1843 | struct brcmf_cfg80211_vif *vif = ifp->vif; | 1850 | struct brcmf_cfg80211_vif *vif = ifp->vif; |
1844 | struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data; | 1851 | struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data; |
1845 | u16 chanspec = be16_to_cpu(rxframe->chanspec); | 1852 | u16 chanspec = be16_to_cpu(rxframe->chanspec); |
1853 | struct brcmu_chan ch; | ||
1846 | u8 *mgmt_frame; | 1854 | u8 *mgmt_frame; |
1847 | u32 mgmt_frame_len; | 1855 | u32 mgmt_frame_len; |
1848 | s32 freq; | 1856 | s32 freq; |
@@ -1851,9 +1859,12 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp, | |||
1851 | brcmf_dbg(INFO, "Enter: event %d reason %d\n", e->event_code, | 1859 | brcmf_dbg(INFO, "Enter: event %d reason %d\n", e->event_code, |
1852 | e->reason); | 1860 | e->reason); |
1853 | 1861 | ||
1862 | ch.chspec = be16_to_cpu(rxframe->chanspec); | ||
1863 | cfg->d11inf.decchspec(&ch); | ||
1864 | |||
1854 | if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status) && | 1865 | if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status) && |
1855 | (memcmp(afx_hdl->tx_dst_addr, e->addr, ETH_ALEN) == 0)) { | 1866 | (memcmp(afx_hdl->tx_dst_addr, e->addr, ETH_ALEN) == 0)) { |
1856 | afx_hdl->peer_chan = CHSPEC_CHANNEL(chanspec); | 1867 | afx_hdl->peer_chan = ch.chnum; |
1857 | brcmf_dbg(INFO, "PROBE REQUEST: Peer found, channel=%d\n", | 1868 | brcmf_dbg(INFO, "PROBE REQUEST: Peer found, channel=%d\n", |
1858 | afx_hdl->peer_chan); | 1869 | afx_hdl->peer_chan); |
1859 | complete(&afx_hdl->act_frm_scan); | 1870 | complete(&afx_hdl->act_frm_scan); |
@@ -1878,12 +1889,13 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp, | |||
1878 | 1889 | ||
1879 | mgmt_frame = (u8 *)(rxframe + 1); | 1890 | mgmt_frame = (u8 *)(rxframe + 1); |
1880 | mgmt_frame_len = e->datalen - sizeof(*rxframe); | 1891 | mgmt_frame_len = e->datalen - sizeof(*rxframe); |
1881 | freq = ieee80211_channel_to_frequency(CHSPEC_CHANNEL(chanspec), | 1892 | freq = ieee80211_channel_to_frequency(ch.chnum, |
1882 | CHSPEC_IS2G(chanspec) ? | 1893 | ch.band == BRCMU_CHAN_BAND_2G ? |
1883 | IEEE80211_BAND_2GHZ : | 1894 | IEEE80211_BAND_2GHZ : |
1884 | IEEE80211_BAND_5GHZ); | 1895 | IEEE80211_BAND_5GHZ); |
1885 | wdev = ifp->ndev->ieee80211_ptr; | 1896 | |
1886 | cfg80211_rx_mgmt(wdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC); | 1897 | cfg80211_rx_mgmt(&vif->wdev, freq, 0, mgmt_frame, mgmt_frame_len, |
1898 | GFP_ATOMIC); | ||
1887 | 1899 | ||
1888 | brcmf_dbg(INFO, "mgmt_frame_len (%d) , e->datalen (%d), chanspec (%04x), freq (%d)\n", | 1900 | brcmf_dbg(INFO, "mgmt_frame_len (%d) , e->datalen (%d), chanspec (%04x), freq (%d)\n", |
1889 | mgmt_frame_len, e->datalen, chanspec, freq); | 1901 | mgmt_frame_len, e->datalen, chanspec, freq); |
@@ -1934,7 +1946,8 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) | |||
1934 | 1946 | ||
1935 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; | 1947 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; |
1936 | 1948 | ||
1937 | brcmf_p2p_generate_bss_mac(p2p); | 1949 | brcmf_p2p_generate_bss_mac(p2p, NULL); |
1950 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | ||
1938 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); | 1951 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); |
1939 | 1952 | ||
1940 | /* Initialize P2P Discovery in the firmware */ | 1953 | /* Initialize P2P Discovery in the firmware */ |
@@ -2001,21 +2014,19 @@ static void brcmf_p2p_get_current_chanspec(struct brcmf_p2p_info *p2p, | |||
2001 | { | 2014 | { |
2002 | struct brcmf_if *ifp; | 2015 | struct brcmf_if *ifp; |
2003 | struct brcmf_fil_chan_info_le ci; | 2016 | struct brcmf_fil_chan_info_le ci; |
2017 | struct brcmu_chan ch; | ||
2004 | s32 err; | 2018 | s32 err; |
2005 | 2019 | ||
2006 | ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | 2020 | ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; |
2007 | 2021 | ||
2008 | *chanspec = 11 & WL_CHANSPEC_CHAN_MASK; | 2022 | ch.chnum = 11; |
2009 | 2023 | ||
2010 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL, &ci, sizeof(ci)); | 2024 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL, &ci, sizeof(ci)); |
2011 | if (!err) { | 2025 | if (!err) |
2012 | *chanspec = le32_to_cpu(ci.hw_channel) & WL_CHANSPEC_CHAN_MASK; | 2026 | ch.chnum = le32_to_cpu(ci.hw_channel); |
2013 | if (*chanspec < CH_MAX_2G_CHANNEL) | 2027 | ch.bw = BRCMU_CHAN_BW_20; |
2014 | *chanspec |= WL_CHANSPEC_BAND_2G; | 2028 | p2p->cfg->d11inf.encchspec(&ch); |
2015 | else | 2029 | *chanspec = ch.chspec; |
2016 | *chanspec |= WL_CHANSPEC_BAND_5G; | ||
2017 | } | ||
2018 | *chanspec |= WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE; | ||
2019 | } | 2030 | } |
2020 | 2031 | ||
2021 | /** | 2032 | /** |
@@ -2040,13 +2051,13 @@ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg, | |||
2040 | brcmf_err("vif for P2PAPI_BSSCFG_PRIMARY does not exist\n"); | 2051 | brcmf_err("vif for P2PAPI_BSSCFG_PRIMARY does not exist\n"); |
2041 | return -EPERM; | 2052 | return -EPERM; |
2042 | } | 2053 | } |
2043 | brcmf_notify_escan_complete(cfg, vif->ifp->ndev, true, true); | 2054 | brcmf_notify_escan_complete(cfg, vif->ifp, true, true); |
2044 | vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif; | 2055 | vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif; |
2045 | if (!vif) { | 2056 | if (!vif) { |
2046 | brcmf_err("vif for P2PAPI_BSSCFG_CONNECTION does not exist\n"); | 2057 | brcmf_err("vif for P2PAPI_BSSCFG_CONNECTION does not exist\n"); |
2047 | return -EPERM; | 2058 | return -EPERM; |
2048 | } | 2059 | } |
2049 | brcmf_set_mpc(vif->ifp->ndev, 0); | 2060 | brcmf_set_mpc(vif->ifp, 0); |
2050 | 2061 | ||
2051 | /* In concurrency case, STA may be already associated in a particular */ | 2062 | /* In concurrency case, STA may be already associated in a particular */ |
2052 | /* channel. so retrieve the current channel of primary interface and */ | 2063 | /* channel. so retrieve the current channel of primary interface and */ |
@@ -2124,13 +2135,105 @@ static int brcmf_p2p_release_p2p_if(struct brcmf_cfg80211_vif *vif) | |||
2124 | } | 2135 | } |
2125 | 2136 | ||
2126 | /** | 2137 | /** |
2138 | * brcmf_p2p_create_p2pdev() - create a P2P_DEVICE virtual interface. | ||
2139 | * | ||
2140 | * @p2p: P2P specific data. | ||
2141 | * @wiphy: wiphy device of new interface. | ||
2142 | * @addr: mac address for this new interface. | ||
2143 | */ | ||
2144 | static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, | ||
2145 | struct wiphy *wiphy, | ||
2146 | u8 *addr) | ||
2147 | { | ||
2148 | struct brcmf_cfg80211_vif *p2p_vif; | ||
2149 | struct brcmf_if *p2p_ifp; | ||
2150 | struct brcmf_if *pri_ifp; | ||
2151 | int err; | ||
2152 | u32 bssidx; | ||
2153 | |||
2154 | if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif) | ||
2155 | return ERR_PTR(-ENOSPC); | ||
2156 | |||
2157 | p2p_vif = brcmf_alloc_vif(p2p->cfg, NL80211_IFTYPE_P2P_DEVICE, | ||
2158 | false); | ||
2159 | if (IS_ERR(p2p_vif)) { | ||
2160 | brcmf_err("could not create discovery vif\n"); | ||
2161 | return (struct wireless_dev *)p2p_vif; | ||
2162 | } | ||
2163 | |||
2164 | pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | ||
2165 | brcmf_p2p_generate_bss_mac(p2p, addr); | ||
2166 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); | ||
2167 | |||
2168 | brcmf_cfg80211_arm_vif_event(p2p->cfg, p2p_vif); | ||
2169 | |||
2170 | /* Initialize P2P Discovery in the firmware */ | ||
2171 | err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); | ||
2172 | if (err < 0) { | ||
2173 | brcmf_err("set p2p_disc error\n"); | ||
2174 | brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); | ||
2175 | goto fail; | ||
2176 | } | ||
2177 | |||
2178 | /* wait for firmware event */ | ||
2179 | err = brcmf_cfg80211_wait_vif_event_timeout(p2p->cfg, BRCMF_E_IF_ADD, | ||
2180 | msecs_to_jiffies(1500)); | ||
2181 | brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); | ||
2182 | if (!err) { | ||
2183 | brcmf_err("timeout occurred\n"); | ||
2184 | err = -EIO; | ||
2185 | goto fail; | ||
2186 | } | ||
2187 | |||
2188 | /* discovery interface created */ | ||
2189 | p2p_ifp = p2p_vif->ifp; | ||
2190 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; | ||
2191 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | ||
2192 | memcpy(&p2p_vif->wdev.address, p2p->dev_addr, sizeof(p2p->dev_addr)); | ||
2193 | |||
2194 | /* verify bsscfg index for P2P discovery */ | ||
2195 | err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); | ||
2196 | if (err < 0) { | ||
2197 | brcmf_err("retrieving discover bsscfg index failed\n"); | ||
2198 | goto fail; | ||
2199 | } | ||
2200 | |||
2201 | WARN_ON(p2p_ifp->bssidx != bssidx); | ||
2202 | |||
2203 | init_completion(&p2p->send_af_done); | ||
2204 | INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler); | ||
2205 | init_completion(&p2p->afx_hdl.act_frm_scan); | ||
2206 | init_completion(&p2p->wait_next_af); | ||
2207 | |||
2208 | return &p2p_vif->wdev; | ||
2209 | |||
2210 | fail: | ||
2211 | brcmf_free_vif(p2p_vif); | ||
2212 | return ERR_PTR(err); | ||
2213 | } | ||
2214 | |||
2215 | /** | ||
2216 | * brcmf_p2p_delete_p2pdev() - delete P2P_DEVICE virtual interface. | ||
2217 | * | ||
2218 | * @vif: virtual interface object to delete. | ||
2219 | */ | ||
2220 | static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_vif *vif) | ||
2221 | { | ||
2222 | struct brcmf_p2p_info *p2p = &vif->ifp->drvr->config->p2p; | ||
2223 | |||
2224 | cfg80211_unregister_wdev(&vif->wdev); | ||
2225 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; | ||
2226 | brcmf_free_vif(vif); | ||
2227 | } | ||
2228 | |||
2229 | /** | ||
2127 | * brcmf_p2p_add_vif() - create a new P2P virtual interface. | 2230 | * brcmf_p2p_add_vif() - create a new P2P virtual interface. |
2128 | * | 2231 | * |
2129 | * @wiphy: wiphy device of new interface. | 2232 | * @wiphy: wiphy device of new interface. |
2130 | * @name: name of the new interface. | 2233 | * @name: name of the new interface. |
2131 | * @type: nl80211 interface type. | 2234 | * @type: nl80211 interface type. |
2132 | * @flags: TBD | 2235 | * @flags: not used. |
2133 | * @params: TBD | 2236 | * @params: contains mac address for P2P device. |
2134 | */ | 2237 | */ |
2135 | struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | 2238 | struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, |
2136 | enum nl80211_iftype type, u32 *flags, | 2239 | enum nl80211_iftype type, u32 *flags, |
@@ -2157,6 +2260,9 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | |||
2157 | iftype = BRCMF_FIL_P2P_IF_GO; | 2260 | iftype = BRCMF_FIL_P2P_IF_GO; |
2158 | mode = WL_MODE_AP; | 2261 | mode = WL_MODE_AP; |
2159 | break; | 2262 | break; |
2263 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2264 | return brcmf_p2p_create_p2pdev(&cfg->p2p, wiphy, | ||
2265 | params->macaddr); | ||
2160 | default: | 2266 | default: |
2161 | return ERR_PTR(-EOPNOTSUPP); | 2267 | return ERR_PTR(-EOPNOTSUPP); |
2162 | } | 2268 | } |
@@ -2244,6 +2350,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2244 | break; | 2350 | break; |
2245 | 2351 | ||
2246 | case NL80211_IFTYPE_P2P_DEVICE: | 2352 | case NL80211_IFTYPE_P2P_DEVICE: |
2353 | brcmf_p2p_delete_p2pdev(vif); | ||
2354 | return 0; | ||
2247 | default: | 2355 | default: |
2248 | return -ENOTSUPP; | 2356 | return -ENOTSUPP; |
2249 | break; | 2357 | break; |
@@ -2275,3 +2383,33 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2275 | 2383 | ||
2276 | return err; | 2384 | return err; |
2277 | } | 2385 | } |
2386 | |||
2387 | int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev) | ||
2388 | { | ||
2389 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
2390 | struct brcmf_p2p_info *p2p = &cfg->p2p; | ||
2391 | struct brcmf_cfg80211_vif *vif; | ||
2392 | int err; | ||
2393 | |||
2394 | vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); | ||
2395 | mutex_lock(&cfg->usr_sync); | ||
2396 | err = brcmf_p2p_enable_discovery(p2p); | ||
2397 | if (!err) | ||
2398 | set_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); | ||
2399 | mutex_unlock(&cfg->usr_sync); | ||
2400 | return err; | ||
2401 | } | ||
2402 | |||
2403 | void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev) | ||
2404 | { | ||
2405 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
2406 | struct brcmf_p2p_info *p2p = &cfg->p2p; | ||
2407 | struct brcmf_cfg80211_vif *vif; | ||
2408 | |||
2409 | vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); | ||
2410 | mutex_lock(&cfg->usr_sync); | ||
2411 | (void)brcmf_p2p_deinit_discovery(p2p); | ||
2412 | brcmf_abort_scanning(cfg); | ||
2413 | clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); | ||
2414 | mutex_unlock(&cfg->usr_sync); | ||
2415 | } | ||