aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
diff options
context:
space:
mode:
authorHante Meuleman <meuleman@broadcom.com>2013-02-08 09:53:52 -0500
committerJohn W. Linville <linville@tuxdriver.com>2013-02-08 14:51:40 -0500
commit2fde59d93f8ac5525213996b5e98efb8f4d8c88c (patch)
tree1a484d63173e0dd710f373ba42ee40c740053168 /drivers/net/wireless/brcm80211/brcmfmac/p2p.c
parent1ce3086ccd81793fd6affb350826a0c41dc3ef37 (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.c226
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 */
412static int brcmf_p2p_set_firmware(struct brcmf_p2p_info *p2p) 413static 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 */
441static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p) 440static 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 */
513static 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 */
591static s32 brcmf_p2p_deinit_discovery(struct brcmf_p2p_info *p2p) 515static 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);
652exit: 584exit:
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 */
1359void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, 1291s32 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 }
1355exit:
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 */
1378void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) 1365void 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));