diff options
author | Hante Meuleman <meuleman@broadcom.com> | 2013-02-08 09:53:52 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-02-08 14:51:40 -0500 |
commit | 2fde59d93f8ac5525213996b5e98efb8f4d8c88c (patch) | |
tree | 1a484d63173e0dd710f373ba42ee40c740053168 /drivers/net/wireless/brcm80211/brcmfmac/p2p.c | |
parent | 1ce3086ccd81793fd6affb350826a0c41dc3ef37 (diff) |
brcmfmac: Create p2p0 netdev via module variable.
Add module variable with which a p2p0 netdev can be created. This
netdev can be used by wpa-supplicant to configure and set up the
p2p client/GO.
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/p2p.c')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 226 |
1 files changed, 109 insertions, 117 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 1c854f607d5b..c04d596be5be 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c | |||
@@ -407,22 +407,21 @@ static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len) | |||
407 | /** | 407 | /** |
408 | * brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation. | 408 | * brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation. |
409 | * | 409 | * |
410 | * @p2p: P2P specific data. | 410 | * @ifp: ifp to use for iovars (primary). |
411 | * @p2p_mac: mac address to configure for p2p_da_override | ||
411 | */ | 412 | */ |
412 | static int brcmf_p2p_set_firmware(struct brcmf_p2p_info *p2p) | 413 | static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac) |
413 | { | 414 | { |
414 | struct net_device *ndev = cfg_to_ndev(p2p->cfg); | ||
415 | u8 null_eth_addr[] = { 0, 0, 0, 0, 0, 0 }; | ||
416 | s32 ret = 0; | 415 | s32 ret = 0; |
417 | 416 | ||
418 | brcmf_fil_iovar_int_set(netdev_priv(ndev), "apsta", 1); | 417 | brcmf_fil_iovar_int_set(ifp, "apsta", 1); |
419 | 418 | ||
420 | /* In case of COB type, firmware has default mac address | 419 | /* In case of COB type, firmware has default mac address |
421 | * After Initializing firmware, we have to set current mac address to | 420 | * After Initializing firmware, we have to set current mac address to |
422 | * firmware for P2P device address | 421 | * firmware for P2P device address |
423 | */ | 422 | */ |
424 | ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "p2p_da_override", | 423 | ret = brcmf_fil_iovar_data_set(ifp, "p2p_da_override", p2p_mac, |
425 | null_eth_addr, sizeof(null_eth_addr)); | 424 | ETH_ALEN); |
426 | if (ret) | 425 | if (ret) |
427 | brcmf_err("failed to update device address ret %d\n", ret); | 426 | brcmf_err("failed to update device address ret %d\n", ret); |
428 | 427 | ||
@@ -440,11 +439,15 @@ static int brcmf_p2p_set_firmware(struct brcmf_p2p_info *p2p) | |||
440 | */ | 439 | */ |
441 | static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p) | 440 | static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p) |
442 | { | 441 | { |
442 | struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | ||
443 | struct brcmf_if *p2p_ifp = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp; | ||
444 | |||
443 | /* Generate the P2P Device Address. This consists of the device's | 445 | /* Generate the P2P Device Address. This consists of the device's |
444 | * primary MAC address with the locally administered bit set. | 446 | * primary MAC address with the locally administered bit set. |
445 | */ | 447 | */ |
446 | memcpy(p2p->dev_addr, p2p->cfg->pub->mac, ETH_ALEN); | 448 | memcpy(p2p->dev_addr, pri_ifp->mac_addr, ETH_ALEN); |
447 | p2p->dev_addr[0] |= 0x02; | 449 | p2p->dev_addr[0] |= 0x02; |
450 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | ||
448 | 451 | ||
449 | /* Generate the P2P Interface Address. If the discovery and connection | 452 | /* Generate the P2P Interface Address. If the discovery and connection |
450 | * BSSCFGs need to simultaneously co-exist, then this address must be | 453 | * BSSCFGs need to simultaneously co-exist, then this address must be |
@@ -503,111 +506,25 @@ static s32 brcmf_p2p_set_discover_state(struct brcmf_if *ifp, u8 state, | |||
503 | } | 506 | } |
504 | 507 | ||
505 | /** | 508 | /** |
506 | * brcmf_p2p_init_discovery() - enable discovery in the firmware. | ||
507 | * | ||
508 | * @p2p: P2P specific data. | ||
509 | * | ||
510 | * Configures the firmware to allow P2P peer discovery. Creates the | ||
511 | * virtual interface and consequently the P2P device for it. | ||
512 | */ | ||
513 | static s32 brcmf_p2p_init_discovery(struct brcmf_p2p_info *p2p) | ||
514 | { | ||
515 | struct net_device *ndev = cfg_to_ndev(p2p->cfg); | ||
516 | struct brcmf_cfg80211_vif *vif; | ||
517 | struct brcmf_if *ifp; | ||
518 | struct p2p_bss *bss_dev; | ||
519 | s32 index; | ||
520 | s32 ret; | ||
521 | |||
522 | brcmf_dbg(TRACE, "enter\n"); | ||
523 | |||
524 | bss_dev = &p2p->bss_idx[P2PAPI_BSSCFG_DEVICE]; | ||
525 | if (bss_dev->vif != NULL) { | ||
526 | brcmf_dbg(INFO, "do nothing, already initialized\n"); | ||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | /* Enable P2P Discovery in the firmware */ | ||
531 | ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "p2p_disc", 1); | ||
532 | if (ret < 0) { | ||
533 | brcmf_err("set discover error\n"); | ||
534 | return ret; | ||
535 | } | ||
536 | |||
537 | /* obtain bsscfg index for P2P discovery */ | ||
538 | ret = brcmf_fil_iovar_int_get(netdev_priv(ndev), "p2p_dev", &index); | ||
539 | if (ret < 0) { | ||
540 | brcmf_err("retrieving discover bsscfg index failed\n"); | ||
541 | return ret; | ||
542 | } | ||
543 | |||
544 | /* | ||
545 | * need brcmf_if for setting the discovery state. | ||
546 | */ | ||
547 | ifp = kzalloc(sizeof(*vif->ifp), GFP_KERNEL); | ||
548 | if (!ifp) { | ||
549 | brcmf_err("could not create discovery if\n"); | ||
550 | return -ENOMEM; | ||
551 | } | ||
552 | |||
553 | /* set required fields */ | ||
554 | ifp->drvr = p2p->cfg->pub; | ||
555 | ifp->ifidx = 0; | ||
556 | ifp->bssidx = index; | ||
557 | |||
558 | /* Set the initial discovery state to SCAN */ | ||
559 | ret = brcmf_p2p_set_discover_state(ifp, WL_P2P_DISC_ST_SCAN, 0, 0); | ||
560 | |||
561 | if (ret != 0) { | ||
562 | brcmf_err("unable to set WL_P2P_DISC_ST_SCAN\n"); | ||
563 | (void)brcmf_fil_iovar_int_set(netdev_priv(ndev), "p2p_disc", 0); | ||
564 | kfree(ifp); | ||
565 | return ret; | ||
566 | } | ||
567 | |||
568 | /* create a vif for it */ | ||
569 | vif = brcmf_alloc_vif(p2p->cfg, NL80211_IFTYPE_P2P_DEVICE, false); | ||
570 | if (IS_ERR(vif)) { | ||
571 | brcmf_err("could not create discovery vif\n"); | ||
572 | kfree(ifp); | ||
573 | return PTR_ERR(vif); | ||
574 | } | ||
575 | |||
576 | vif->ifp = ifp; | ||
577 | ifp->vif = vif; | ||
578 | bss_dev->vif = vif; | ||
579 | |||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | /** | ||
584 | * brcmf_p2p_deinit_discovery() - disable P2P device discovery. | 509 | * brcmf_p2p_deinit_discovery() - disable P2P device discovery. |
585 | * | 510 | * |
586 | * @p2p: P2P specific data. | 511 | * @p2p: P2P specific data. |
587 | * | 512 | * |
588 | * Resets the discovery state and disables it in firmware. The virtual | 513 | * Resets the discovery state and disables it in firmware. |
589 | * interface and P2P device are freed. | ||
590 | */ | 514 | */ |
591 | static s32 brcmf_p2p_deinit_discovery(struct brcmf_p2p_info *p2p) | 515 | static s32 brcmf_p2p_deinit_discovery(struct brcmf_p2p_info *p2p) |
592 | { | 516 | { |
593 | struct net_device *ndev = cfg_to_ndev(p2p->cfg); | 517 | struct brcmf_cfg80211_vif *vif; |
594 | struct brcmf_if *ifp; | ||
595 | struct p2p_bss *bss_dev; | ||
596 | brcmf_dbg(TRACE, "enter\n"); | ||
597 | 518 | ||
598 | bss_dev = &p2p->bss_idx[P2PAPI_BSSCFG_DEVICE]; | 519 | brcmf_dbg(TRACE, "enter\n"); |
599 | ifp = bss_dev->vif->ifp; | ||
600 | 520 | ||
601 | /* Set the discovery state to SCAN */ | 521 | /* Set the discovery state to SCAN */ |
602 | (void)brcmf_p2p_set_discover_state(ifp, WL_P2P_DISC_ST_SCAN, 0, 0); | 522 | vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; |
523 | (void)brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_SCAN, 0, 0); | ||
603 | 524 | ||
604 | /* Disable P2P discovery in the firmware */ | 525 | /* Disable P2P discovery in the firmware */ |
605 | (void)brcmf_fil_iovar_int_set(netdev_priv(ndev), "p2p_disc", 0); | 526 | vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; |
606 | 527 | (void)brcmf_fil_iovar_int_set(vif->ifp, "p2p_disc", 0); | |
607 | /* remove discovery interface */ | ||
608 | brcmf_free_vif(bss_dev->vif); | ||
609 | bss_dev->vif = NULL; | ||
610 | kfree(ifp); | ||
611 | 528 | ||
612 | return 0; | 529 | return 0; |
613 | } | 530 | } |
@@ -626,18 +543,30 @@ static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p) | |||
626 | 543 | ||
627 | brcmf_dbg(TRACE, "enter\n"); | 544 | brcmf_dbg(TRACE, "enter\n"); |
628 | vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; | 545 | vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; |
629 | if (vif) { | 546 | if (!vif) { |
630 | brcmf_dbg(INFO, "DISCOVERY init already done\n"); | 547 | brcmf_err("P2P config device not available\n"); |
548 | ret = -EPERM; | ||
631 | goto exit; | 549 | goto exit; |
632 | } | 550 | } |
633 | 551 | ||
634 | ret = brcmf_p2p_init_discovery(p2p); | 552 | if (test_bit(BRCMF_P2P_STATUS_ENABLED, &p2p->status)) { |
635 | if (ret < 0) { | 553 | brcmf_dbg(INFO, "P2P config device already configured\n"); |
636 | brcmf_err("init discovery error %d\n", ret); | ||
637 | goto exit; | 554 | goto exit; |
638 | } | 555 | } |
639 | 556 | ||
557 | /* Re-initialize P2P Discovery in the firmware */ | ||
558 | vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; | ||
559 | ret = brcmf_fil_iovar_int_set(vif->ifp, "p2p_disc", 1); | ||
560 | if (ret < 0) { | ||
561 | brcmf_err("set p2p_disc error\n"); | ||
562 | goto exit; | ||
563 | } | ||
640 | vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; | 564 | vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; |
565 | ret = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_SCAN, 0, 0); | ||
566 | if (ret < 0) { | ||
567 | brcmf_err("unable to set WL_P2P_DISC_ST_SCAN\n"); | ||
568 | goto exit; | ||
569 | } | ||
641 | 570 | ||
642 | /* | 571 | /* |
643 | * Set wsec to any non-zero value in the discovery bsscfg | 572 | * Set wsec to any non-zero value in the discovery bsscfg |
@@ -646,9 +575,12 @@ static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p) | |||
646 | * initiate WPS with us if this bit is not set. | 575 | * initiate WPS with us if this bit is not set. |
647 | */ | 576 | */ |
648 | ret = brcmf_fil_bsscfg_int_set(vif->ifp, "wsec", AES_ENABLED); | 577 | ret = brcmf_fil_bsscfg_int_set(vif->ifp, "wsec", AES_ENABLED); |
649 | if (ret < 0) | 578 | if (ret < 0) { |
650 | brcmf_err("wsec error %d\n", ret); | 579 | brcmf_err("wsec error %d\n", ret); |
580 | goto exit; | ||
581 | } | ||
651 | 582 | ||
583 | set_bit(BRCMF_P2P_STATUS_ENABLED, &p2p->status); | ||
652 | exit: | 584 | exit: |
653 | return ret; | 585 | return ret; |
654 | } | 586 | } |
@@ -1356,20 +1288,75 @@ exit: | |||
1356 | * | 1288 | * |
1357 | * @cfg: driver private data for cfg80211 interface. | 1289 | * @cfg: driver private data for cfg80211 interface. |
1358 | */ | 1290 | */ |
1359 | void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, | 1291 | s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) |
1360 | struct brcmf_cfg80211_vif *vif) | ||
1361 | { | 1292 | { |
1293 | struct brcmf_if *pri_ifp; | ||
1294 | struct brcmf_if *p2p_ifp; | ||
1295 | struct brcmf_cfg80211_vif *p2p_vif; | ||
1362 | struct brcmf_p2p_info *p2p; | 1296 | struct brcmf_p2p_info *p2p; |
1297 | struct brcmf_pub *drvr; | ||
1298 | s32 bssidx; | ||
1299 | s32 err = 0; | ||
1363 | 1300 | ||
1364 | p2p = &cfg->p2p; | 1301 | p2p = &cfg->p2p; |
1365 | |||
1366 | p2p->cfg = cfg; | 1302 | p2p->cfg = cfg; |
1367 | p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = vif; | 1303 | |
1368 | brcmf_p2p_generate_bss_mac(p2p); | 1304 | drvr = cfg->pub; |
1369 | brcmf_p2p_set_firmware(p2p); | 1305 | |
1370 | init_completion(&p2p->send_af_done); | 1306 | pri_ifp = drvr->iflist[0]; |
1307 | p2p_ifp = drvr->iflist[1]; | ||
1308 | |||
1309 | p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif; | ||
1310 | |||
1311 | if (p2p_ifp) { | ||
1312 | p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, | ||
1313 | false); | ||
1314 | if (IS_ERR(p2p_vif)) { | ||
1315 | brcmf_err("could not create discovery vif\n"); | ||
1316 | err = -ENOMEM; | ||
1317 | goto exit; | ||
1318 | } | ||
1319 | |||
1320 | p2p_vif->ifp = p2p_ifp; | ||
1321 | p2p_ifp->vif = p2p_vif; | ||
1322 | p2p_vif->wdev.netdev = p2p_ifp->ndev; | ||
1323 | p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev; | ||
1324 | SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy)); | ||
1325 | |||
1326 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; | ||
1327 | |||
1328 | brcmf_p2p_generate_bss_mac(p2p); | ||
1329 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); | ||
1330 | |||
1331 | /* Initialize P2P Discovery in the firmware */ | ||
1332 | err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); | ||
1333 | if (err < 0) { | ||
1334 | brcmf_err("set p2p_disc error\n"); | ||
1335 | brcmf_free_vif(p2p_vif); | ||
1336 | goto exit; | ||
1337 | } | ||
1338 | /* obtain bsscfg index for P2P discovery */ | ||
1339 | err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); | ||
1340 | if (err < 0) { | ||
1341 | brcmf_err("retrieving discover bsscfg index failed\n"); | ||
1342 | brcmf_free_vif(p2p_vif); | ||
1343 | goto exit; | ||
1344 | } | ||
1345 | /* Verify that firmware uses same bssidx as driver !! */ | ||
1346 | if (p2p_ifp->bssidx != bssidx) { | ||
1347 | brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n", | ||
1348 | bssidx, p2p_ifp->bssidx); | ||
1349 | brcmf_free_vif(p2p_vif); | ||
1350 | goto exit; | ||
1351 | } | ||
1352 | |||
1353 | init_completion(&p2p->send_af_done); | ||
1354 | } | ||
1355 | exit: | ||
1356 | return err; | ||
1371 | } | 1357 | } |
1372 | 1358 | ||
1359 | |||
1373 | /** | 1360 | /** |
1374 | * brcmf_p2p_detach() - detach P2P. | 1361 | * brcmf_p2p_detach() - detach P2P. |
1375 | * | 1362 | * |
@@ -1377,10 +1364,15 @@ void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, | |||
1377 | */ | 1364 | */ |
1378 | void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) | 1365 | void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) |
1379 | { | 1366 | { |
1380 | if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif != NULL) { | 1367 | struct brcmf_cfg80211_vif *vif; |
1381 | brcmf_p2p_cancel_remain_on_channel( | 1368 | |
1382 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp); | 1369 | vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; |
1370 | if (vif != NULL) { | ||
1371 | brcmf_p2p_cancel_remain_on_channel(vif->ifp); | ||
1383 | brcmf_p2p_deinit_discovery(p2p); | 1372 | brcmf_p2p_deinit_discovery(p2p); |
1373 | /* remove discovery interface */ | ||
1374 | brcmf_free_vif(vif); | ||
1375 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; | ||
1384 | } | 1376 | } |
1385 | /* just set it all to zero */ | 1377 | /* just set it all to zero */ |
1386 | memset(p2p, 0, sizeof(*p2p)); | 1378 | memset(p2p, 0, sizeof(*p2p)); |