forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_cfgp2p.c
....@@ -1,15 +1,16 @@
1
-/* SPDX-License-Identifier: GPL-2.0 */
21 /*
32 * Linux cfgp2p driver
43 *
5
- * Copyright (C) 1999-2019, Broadcom Corporation
6
- *
4
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
5
+ *
6
+ * Copyright (C) 1999-2017, Broadcom Corporation
7
+ *
78 * Unless you and Broadcom execute a separate written software license
89 * agreement governing use of this software, this software is licensed to you
910 * under the terms of the GNU General Public License version 2 (the "GPL"),
1011 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
1112 * following added to such license:
12
- *
13
+ *
1314 * As a special exception, the copyright holders of this software give you
1415 * permission to link this software with independent modules, and to copy and
1516 * distribute the resulting executable under terms of your choice, provided that
....@@ -17,7 +18,7 @@
1718 * the license of that module. An independent module is a module which is not
1819 * derived from this software. The special exception does not apply to any
1920 * modifications of the software.
20
- *
21
+ *
2122 * Notwithstanding the above, under no circumstances may you combine this
2223 * software in any way with any other Broadcom software provided under a license
2324 * other than the GPL, without Broadcom's express prior written consent.
....@@ -25,7 +26,7 @@
2526 *
2627 * <<Broadcom-WL-IPTag/Open:>>
2728 *
28
- * $Id: wl_cfgp2p.c 709309 2019-01-17 09:04:00Z $
29
+ * $Id: wl_cfgp2p.c 815562 2019-04-18 02:33:27Z $
2930 *
3031 */
3132 #include <typedefs.h>
....@@ -39,28 +40,33 @@
3940 #include <linux/string.h>
4041 #include <linux/timer.h>
4142 #include <linux/if_arp.h>
42
-#include <linux/uaccess.h>
43
+#include <asm/uaccess.h>
4344
4445 #include <bcmutils.h>
46
+#include <bcmstdlib_s.h>
4547 #include <bcmendian.h>
46
-#include <proto/ethernet.h>
47
-#include <proto/802.11.h>
48
+#include <ethernet.h>
49
+#include <802.11.h>
4850 #include <net/rtnetlink.h>
4951
5052 #include <wl_cfg80211.h>
5153 #include <wl_cfgp2p.h>
54
+#include <wl_cfgscan.h>
5255 #include <wldev_common.h>
56
+#ifdef OEM_ANDROID
5357 #include <wl_android.h>
58
+#endif // endif
5459 #include <dngl_stats.h>
5560 #include <dhd.h>
5661 #include <dhd_linux.h>
5762 #include <dhdioctl.h>
5863 #include <wlioctl.h>
5964 #include <dhd_cfg80211.h>
65
+#include <dhd_bus.h>
6066
6167 static s8 scanparambuf[WLC_IOCTL_SMLEN];
62
-static bool
63
-wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type);
68
+static bool wl_cfgp2p_has_ie(const bcm_tlv_t *ie, const u8 **tlvs, u32 *tlvs_len,
69
+ const u8 *oui, u32 oui_len, u8 type);
6470
6571 static s32 wl_cfgp2p_cancel_listen(struct bcm_cfg80211 *cfg, struct net_device *ndev,
6672 struct wireless_dev *wdev, bool notify);
....@@ -79,6 +85,22 @@
7985 };
8086 #endif /* WL_ENABLE_P2P_IF */
8187
88
+#if defined(WL_NEWCFG_PRIVCMD_SUPPORT)
89
+static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev);
90
+static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd);
91
+
92
+static int wl_cfgp2p_if_dummy(struct net_device *net)
93
+{
94
+ return 0;
95
+}
96
+
97
+static const struct net_device_ops wl_cfgp2p_if_ops = {
98
+ .ndo_open = wl_cfgp2p_if_dummy,
99
+ .ndo_stop = wl_cfgp2p_if_dummy,
100
+ .ndo_do_ioctl = wl_cfgp2p_do_ioctl,
101
+ .ndo_start_xmit = wl_cfgp2p_start_xmit,
102
+};
103
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
82104
83105 bool wl_cfgp2p_is_pub_action(void *frame, u32 frame_len)
84106 {
....@@ -126,17 +148,17 @@
126148
127149 bool wl_cfgp2p_find_gas_subtype(u8 subtype, u8* data, u32 len)
128150 {
129
- bcm_tlv_t *ie = (bcm_tlv_t *)data;
130
- u8 *frame = NULL;
151
+ const bcm_tlv_t *ie = (bcm_tlv_t *)data;
152
+ const u8 *frame = NULL;
131153 u16 id, flen;
132154
133155 /* Skipped first ANQP Element, if frame has anqp elemnt */
134
- ie = bcm_parse_tlvs(ie, (int)len, DOT11_MNG_ADVERTISEMENT_ID);
156
+ ie = bcm_parse_tlvs(ie, len, DOT11_MNG_ADVERTISEMENT_ID);
135157
136158 if (ie == NULL)
137159 return false;
138160
139
- frame = (uint8 *)ie + ie->len + TLV_HDR_LEN + GAS_RESP_LEN;
161
+ frame = (const uint8 *)ie + ie->len + TLV_HDR_LEN + GAS_RESP_LEN;
140162 id = ((u16) (((frame)[1] << 8) | (frame)[0]));
141163 flen = ((u16) (((frame)[3] << 8) | (frame)[2]));
142164
....@@ -314,7 +336,6 @@
314336 " channel=%d\n", (tx)? "TX" : "RX", channel));
315337 }
316338
317
-
318339 }
319340 }
320341
....@@ -325,7 +346,8 @@
325346 s32
326347 wl_cfgp2p_init_priv(struct bcm_cfg80211 *cfg)
327348 {
328
- if (!(cfg->p2p = kzalloc(sizeof(struct p2p_info), GFP_KERNEL))) {
349
+ cfg->p2p = MALLOCZ(cfg->osh, sizeof(struct p2p_info));
350
+ if (cfg->p2p == NULL) {
329351 CFGP2P_ERR(("struct p2p_info allocation failed\n"));
330352 return -ENOMEM;
331353 }
....@@ -338,9 +360,6 @@
338360 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION1) = -1;
339361 wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION2) = NULL;
340362 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION2) = -1;
341
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
342
- cfg->p2p->cfg = cfg;
343
-#endif
344363 return BCME_OK;
345364
346365 }
....@@ -351,9 +370,9 @@
351370 void
352371 wl_cfgp2p_deinit_priv(struct bcm_cfg80211 *cfg)
353372 {
354
- CFGP2P_ERR(("In\n"));
373
+ CFGP2P_INFO(("In\n"));
355374 if (cfg->p2p) {
356
- kfree(cfg->p2p);
375
+ MFREE(cfg->osh, cfg->p2p, sizeof(struct p2p_info));
357376 cfg->p2p = NULL;
358377 }
359378 cfg->p2p_supported = 0;
....@@ -376,7 +395,7 @@
376395 }
377396 if (val == 0) {
378397 val = 1;
379
- ret = wldev_ioctl(ndev, WLC_DOWN, &val, sizeof(s32), true);
398
+ ret = wldev_ioctl_set(ndev, WLC_DOWN, &val, sizeof(s32));
380399 if (ret < 0) {
381400 CFGP2P_ERR(("WLC_DOWN error %d\n", ret));
382401 return ret;
....@@ -389,7 +408,7 @@
389408 return ret;
390409 }
391410
392
- ret = wldev_ioctl(ndev, WLC_UP, &val, sizeof(s32), true);
411
+ ret = wldev_ioctl_set(ndev, WLC_UP, &val, sizeof(s32));
393412 if (ret < 0) {
394413 CFGP2P_ERR(("WLC_UP error %d\n", ret));
395414 return ret;
....@@ -435,27 +454,22 @@
435454 {
436455 wl_p2p_if_t ifreq;
437456 s32 err;
438
- u32 scb_timeout = WL_SCB_TIMEOUT;
439457 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
440458
441459 ifreq.type = if_type;
442460 ifreq.chspec = chspec;
443461 memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet));
444462
445
- CFGP2P_DBG(("---cfg p2p_ifadd "MACDBG" %s %u\n",
463
+ CFGP2P_ERR(("---cfg p2p_ifadd "MACDBG" %s %u\n",
446464 MAC2STRDBG(ifreq.addr.octet),
447465 (if_type == WL_P2P_IF_GO) ? "go" : "client",
448466 (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT));
449467
450468 err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq),
451469 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
452
-
453
- if (unlikely(err < 0))
470
+ if (unlikely(err < 0)) {
454471 printk("'cfg p2p_ifadd' error %d\n", err);
455
- else if (if_type == WL_P2P_IF_GO) {
456
- err = wldev_ioctl(ndev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true);
457
- if (unlikely(err < 0))
458
- printk("'cfg scb_timeout' error %d\n", err);
472
+ return err;
459473 }
460474
461475 return err;
....@@ -472,8 +486,8 @@
472486 s32 ret;
473487 struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
474488
475
- CFGP2P_INFO(("------primary idx %d : cfg p2p_ifdis "MACDBG"\n",
476
- netdev->ifindex, MAC2STRDBG(mac->octet)));
489
+ CFGP2P_INFO(("------ cfg p2p_ifdis "MACDBG" dev->ifindex:%d \n",
490
+ MAC2STRDBG(mac->octet), netdev->ifindex));
477491 ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac),
478492 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
479493 if (unlikely(ret < 0)) {
....@@ -491,15 +505,31 @@
491505 wl_cfgp2p_ifdel(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
492506 {
493507 s32 ret;
508
+#ifdef WL_DISABLE_HE_P2P
509
+ s32 bssidx = 0;
510
+#endif /* WL_DISABLE_HE_P2P */
494511 struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
495512
496
- CFGP2P_INFO(("------primary idx %d : cfg p2p_ifdel "MACDBG"\n",
497
- netdev->ifindex, MAC2STRDBG(mac->octet)));
513
+ CFGP2P_ERR(("------ cfg p2p_ifdel "MACDBG" dev->ifindex:%d\n",
514
+ MAC2STRDBG(mac->octet), netdev->ifindex));
498515 ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac),
499516 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
500517 if (unlikely(ret < 0)) {
501518 printk("'cfg p2p_ifdel' error %d\n", ret);
502519 }
520
+#ifdef WL_DISABLE_HE_P2P
521
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, netdev->ieee80211_ptr)) < 0) {
522
+ WL_ERR(("Find index failed\n"));
523
+ ret = BCME_ERROR;
524
+ return ret;
525
+ }
526
+ WL_DBG(("Enabling back HE for P2P\n"));
527
+ wl_cfg80211_set_he_mode(netdev, cfg, bssidx, WL_IF_TYPE_P2P_DISC, TRUE);
528
+ if (ret < 0) {
529
+ WL_ERR(("failed to set he features, error=%d\n", ret));
530
+ }
531
+#endif /* WL_DISABLE_HE_P2P */
532
+
503533 return ret;
504534 }
505535
....@@ -514,7 +544,6 @@
514544 {
515545 wl_p2p_if_t ifreq;
516546 s32 err;
517
- u32 scb_timeout = WL_SCB_TIMEOUT;
518547
519548 struct net_device *netdev = wl_to_p2p_bss_ndev(cfg, conn_idx);
520549
....@@ -530,18 +559,13 @@
530559
531560 err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq),
532561 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
533
-
534562 if (unlikely(err < 0)) {
535563 printk("'cfg p2p_ifupd' error %d\n", err);
536564 } else if (if_type == WL_P2P_IF_GO) {
537565 cfg->p2p->p2p_go_count++;
538
- err = wldev_ioctl(netdev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true);
539
- if (unlikely(err < 0))
540
- printk("'cfg scb_timeout' error %d\n", err);
541566 }
542567 return err;
543568 }
544
-
545569
546570 /* Get the index of a created P2P BSS.
547571 * Parameters:
....@@ -563,7 +587,7 @@
563587
564588 if (ret == 0) {
565589 memcpy(index, getbuf, sizeof(s32));
566
- CFGP2P_INFO(("---cfg p2p_if ==> %d\n", *index));
590
+ CFGP2P_DBG(("---cfg p2p_if ==> %d\n", *index));
567591 }
568592
569593 return ret;
....@@ -635,7 +659,7 @@
635659
636660 /* Put the WL driver into P2P Listen Mode to respond to P2P probe reqs */
637661 discovery_mode.state = mode;
638
- discovery_mode.chspec = wl_ch_host_to_driver(bssidx, channel);
662
+ discovery_mode.chspec = wl_ch_host_to_driver(channel);
639663 discovery_mode.dwell = listen_ms;
640664 ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_state", &discovery_mode,
641665 sizeof(discovery_mode), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
....@@ -675,7 +699,7 @@
675699 CFGP2P_ERR(("Multi p2p not supported"));
676700 return BCME_ERROR;
677701 }
678
- if ((connected_cnt = wl_get_drv_status_all(cfg, CONNECTED)) > 1) {
702
+ if ((connected_cnt = wl_get_drv_status_all(cfg, CONNECTED)) > 2) {
679703 CFGP2P_ERR(("Failed to create second p2p interface"
680704 "Already one connection exists"));
681705 return BCME_ERROR;
....@@ -693,33 +717,42 @@
693717
694718 s32 bssidx = 0;
695719 s32 ret = BCME_OK;
720
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
696721
722
+ BCM_REFERENCE(ndev);
697723 CFGP2P_DBG(("enter\n"));
698724
699725 if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) > 0) {
700726 CFGP2P_ERR(("do nothing, already initialized\n"));
701
- return ret;
727
+ goto exit;
702728 }
703729
704730 ret = wl_cfgp2p_set_discovery(cfg, 1);
705731 if (ret < 0) {
706732 CFGP2P_ERR(("set discover error\n"));
707
- return ret;
733
+ goto exit;
708734 }
709735 /* Enable P2P Discovery in the WL Driver */
710736 ret = wl_cfgp2p_get_disc_idx(cfg, &bssidx);
711
-
712737 if (ret < 0) {
713
- return ret;
738
+ goto exit;
714739 }
740
+
715741 /* In case of CFG80211 case, check if p2p_discovery interface has allocated p2p_wdev */
716742 if (!cfg->p2p_wdev) {
717743 CFGP2P_ERR(("p2p_wdev is NULL.\n"));
718
- return BCME_NODEVICE;
744
+ ret = -ENODEV;
745
+ goto exit;
719746 }
720
- /* Make an entry in the netinfo */
721
- wl_alloc_netinfo(cfg, NULL, cfg->p2p_wdev, WL_MODE_BSS, 0, bssidx);
722747
748
+ /* Once p2p also starts using interface_create iovar, the ifidx may change.
749
+ * so that time, the ifidx returned in WLC_E_IF should be used for populating
750
+ * the netinfo
751
+ */
752
+ ret = wl_alloc_netinfo(cfg, NULL, cfg->p2p_wdev, WL_IF_TYPE_STA, 0, bssidx, 0);
753
+ if (unlikely(ret)) {
754
+ goto exit;
755
+ }
723756 wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) =
724757 wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
725758 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = bssidx;
....@@ -733,7 +766,15 @@
733766 wl_cfgp2p_set_discovery(cfg, 0);
734767 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
735768 wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
736
- return 0;
769
+ ret = 0;
770
+ goto exit;
771
+ }
772
+
773
+ /* Clear our saved WPS and P2P IEs for the discovery BSS */
774
+ wl_cfg80211_clear_p2p_disc_ies(cfg);
775
+exit:
776
+ if (ret) {
777
+ wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
737778 }
738779 return ret;
739780 }
....@@ -757,7 +798,7 @@
757798 }
758799
759800 /* Clear our saved WPS and P2P IEs for the discovery BSS */
760
- wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
801
+ wl_cfg80211_clear_p2p_disc_ies(cfg);
761802
762803 /* Set the discovery state to SCAN */
763804 wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
....@@ -787,10 +828,19 @@
787828 {
788829 s32 ret = BCME_OK;
789830 s32 bssidx;
831
+ bcm_struct_cfgdev *cfgdev;
790832
791833 CFGP2P_DBG(("enter\n"));
834
+ mutex_lock(&cfg->if_sync);
835
+#ifdef WL_IFACE_MGMT
836
+ if ((ret = wl_cfg80211_handle_if_role_conflict(cfg, WL_IF_TYPE_P2P_DISC)) != BCME_OK) {
837
+ WL_ERR(("secondary iface is active, p2p enable discovery is not supported\n"));
838
+ goto exit;
839
+ }
840
+#endif /* WL_IFACE_MGMT */
841
+
792842 if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
793
- CFGP2P_INFO((" DISCOVERY is already initialized, we have nothing to do\n"));
843
+ CFGP2P_DBG((" DISCOVERY is already initialized, we have nothing to do\n"));
794844 goto set_ie;
795845 }
796846
....@@ -817,19 +867,29 @@
817867 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
818868 } else if ((bssidx = wl_get_bssidx_by_wdev(cfg, cfg->p2p_wdev)) < 0) {
819869 WL_ERR(("Find p2p index from wdev(%p) failed\n", cfg->p2p_wdev));
820
- return BCME_ERROR;
870
+ ret = BCME_ERROR;
871
+ goto exit;
821872 }
822873
823
- ret = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev),
824
- bssidx,
825
- VNDR_IE_PRBREQ_FLAG, ie, ie_len);
826
-
874
+#if defined(WL_CFG80211_P2P_DEV_IF)
875
+ /* For 3.8+ kernels, pass p2p discovery wdev */
876
+ cfgdev = cfg->p2p_wdev;
877
+#else
878
+ /* Prior to 3.8 kernel, there is no netless p2p, so pass p2p0 ndev */
879
+ cfgdev = ndev_to_cfgdev(dev);
880
+#endif /* WL_CFG80211_P2P_DEV_IF */
881
+ ret = wl_cfg80211_set_mgmt_vndr_ies(cfg, cfgdev,
882
+ bssidx, VNDR_IE_PRBREQ_FLAG, ie, ie_len);
827883 if (unlikely(ret < 0)) {
828884 CFGP2P_ERR(("set probreq ie occurs error %d\n", ret));
829885 goto exit;
830886 }
831887 }
832888 exit:
889
+ if (ret) {
890
+ wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
891
+ }
892
+ mutex_unlock(&cfg->if_sync);
833893 return ret;
834894 }
835895
....@@ -843,24 +903,21 @@
843903 {
844904 s32 ret = BCME_OK;
845905 s32 bssidx;
906
+
846907 CFGP2P_DBG((" enter\n"));
847908 wl_clr_p2p_status(cfg, DISCOVERY_ON);
848
-
849909 #ifdef DHD_IFDEBUG
850
- WL_ERR(("%s: (cfg)->p2p->bss[type].bssidx: %d\n",
910
+ WL_ERR(("%s: bssidx: %d\n",
851911 __FUNCTION__, (cfg)->p2p->bss[P2PAPI_BSSCFG_DEVICE].bssidx));
852
-#endif
912
+#endif // endif
853913 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
854914 if (bssidx <= 0) {
855915 CFGP2P_ERR((" do nothing, not initialized\n"));
856916 return 0;
857917 }
858918
859
- ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
860
- bssidx);
861
-
919
+ ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx);
862920 if (unlikely(ret < 0)) {
863
-
864921 CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n"));
865922 }
866923 /* Do a scan abort to stop the driver's scan engine in case it is still
....@@ -871,8 +928,15 @@
871928 return ret;
872929 }
873930
931
+/* Scan parameters */
932
+#define P2PAPI_SCAN_NPROBES 1
933
+#define P2PAPI_SCAN_DWELL_TIME_MS 80
934
+#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40
935
+#define P2PAPI_SCAN_HOME_TIME_MS 60
936
+#define P2PAPI_SCAN_NPROBS_TIME_MS 30
937
+#define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100
874938 s32
875
-wl_cfgp2p_escan(struct bcm_cfg80211 *cfg, struct net_device *dev, u16 active,
939
+wl_cfgp2p_escan(struct bcm_cfg80211 *cfg, struct net_device *dev, u16 active_scan,
876940 u32 num_chans, u16 *channels,
877941 s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr,
878942 p2p_scan_purpose_t p2p_scan_purpose)
....@@ -884,20 +948,26 @@
884948 s8 *memblk;
885949 wl_p2p_scan_t *p2p_params;
886950 wl_escan_params_t *eparams;
951
+ wl_escan_params_v2_t *eparams_v2;
887952 wlc_ssid_t ssid;
888
- /* Scan parameters */
889
-#define P2PAPI_SCAN_NPROBES 1
890
-#define P2PAPI_SCAN_DWELL_TIME_MS 80
891
-#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40
892
-#define P2PAPI_SCAN_HOME_TIME_MS 60
893
-#define P2PAPI_SCAN_NPROBS_TIME_MS 30
894
-#define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100
953
+ u32 sync_id = 0;
954
+ s32 nprobes = 0;
955
+ s32 active_time = 0;
956
+ const struct ether_addr *mac_addr = NULL;
957
+ u32 scan_type = 0;
958
+ struct net_device *pri_dev = NULL;
895959
896
- struct net_device *pri_dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
960
+ pri_dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
897961 /* Allocate scan params which need space for 3 channels and 0 ssids */
898
- eparams_size = (WL_SCAN_PARAMS_FIXED_SIZE +
899
- OFFSETOF(wl_escan_params_t, params)) +
900
- num_chans * sizeof(eparams->params.channel_list[0]);
962
+ if (cfg->scan_params_v2) {
963
+ eparams_size = (WL_SCAN_PARAMS_V2_FIXED_SIZE +
964
+ OFFSETOF(wl_escan_params_v2_t, params)) +
965
+ num_chans * sizeof(eparams->params.channel_list[0]);
966
+ } else {
967
+ eparams_size = (WL_SCAN_PARAMS_FIXED_SIZE +
968
+ OFFSETOF(wl_escan_params_t, params)) +
969
+ num_chans * sizeof(eparams->params.channel_list[0]);
970
+ }
901971
902972 memsize = sizeof(wl_p2p_scan_t) + eparams_size;
903973 memblk = scanparambuf;
....@@ -906,8 +976,8 @@
906976 memsize, sizeof(scanparambuf)));
907977 return -1;
908978 }
909
- memset(memblk, 0, memsize);
910
- memset(cfg->ioctl_buf, 0, WLC_IOCTL_MAXLEN);
979
+ bzero(memblk, memsize);
980
+ bzero(cfg->ioctl_buf, WLC_IOCTL_MAXLEN);
911981 if (search_state == WL_P2P_DISC_ST_SEARCH) {
912982 /*
913983 * If we in SEARCH STATE, we don't need to set SSID explictly
....@@ -916,7 +986,7 @@
916986 wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SEARCH, 0, 0, bssidx);
917987 /* use null ssid */
918988 ssid.SSID_len = 0;
919
- memset(&ssid.SSID, 0, sizeof(ssid.SSID));
989
+ bzero(&ssid.SSID, sizeof(ssid.SSID));
920990 } else if (search_state == WL_P2P_DISC_ST_SCAN) {
921991 /* SCAN STATE 802.11 SCAN
922992 * WFD Supplicant has p2p_find command with (type=progressive, type= full)
....@@ -927,91 +997,122 @@
927997 wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx);
928998 /* use wild card ssid */
929999 ssid.SSID_len = WL_P2P_WILDCARD_SSID_LEN;
930
- memset(&ssid.SSID, 0, sizeof(ssid.SSID));
1000
+ bzero(&ssid.SSID, sizeof(ssid.SSID));
9311001 memcpy(&ssid.SSID, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN);
9321002 } else {
9331003 CFGP2P_ERR((" invalid search state %d\n", search_state));
9341004 return -1;
9351005 }
9361006
937
-
9381007 /* Fill in the P2P scan structure at the start of the iovar param block */
9391008 p2p_params = (wl_p2p_scan_t*) memblk;
9401009 p2p_params->type = 'E';
941
- /* Fill in the Scan structure that follows the P2P scan structure */
942
- eparams = (wl_escan_params_t*) (p2p_params + 1);
943
- eparams->params.bss_type = DOT11_BSSTYPE_ANY;
944
- if (active)
945
- eparams->params.scan_type = DOT11_SCANTYPE_ACTIVE;
946
- else
947
- eparams->params.scan_type = DOT11_SCANTYPE_PASSIVE;
9481010
949
- if (tx_dst_addr == NULL)
950
- memcpy(&eparams->params.bssid, &ether_bcast, ETHER_ADDR_LEN);
951
- else
952
- memcpy(&eparams->params.bssid, tx_dst_addr, ETHER_ADDR_LEN);
1011
+ if (!active_scan) {
1012
+ scan_type = WL_SCANFLAGS_PASSIVE;
1013
+ }
9531014
954
- if (ssid.SSID_len)
955
- memcpy(&eparams->params.ssid, &ssid, sizeof(wlc_ssid_t));
956
-
957
- eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
1015
+ if (tx_dst_addr == NULL) {
1016
+ mac_addr = &ether_bcast;
1017
+ } else {
1018
+ mac_addr = tx_dst_addr;
1019
+ }
9581020
9591021 switch (p2p_scan_purpose) {
9601022 case P2P_SCAN_SOCIAL_CHANNEL:
961
- eparams->params.active_time = htod32(P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS);
1023
+ active_time = P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS;
9621024 break;
9631025 case P2P_SCAN_AFX_PEER_NORMAL:
9641026 case P2P_SCAN_AFX_PEER_REDUCED:
965
- eparams->params.active_time = htod32(P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS);
1027
+ active_time = P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS;
9661028 break;
9671029 case P2P_SCAN_CONNECT_TRY:
968
- eparams->params.active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
1030
+ active_time = WL_SCAN_CONNECT_DWELL_TIME_MS;
9691031 break;
970
- default :
971
- if (wl_get_drv_status_all(cfg, CONNECTED))
972
- eparams->params.active_time = -1;
973
- else
974
- eparams->params.active_time = htod32(P2PAPI_SCAN_DWELL_TIME_MS);
1032
+ default:
1033
+ active_time = wl_get_drv_status_all(cfg, CONNECTED) ?
1034
+ -1 : P2PAPI_SCAN_DWELL_TIME_MS;
9751035 break;
9761036 }
9771037
978
- if (p2p_scan_purpose == P2P_SCAN_CONNECT_TRY)
979
- eparams->params.nprobes = htod32(eparams->params.active_time /
980
- WL_SCAN_JOIN_PROBE_INTERVAL_MS);
981
- else
982
- eparams->params.nprobes = htod32((eparams->params.active_time /
983
- P2PAPI_SCAN_NPROBS_TIME_MS));
984
-
985
-
986
- if (eparams->params.nprobes <= 0)
987
- eparams->params.nprobes = 1;
988
- CFGP2P_DBG(("nprobes # %d, active_time %d\n",
989
- eparams->params.nprobes, eparams->params.active_time));
990
- eparams->params.passive_time = htod32(-1);
991
- eparams->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
992
- (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
993
-
994
- for (i = 0; i < num_chans; i++) {
995
- eparams->params.channel_list[i] = wl_ch_host_to_driver(bssidx, channels[i]);
1038
+ if (p2p_scan_purpose == P2P_SCAN_CONNECT_TRY) {
1039
+ nprobes = active_time /
1040
+ WL_SCAN_JOIN_PROBE_INTERVAL_MS;
1041
+ } else {
1042
+ nprobes = active_time /
1043
+ P2PAPI_SCAN_NPROBS_TIME_MS;
9961044 }
997
- eparams->version = htod32(ESCAN_REQ_VERSION);
998
- eparams->action = htod16(action);
999
- wl_escan_set_sync_id(eparams->sync_id, cfg);
1045
+
1046
+ if (nprobes <= 0) {
1047
+ nprobes = 1;
1048
+ }
1049
+
1050
+ wl_escan_set_sync_id(sync_id, cfg);
1051
+ /* Fill in the Scan structure that follows the P2P scan structure */
1052
+ if (cfg->scan_params_v2) {
1053
+ eparams_v2 = (wl_escan_params_v2_t*) (p2p_params + 1);
1054
+ eparams_v2->version = htod16(ESCAN_REQ_VERSION_V2);
1055
+ eparams_v2->action = htod16(action);
1056
+ eparams_v2->params.version = htod16(WL_SCAN_PARAMS_VERSION_V2);
1057
+ eparams_v2->params.length = htod16(sizeof(wl_scan_params_v2_t));
1058
+ eparams_v2->params.bss_type = DOT11_BSSTYPE_ANY;
1059
+ eparams_v2->params.scan_type = htod32(scan_type);
1060
+ (void)memcpy_s(&eparams_v2->params.bssid, ETHER_ADDR_LEN, mac_addr, ETHER_ADDR_LEN);
1061
+ eparams_v2->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
1062
+ eparams_v2->params.active_time = htod32(active_time);
1063
+ eparams_v2->params.nprobes = htod32(nprobes);
1064
+ eparams_v2->params.passive_time = htod32(-1);
1065
+ eparams_v2->sync_id = sync_id;
1066
+ for (i = 0; i < num_chans; i++) {
1067
+ eparams_v2->params.channel_list[i] =
1068
+ wl_ch_host_to_driver(channels[i]);
1069
+ }
1070
+ eparams_v2->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
1071
+ (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
1072
+ if (ssid.SSID_len)
1073
+ (void)memcpy_s(&eparams_v2->params.ssid,
1074
+ sizeof(wlc_ssid_t), &ssid, sizeof(wlc_ssid_t));
1075
+ sync_id = eparams_v2->sync_id;
1076
+ } else {
1077
+ eparams = (wl_escan_params_t*) (p2p_params + 1);
1078
+ eparams->version = htod32(ESCAN_REQ_VERSION);
1079
+ eparams->action = htod16(action);
1080
+ eparams->params.bss_type = DOT11_BSSTYPE_ANY;
1081
+ eparams->params.scan_type = htod32(scan_type);
1082
+ (void)memcpy_s(&eparams->params.bssid, ETHER_ADDR_LEN, mac_addr, ETHER_ADDR_LEN);
1083
+ eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
1084
+ eparams->params.active_time = htod32(active_time);
1085
+ eparams->params.nprobes = htod32(nprobes);
1086
+ eparams->params.passive_time = htod32(-1);
1087
+ eparams->sync_id = sync_id;
1088
+ for (i = 0; i < num_chans; i++) {
1089
+ eparams->params.channel_list[i] =
1090
+ wl_ch_host_to_driver(channels[i]);
1091
+ }
1092
+ eparams->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
1093
+ (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
1094
+ if (ssid.SSID_len)
1095
+ (void)memcpy_s(&eparams->params.ssid,
1096
+ sizeof(wlc_ssid_t), &ssid, sizeof(wlc_ssid_t));
1097
+ sync_id = eparams->sync_id;
1098
+ }
1099
+
10001100 wl_escan_set_type(cfg, WL_SCANTYPE_P2P);
1001
- CFGP2P_INFO(("SCAN CHANNELS : "));
10021101
1003
- for (i = 0; i < num_chans; i++) {
1004
- if (i == 0) CFGP2P_INFO(("%d", channels[i]));
1005
- else CFGP2P_INFO((",%d", channels[i]));
1102
+ CFGP2P_DBG(("nprobes:%d active_time:%d\n", nprobes, active_time));
1103
+ CFGP2P_DBG(("SCAN CHANNELS : "));
1104
+ CFGP2P_DBG(("%d", channels[0]));
1105
+ for (i = 1; i < num_chans; i++) {
1106
+ CFGP2P_DBG((",%d", channels[i]));
10061107 }
1007
-
1008
- CFGP2P_INFO(("\n"));
1108
+ CFGP2P_DBG(("\n"));
10091109
10101110 ret = wldev_iovar_setbuf_bsscfg(pri_dev, "p2p_scan",
10111111 memblk, memsize, cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
1012
- WL_ERR(("P2P_SEARCH sync ID: %d, bssidx: %d\n", eparams->sync_id, bssidx));
1013
- if (ret == BCME_OK)
1112
+ WL_INFORM(("P2P_SEARCH sync ID: %d, bssidx: %d\n", sync_id, bssidx));
1113
+ if (ret == BCME_OK) {
10141114 wl_set_p2p_status(cfg, SCANNING);
1115
+ }
10151116 return ret;
10161117 }
10171118
....@@ -1039,7 +1140,17 @@
10391140 chan_cnt = AF_PEER_SEARCH_CNT;
10401141 else
10411142 chan_cnt = SOCIAL_CHAN_CNT;
1042
- default_chan_list = kzalloc(chan_cnt * sizeof(*default_chan_list), GFP_KERNEL);
1143
+
1144
+ if (cfg->afx_hdl->pending_tx_act_frm && cfg->afx_hdl->is_active) {
1145
+ wl_action_frame_t *action_frame;
1146
+ action_frame = &(cfg->afx_hdl->pending_tx_act_frm->action_frame);
1147
+ if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len)) {
1148
+ chan_cnt = 1;
1149
+ p2p_scan_purpose = P2P_SCAN_AFX_PEER_REDUCED;
1150
+ }
1151
+ }
1152
+
1153
+ default_chan_list = (u16 *)MALLOCZ(cfg->osh, chan_cnt * sizeof(*default_chan_list));
10431154 if (default_chan_list == NULL) {
10441155 CFGP2P_ERR(("channel list allocation failed \n"));
10451156 ret = -ENOMEM;
....@@ -1059,7 +1170,7 @@
10591170 ret = wl_cfgp2p_escan(cfg, ndev, true, chan_cnt,
10601171 default_chan_list, WL_P2P_DISC_ST_SEARCH,
10611172 WL_SCAN_ACTION_START, bssidx, NULL, p2p_scan_purpose);
1062
- kfree(default_chan_list);
1173
+ MFREE(cfg->osh, default_chan_list, chan_cnt * sizeof(*default_chan_list));
10631174 exit:
10641175 return ret;
10651176 }
....@@ -1076,90 +1187,87 @@
10761187 /* Check whether the given IE looks like WFA WFDisplay IE. */
10771188 #ifndef WFA_OUI_TYPE_WFD
10781189 #define WFA_OUI_TYPE_WFD 0x0a /* WiFi Display OUI TYPE */
1079
-#endif
1190
+#endif // endif
10801191 #define wl_cfgp2p_is_wfd_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
10811192 (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
1082
-
10831193
10841194 /* Is any of the tlvs the expected entry? If
10851195 * not update the tlvs buffer pointer/length.
10861196 */
10871197 static bool
1088
-wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type)
1198
+wl_cfgp2p_has_ie(const bcm_tlv_t *ie, const u8 **tlvs, u32 *tlvs_len,
1199
+ const u8 *oui, u32 oui_len, u8 type)
10891200 {
10901201 /* If the contents match the OUI and the type */
1091
- if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
1092
- !bcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
1093
- type == ie[TLV_BODY_OFF + oui_len]) {
1202
+ if (ie->len >= oui_len + 1 &&
1203
+ !bcmp(ie->data, oui, oui_len) &&
1204
+ type == ie->data[oui_len]) {
10941205 return TRUE;
10951206 }
10961207
1097
- if (tlvs == NULL)
1098
- return FALSE;
10991208 /* point to the next ie */
1100
- ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
1101
- /* calculate the length of the rest of the buffer */
1102
- *tlvs_len -= (int)(ie - *tlvs);
1103
- /* update the pointer to the start of the buffer */
1104
- *tlvs = ie;
1209
+ if (tlvs != NULL) {
1210
+ bcm_tlv_buffer_advance_past(ie, tlvs, tlvs_len);
1211
+ }
11051212
11061213 return FALSE;
11071214 }
11081215
1109
-wpa_ie_fixed_t *
1110
-wl_cfgp2p_find_wpaie(u8 *parse, u32 len)
1216
+const wpa_ie_fixed_t *
1217
+wl_cfgp2p_find_wpaie(const u8 *parse, u32 len)
11111218 {
1112
- bcm_tlv_t *ie;
1219
+ const bcm_tlv_t *ie;
11131220
1114
- while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_VS_ID))) {
1115
- if (wl_cfgp2p_is_wpa_ie((u8*)ie, &parse, &len)) {
1116
- return (wpa_ie_fixed_t *)ie;
1221
+ while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
1222
+ if (wl_cfgp2p_is_wpa_ie(ie, &parse, &len)) {
1223
+ return (const wpa_ie_fixed_t *)ie;
11171224 }
11181225 }
11191226 return NULL;
11201227 }
11211228
1122
-wpa_ie_fixed_t *
1123
-wl_cfgp2p_find_wpsie(u8 *parse, u32 len)
1229
+const wpa_ie_fixed_t *
1230
+wl_cfgp2p_find_wpsie(const u8 *parse, u32 len)
11241231 {
1125
- bcm_tlv_t *ie;
1232
+ const bcm_tlv_t *ie;
11261233
1127
- while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_VS_ID))) {
1128
- if (wl_cfgp2p_is_wps_ie((u8*)ie, &parse, &len)) {
1129
- return (wpa_ie_fixed_t *)ie;
1234
+ while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
1235
+ if (wl_cfgp2p_is_wps_ie(ie, &parse, &len)) {
1236
+ return (const wpa_ie_fixed_t *)ie;
11301237 }
11311238 }
11321239 return NULL;
11331240 }
11341241
11351242 wifi_p2p_ie_t *
1136
-wl_cfgp2p_find_p2pie(u8 *parse, u32 len)
1243
+wl_cfgp2p_find_p2pie(const u8 *parse, u32 len)
11371244 {
11381245 bcm_tlv_t *ie;
11391246
1140
- while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
1141
- if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len)) {
1247
+ while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
1248
+ if (wl_cfgp2p_is_p2p_ie(ie, &parse, &len)) {
11421249 return (wifi_p2p_ie_t *)ie;
11431250 }
11441251 }
11451252 return NULL;
11461253 }
11471254
1148
-wifi_wfd_ie_t *
1149
-wl_cfgp2p_find_wfdie(u8 *parse, u32 len)
1255
+const wifi_wfd_ie_t *
1256
+wl_cfgp2p_find_wfdie(const u8 *parse, u32 len)
11501257 {
1151
- bcm_tlv_t *ie;
1258
+ const bcm_tlv_t *ie;
11521259
1153
- while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
1154
- if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) {
1155
- return (wifi_wfd_ie_t *)ie;
1260
+ while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
1261
+ if (wl_cfgp2p_is_wfd_ie(ie, &parse, &len)) {
1262
+ return (const wifi_wfd_ie_t *)ie;
11561263 }
11571264 }
11581265 return NULL;
11591266 }
1267
+
11601268 u32
11611269 wl_cfgp2p_vndr_ie(struct bcm_cfg80211 *cfg, u8 *iebuf, s32 pktflag,
1162
- s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd)
1270
+ s8 *oui, s32 ie_id, const s8 *data, s32 datalen, const s8* add_del_cmd)
11631271 {
11641272 vndr_ie_setbuf_t hdr; /* aligned temporary vndr_ie buffer header */
11651273 s32 iecount;
....@@ -1168,18 +1276,23 @@
11681276 /* Validate the pktflag parameter */
11691277 if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
11701278 VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
1171
- VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG))) {
1279
+ VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG |
1280
+ VNDR_IE_DISASSOC_FLAG))) {
11721281 CFGP2P_ERR(("p2pwl_vndr_ie: Invalid packet flag 0x%x\n", pktflag));
11731282 return -1;
11741283 }
11751284
11761285 /* Copy the vndr_ie SET command ("add"/"del") to the buffer */
1177
- strncpy(hdr.cmd, add_del_cmd, VNDR_IE_CMD_LEN - 1);
1178
- hdr.cmd[VNDR_IE_CMD_LEN - 1] = '\0';
1286
+ strlcpy(hdr.cmd, add_del_cmd, sizeof(hdr.cmd));
11791287
11801288 /* Set the IE count - the buffer contains only 1 IE */
11811289 iecount = htod32(1);
11821290 memcpy((void *)&hdr.vndr_ie_buffer.iecount, &iecount, sizeof(s32));
1291
+
1292
+ /* For vendor ID DOT11_MNG_ID_EXT_ID, need to set pkt flag to VNDR_IE_CUSTOM_FLAG */
1293
+ if (ie_id == DOT11_MNG_ID_EXT_ID) {
1294
+ pktflag = pktflag | VNDR_IE_CUSTOM_FLAG;
1295
+ }
11831296
11841297 /* Copy packet flags that indicate which packets will contain this IE */
11851298 pktflag = htod32(pktflag);
....@@ -1249,7 +1362,10 @@
12491362 CFGP2P_ERR((" argument is invalid\n"));
12501363 goto exit;
12511364 }
1252
-
1365
+ if (!cfg->p2p) {
1366
+ CFGP2P_ERR(("p2p if does not exist\n"));
1367
+ goto exit;
1368
+ }
12531369 for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
12541370 if (bssidx == wl_to_p2p_bss_bssidx(cfg, i)) {
12551371 *type = i;
....@@ -1276,10 +1392,31 @@
12761392
12771393 CFGP2P_DBG((" Enter\n"));
12781394 #ifdef DHD_IFDEBUG
1279
- WL_ERR(("%s: cfg: %p, cfgdev: %p, cfg->wdev: %p, cfg->p2p_wdev: %p\n",
1280
- __FUNCTION__, cfg, cfgdev, cfg->wdev, cfg->p2p_wdev));
1281
-#endif
1395
+ PRINT_WDEV_INFO(cfgdev);
1396
+#endif /* DHD_IFDEBUG */
1397
+
12821398 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
1399
+
1400
+#ifdef P2P_LISTEN_OFFLOADING
1401
+ if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
1402
+ wl_clr_p2p_status(cfg, DISC_IN_PROGRESS);
1403
+ CFGP2P_ERR(("DISC_IN_PROGRESS cleared\n"));
1404
+ if (ndev && (ndev->ieee80211_ptr != NULL)) {
1405
+#if defined(WL_CFG80211_P2P_DEV_IF)
1406
+ if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy) {
1407
+ cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
1408
+ &cfg->remain_on_chan, GFP_KERNEL);
1409
+ } else {
1410
+ CFGP2P_ERR(("Invalid cfgdev. Dropping the"
1411
+ "remain_on_channel_expired event.\n"));
1412
+ }
1413
+#else
1414
+ cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
1415
+ &cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
1416
+#endif /* WL_CFG80211_P2P_DEV_IF */
1417
+ }
1418
+ }
1419
+#endif /* P2P_LISTEN_OFFLOADING */
12831420
12841421 if (wl_get_p2p_status(cfg, LISTEN_EXPIRED) == 0) {
12851422 wl_set_p2p_status(cfg, LISTEN_EXPIRED);
....@@ -1318,20 +1455,36 @@
13181455 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
13191456 if (ndev && (ndev->ieee80211_ptr != NULL)) {
13201457 #if defined(WL_CFG80211_P2P_DEV_IF)
1321
- if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy) {
1458
+ if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy &&
1459
+ bcmcfg_to_p2p_wdev(cfg)) {
13221460 /*
13231461 * To prevent kernel panic,
13241462 * if cfgdev->wiphy may be invalid, adding explicit check
13251463 */
1326
- cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
1327
- &cfg->remain_on_chan, GFP_KERNEL);
1328
- } else {
1464
+ struct wireless_dev *wdev_dpp_listen = NULL;
1465
+ wdev_dpp_listen = wl_get_wdev_by_dpp_listen(cfg);
1466
+ /*
1467
+ * check if dpp listen was trigerred
1468
+ * if so, clear dpp disten flag and route the event for listen
1469
+ * complete on the interface on which listen was reqeusted.
1470
+ */
1471
+ if (wdev_dpp_listen) {
1472
+ wl_set_dpp_listen_by_netdev(cfg, wdev_dpp_listen->netdev, 0);
1473
+ cfg80211_remain_on_channel_expired(wdev_dpp_listen,
1474
+ cfg->last_roc_id, &cfg->remain_on_chan, GFP_KERNEL);
1475
+ } else {
1476
+ cfg80211_remain_on_channel_expired(bcmcfg_to_p2p_wdev(cfg),
1477
+ cfg->last_roc_id, &cfg->remain_on_chan, GFP_KERNEL);
1478
+ }
1479
+
1480
+ } else
13291481 CFGP2P_ERR(("Invalid cfgdev. Dropping the"
13301482 "remain_on_channel_expired event.\n"));
1331
- }
13321483 #else
1333
- cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
1334
- &cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
1484
+ if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy)
1485
+ cfg80211_remain_on_channel_expired(cfgdev,
1486
+ cfg->last_roc_id, &cfg->remain_on_chan,
1487
+ cfg->remain_on_chan_type, GFP_KERNEL);
13351488 #endif /* WL_CFG80211_P2P_DEV_IF */
13361489 }
13371490 }
....@@ -1351,30 +1504,32 @@
13511504 * We can't report cfg80211_remain_on_channel_expired from Timer ISR context,
13521505 * so lets do it from thread context.
13531506 */
1354
-
13551507 void
1356
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
1357
-wl_cfgp2p_listen_expired(struct timer_list *t)
1358
-{
1359
- struct p2p_info *p2p = from_timer(p2p, t, listen_timer);
1360
- struct bcm_cfg80211 *cfg = p2p->cfg;
1361
-#else
13621508 wl_cfgp2p_listen_expired(unsigned long data)
13631509 {
1364
- struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *) data;
1365
-#endif
13661510 wl_event_msg_t msg;
1511
+ struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *) data;
1512
+ struct net_device *ndev;
13671513 CFGP2P_DBG((" Enter\n"));
1514
+
1515
+ if (!cfg) {
1516
+ CFGP2P_ERR((" No cfg\n"));
1517
+ return;
1518
+ }
13681519 bzero(&msg, sizeof(wl_event_msg_t));
13691520 msg.event_type = hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE);
13701521 msg.bsscfgidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
13711522 #if defined(WL_ENABLE_P2P_IF)
1372
- wl_cfg80211_event(cfg->p2p_net ? cfg->p2p_net :
1373
- wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), &msg, NULL);
1523
+ ndev = cfg->p2p_net ? cfg->p2p_net :
1524
+ wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE);
13741525 #else
1375
- wl_cfg80211_event(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), &msg,
1376
- NULL);
1526
+ ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE);
13771527 #endif /* WL_ENABLE_P2P_IF */
1528
+ if (!ndev) {
1529
+ CFGP2P_ERR((" No ndev\n"));
1530
+ return;
1531
+ }
1532
+ wl_cfg80211_event(ndev, &msg, NULL);
13781533 }
13791534 /*
13801535 * Routine for cancelling the P2P LISTEN
....@@ -1391,7 +1546,7 @@
13911546 del_timer_sync(&cfg->p2p->listen_timer);
13921547 if (notify) {
13931548 #if defined(WL_CFG80211_P2P_DEV_IF)
1394
- if (wdev)
1549
+ if (bcmcfg_to_p2p_wdev(cfg))
13951550 cfg80211_remain_on_channel_expired(wdev, cfg->last_roc_id,
13961551 &cfg->remain_on_chan, GFP_KERNEL);
13971552 #else
....@@ -1419,7 +1574,7 @@
14191574 {
14201575 #define EXTRA_DELAY_TIME 100
14211576 s32 ret = BCME_OK;
1422
- struct timer_list *_timer;
1577
+ timer_list_compat_t *_timer;
14231578 s32 extra_delay;
14241579 struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
14251580
....@@ -1469,7 +1624,6 @@
14691624 return ret;
14701625 }
14711626
1472
-
14731627 s32
14741628 wl_cfgp2p_discover_enable_search(struct bcm_cfg80211 *cfg, u8 enable)
14751629 {
....@@ -1509,6 +1663,8 @@
15091663 u32 event_type = ntoh32(e->event_type);
15101664 u32 status = ntoh32(e->status);
15111665 struct net_device *ndev = NULL;
1666
+ u8 bsscfgidx = e->bsscfgidx;
1667
+
15121668 CFGP2P_DBG((" Enter\n"));
15131669
15141670 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
....@@ -1516,22 +1672,26 @@
15161672 if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
15171673 if (event_type == WLC_E_ACTION_FRAME_COMPLETE) {
15181674
1519
- CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status));
1675
+ CFGP2P_DBG((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status));
15201676 if (status == WLC_E_STATUS_SUCCESS) {
15211677 wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
1522
- CFGP2P_DBG(("WLC_E_ACTION_FRAME_COMPLETE : ACK\n"));
1678
+ CFGP2P_ACTION(("TX actfrm : ACK\n"));
15231679 if (!cfg->need_wait_afrx && cfg->af_sent_channel) {
15241680 CFGP2P_DBG(("no need to wait next AF.\n"));
1525
- wl_stop_wait_next_action_frame(cfg, ndev);
1681
+ wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
15261682 }
15271683 }
15281684 else if (!wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) {
15291685 wl_set_p2p_status(cfg, ACTION_TX_NOACK);
1530
- CFGP2P_INFO(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n"));
1531
- wl_stop_wait_next_action_frame(cfg, ndev);
1686
+ if (status == WLC_E_STATUS_SUPPRESS) {
1687
+ CFGP2P_ACTION(("TX actfrm : SUPPRES\n"));
1688
+ } else {
1689
+ CFGP2P_ACTION(("TX actfrm : NO ACK\n"));
1690
+ }
1691
+ wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
15321692 }
15331693 } else {
1534
- CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received,"
1694
+ CFGP2P_DBG((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received,"
15351695 "status : %d\n", status));
15361696
15371697 if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
....@@ -1557,9 +1717,8 @@
15571717 s32 timeout = 0;
15581718 wl_eventmsg_buf_t buf;
15591719
1560
-
1561
- CFGP2P_INFO(("\n"));
1562
- CFGP2P_INFO(("channel : %u , dwell time : %u\n",
1720
+ CFGP2P_DBG(("\n"));
1721
+ CFGP2P_DBG(("channel : %u , dwell time : %u\n",
15631722 af_params->channel, af_params->dwell_time));
15641723
15651724 wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED);
....@@ -1580,7 +1739,7 @@
15801739 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
15811740
15821741 if (ret < 0) {
1583
- CFGP2P_ERR((" sending action frame is failed\n"));
1742
+ CFGP2P_ACTION(("TX actfrm : ERROR\n"));
15841743 goto exit;
15851744 }
15861745
....@@ -1588,21 +1747,21 @@
15881747 msecs_to_jiffies(af_params->dwell_time + WL_AF_TX_EXTRA_TIME_MAX));
15891748
15901749 if (timeout >= 0 && wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) {
1591
- CFGP2P_INFO(("tx action frame operation is completed\n"));
1750
+ CFGP2P_DBG(("tx action frame operation is completed\n"));
15921751 ret = BCME_OK;
15931752 } else if (ETHER_ISBCAST(&cfg->afx_hdl->tx_dst_addr)) {
1594
- CFGP2P_INFO(("bcast tx action frame operation is completed\n"));
1753
+ CFGP2P_DBG(("bcast tx action frame operation is completed\n"));
15951754 ret = BCME_OK;
15961755 } else {
15971756 ret = BCME_ERROR;
1598
- CFGP2P_INFO(("tx action frame operation is failed\n"));
1757
+ CFGP2P_DBG(("tx action frame operation is failed\n"));
15991758 }
16001759 /* clear status bit for action tx */
16011760 wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED);
16021761 wl_clr_p2p_status(cfg, ACTION_TX_NOACK);
16031762
16041763 exit:
1605
- CFGP2P_INFO((" via act frame iovar : status = %d\n", ret));
1764
+ CFGP2P_DBG((" via act frame iovar : status = %d\n", ret));
16061765
16071766 bzero(&buf, sizeof(wl_eventmsg_buf_t));
16081767 wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, false);
....@@ -1688,64 +1847,7 @@
16881847 subel += subelt_len;
16891848 }
16901849 }
1691
-/*
1692
- * Check if a BSS is up.
1693
- * This is a common implementation called by most OSL implementations of
1694
- * p2posl_bss_isup(). DO NOT call this function directly from the
1695
- * common code -- call p2posl_bss_isup() instead to allow the OSL to
1696
- * override the common implementation if necessary.
1697
- */
1698
-bool
1699
-wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx)
1700
-{
1701
- s32 result, val;
1702
- bool isup = false;
1703
- s8 getbuf[64];
17041850
1705
- /* Check if the BSS is up */
1706
- *(int*)getbuf = -1;
1707
- result = wldev_iovar_getbuf_bsscfg(ndev, "bss", &bsscfg_idx,
1708
- sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0, NULL);
1709
- if (result != 0) {
1710
- CFGP2P_ERR(("'cfg bss -C %d' failed: %d\n", bsscfg_idx, result));
1711
- CFGP2P_ERR(("NOTE: this ioctl error is normal "
1712
- "when the BSS has not been created yet.\n"));
1713
- } else {
1714
- val = *(int*)getbuf;
1715
- val = dtoh32(val);
1716
- CFGP2P_INFO(("---cfg bss -C %d ==> %d\n", bsscfg_idx, val));
1717
- isup = (val ? TRUE : FALSE);
1718
- }
1719
- return isup;
1720
-}
1721
-
1722
-
1723
-/* Bring up or down a BSS */
1724
-s32
1725
-wl_cfgp2p_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bsscfg_idx, s32 is_up)
1726
-{
1727
- s32 ret = BCME_OK;
1728
- s32 val = is_up ? 1 : 0;
1729
-
1730
- struct {
1731
- s32 cfg;
1732
- s32 val;
1733
- } bss_setbuf;
1734
-
1735
- bss_setbuf.cfg = htod32(bsscfg_idx);
1736
- bss_setbuf.val = htod32(val);
1737
- CFGP2P_INFO(("---cfg bss -C %d %s\n", bsscfg_idx, is_up ? "up" : "down"));
1738
- ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
1739
- cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
1740
-
1741
- if (ret != 0) {
1742
- CFGP2P_ERR(("'bss %d' failed with %d\n", is_up, ret));
1743
- }
1744
-
1745
- return ret;
1746
-}
1747
-
1748
-/* Check if 'p2p' is supported in the driver */
17491851 s32
17501852 wl_cfgp2p_supported(struct bcm_cfg80211 *cfg, struct net_device *ndev)
17511853 {
....@@ -1776,7 +1878,6 @@
17761878 {
17771879 struct net_device *ndev = NULL;
17781880 struct wireless_dev *wdev = NULL;
1779
- s32 i = 0, index = -1;
17801881
17811882 #if defined(WL_CFG80211_P2P_DEV_IF)
17821883 ndev = bcmcfg_to_prmry_ndev(cfg);
....@@ -1788,18 +1889,21 @@
17881889
17891890 wl_cfgp2p_cancel_listen(cfg, ndev, wdev, TRUE);
17901891 wl_cfgp2p_disable_discovery(cfg);
1791
-#if defined(WL_CFG80211_P2P_DEV_IF)
1892
+
1893
+#if defined(WL_CFG80211_P2P_DEV_IF) && !defined(KEEP_WIFION_OPTION)
1894
+/*
1895
+ * In CUSTOMER_HW4 implementation "ifconfig wlan0 down" can get
1896
+ * called during phone suspend and customer requires the p2p
1897
+ * discovery interface to be left untouched so that the user
1898
+ * space can resume without any problem.
1899
+ */
17921900 if (cfg->p2p_wdev) {
17931901 /* If p2p wdev is left out, clean it up */
17941902 WL_ERR(("Clean up the p2p discovery IF\n"));
17951903 wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
17961904 }
1797
-#endif /* WL_CFG80211_P2P_DEV_IF */
1798
- for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
1799
- index = wl_to_p2p_bss_bssidx(cfg, i);
1800
- if (index != WL_INVALID)
1801
- wl_cfg80211_clear_per_bss_ies(cfg, index);
1802
- }
1905
+#endif /* WL_CFG80211_P2P_DEV_IF !defined(KEEP_WIFION_OPTION) */
1906
+
18031907 wl_cfgp2p_deinit_priv(cfg);
18041908 return 0;
18051909 }
....@@ -1821,9 +1925,10 @@
18211925 int count, start, duration;
18221926 wl_p2p_sched_t dongle_noa;
18231927 s32 bssidx, type;
1928
+ int iovar_len = sizeof(dongle_noa);
18241929 CFGP2P_DBG((" Enter\n"));
18251930
1826
- memset(&dongle_noa, 0, sizeof(dongle_noa));
1931
+ bzero(&dongle_noa, sizeof(dongle_noa));
18271932
18281933 if (wl_cfgp2p_vif_created(cfg)) {
18291934 cfg->p2p->noa.desc[0].start = 0;
....@@ -1882,8 +1987,12 @@
18821987 if (wl_cfgp2p_find_type(cfg, bssidx, &type) != BCME_OK)
18831988 return BCME_ERROR;
18841989
1990
+ if (dongle_noa.action == WL_P2P_SCHED_ACTION_RESET) {
1991
+ iovar_len -= sizeof(wl_p2p_sched_desc_t);
1992
+ }
1993
+
18851994 ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(cfg, type),
1886
- "p2p_noa", &dongle_noa, sizeof(dongle_noa), cfg->ioctl_buf,
1995
+ "p2p_noa", &dongle_noa, iovar_len, cfg->ioctl_buf,
18871996 WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
18881997
18891998 if (ret < 0) {
....@@ -1972,8 +2081,8 @@
19722081 }
19732082
19742083 if ((legacy_ps != -1) && ((legacy_ps == PM_MAX) || (legacy_ps == PM_OFF))) {
1975
- ret = wldev_ioctl(dev,
1976
- WLC_SET_PM, &legacy_ps, sizeof(legacy_ps), true);
2084
+ ret = wldev_ioctl_set(dev,
2085
+ WLC_SET_PM, &legacy_ps, sizeof(legacy_ps));
19772086 if (unlikely(ret))
19782087 CFGP2P_ERR(("error (%d)\n", ret));
19792088 wl_cfg80211_update_power_mode(dev);
....@@ -2015,11 +2124,12 @@
20152124 return BCME_ERROR;
20162125 }
20172126
2127
+ memset_s(&csa_arg, sizeof(csa_arg), 0, sizeof(csa_arg));
20182128 csa_arg.mode = DOT11_CSA_MODE_ADVISORY;
20192129 csa_arg.count = P2P_ECSA_CNT;
20202130 csa_arg.reg = 0;
20212131
2022
- sprintf(buf, "%d/%d", ch, bw);
2132
+ snprintf(buf, len, "%d/%d", ch, bw);
20232133 chnsp = wf_chspec_aton(buf);
20242134 if (chnsp == 0) {
20252135 CFGP2P_ERR(("%s:chsp is not correct\n", __FUNCTION__));
....@@ -2041,12 +2151,46 @@
20412151 return BCME_OK;
20422152 }
20432153
2044
-u8 *
2045
-wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id)
2154
+s32
2155
+wl_cfgp2p_increase_p2p_bw(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len)
20462156 {
2047
- wifi_p2p_ie_t *ie = NULL;
2157
+ int algo;
2158
+ int bw;
2159
+ int ret = BCME_OK;
2160
+
2161
+ sscanf(buf, "%3d", &bw);
2162
+ if (bw == 0) {
2163
+ algo = 0;
2164
+ ret = wldev_iovar_setbuf(ndev, "mchan_algo", &algo, sizeof(algo), cfg->ioctl_buf,
2165
+ WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
2166
+ if (ret < 0) {
2167
+ CFGP2P_ERR(("fw set mchan_algo failed %d\n", ret));
2168
+ return BCME_ERROR;
2169
+ }
2170
+ } else {
2171
+ algo = 1;
2172
+ ret = wldev_iovar_setbuf(ndev, "mchan_algo", &algo, sizeof(algo), cfg->ioctl_buf,
2173
+ WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
2174
+ if (ret < 0) {
2175
+ CFGP2P_ERR(("fw set mchan_algo failed %d\n", ret));
2176
+ return BCME_ERROR;
2177
+ }
2178
+ ret = wldev_iovar_setbuf(ndev, "mchan_bw", &bw, sizeof(algo), cfg->ioctl_buf,
2179
+ WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
2180
+ if (ret < 0) {
2181
+ CFGP2P_ERR(("fw set mchan_bw failed %d\n", ret));
2182
+ return BCME_ERROR;
2183
+ }
2184
+ }
2185
+ return BCME_OK;
2186
+}
2187
+
2188
+const u8 *
2189
+wl_cfgp2p_retreive_p2pattrib(const void *buf, u8 element_id)
2190
+{
2191
+ const wifi_p2p_ie_t *ie = NULL;
20482192 u16 len = 0;
2049
- u8 *subel;
2193
+ const u8 *subel;
20502194 u8 subelt_id;
20512195 u16 subelt_len;
20522196
....@@ -2055,7 +2199,7 @@
20552199 return 0;
20562200 }
20572201
2058
- ie = (wifi_p2p_ie_t*) buf;
2202
+ ie = (const wifi_p2p_ie_t*) buf;
20592203 len = ie->len;
20602204
20612205 /* Point subel to the P2P IE's subelt field.
....@@ -2094,43 +2238,50 @@
20942238
20952239 #define P2P_GROUP_CAPAB_GO_BIT 0x01
20962240
2097
-u8*
2098
-wl_cfgp2p_find_attrib_in_all_p2p_Ies(u8 *parse, u32 len, u32 attrib)
2241
+const u8*
2242
+wl_cfgp2p_find_attrib_in_all_p2p_Ies(const u8 *parse, u32 len, u32 attrib)
20992243 {
21002244 bcm_tlv_t *ie;
2101
- u8* pAttrib;
2245
+ const u8* pAttrib;
2246
+ uint ie_len;
21022247
2103
- CFGP2P_INFO(("Starting parsing parse %p attrib %d remaining len %d ", parse, attrib, len));
2104
- while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
2105
- if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len) == TRUE) {
2248
+ CFGP2P_DBG(("Starting parsing parse %p attrib %d remaining len %d ", parse, attrib, len));
2249
+ ie_len = len;
2250
+ while ((ie = bcm_parse_tlvs(parse, ie_len, DOT11_MNG_VS_ID))) {
2251
+ if (wl_cfgp2p_is_p2p_ie(ie, &parse, &ie_len) == TRUE) {
21062252 /* Have the P2p ie. Now check for attribute */
2107
- if ((pAttrib = wl_cfgp2p_retreive_p2pattrib(parse, attrib)) != NULL) {
2108
- CFGP2P_INFO(("P2P attribute %d was found at parse %p",
2253
+ if ((pAttrib = wl_cfgp2p_retreive_p2pattrib(ie, attrib)) != NULL) {
2254
+ CFGP2P_DBG(("P2P attribute %d was found at parse %p",
21092255 attrib, parse));
21102256 return pAttrib;
21112257 }
21122258 else {
2113
- parse += (ie->len + TLV_HDR_LEN);
2114
- len -= (ie->len + TLV_HDR_LEN);
2259
+ /* move to next IE */
2260
+ bcm_tlv_buffer_advance_past(ie, &parse, &ie_len);
2261
+
21152262 CFGP2P_INFO(("P2P Attribute %d not found Moving parse"
2116
- " to %p len to %d", attrib, parse, len));
2263
+ " to %p len to %d", attrib, parse, ie_len));
21172264 }
21182265 }
21192266 else {
21202267 /* It was not p2p IE. parse will get updated automatically to next TLV */
2121
- CFGP2P_INFO(("IT was NOT P2P IE parse %p len %d", parse, len));
2268
+ CFGP2P_INFO(("IT was NOT P2P IE parse %p len %d", parse, ie_len));
21222269 }
21232270 }
21242271 CFGP2P_ERR(("P2P attribute %d was NOT found", attrib));
21252272 return NULL;
21262273 }
21272274
2128
-u8 *
2275
+const u8 *
21292276 wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length)
21302277 {
2131
- u8 *capability = NULL;
2278
+ const u8 *capability = NULL;
21322279 bool p2p_go = 0;
2133
- u8 *ptr = NULL;
2280
+ const u8 *ptr = NULL;
2281
+
2282
+ if (bi->length != bi->ie_offset + bi->ie_length) {
2283
+ return NULL;
2284
+ }
21342285
21352286 if ((capability = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
21362287 bi->ie_length, P2P_SEID_P2P_INFO)) == NULL) {
....@@ -2173,13 +2324,15 @@
21732324 };
21742325 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
21752326
2176
-#if defined(WL_ENABLE_P2P_IF)
2327
+#if defined(WL_ENABLE_P2P_IF) || defined(WL_NEWCFG_PRIVCMD_SUPPORT)
21772328 s32
21782329 wl_cfgp2p_register_ndev(struct bcm_cfg80211 *cfg)
21792330 {
21802331 int ret = 0;
21812332 struct net_device* net = NULL;
2333
+#ifndef WL_NEWCFG_PRIVCMD_SUPPORT
21822334 struct wireless_dev *wdev = NULL;
2335
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
21832336 uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x33, 0x22, 0x11 };
21842337
21852338 if (cfg->p2p_net) {
....@@ -2193,15 +2346,16 @@
21932346 return -ENODEV;
21942347 }
21952348
2196
- wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
2349
+#ifndef WL_NEWCFG_PRIVCMD_SUPPORT
2350
+ wdev = (struct wireless_dev *)MALLOCZ(cfg->osh, sizeof(*wdev));
21972351 if (unlikely(!wdev)) {
21982352 WL_ERR(("Could not allocate wireless device\n"));
21992353 free_netdev(net);
22002354 return -ENOMEM;
22012355 }
2356
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
22022357
2203
- strncpy(net->name, "p2p%d", sizeof(net->name) - 1);
2204
- net->name[IFNAMSIZ - 1] = '\0';
2358
+ strlcpy(net->name, "p2p%d", sizeof(net->name));
22052359
22062360 /* Copy the reference to bcm_cfg80211 */
22072361 memcpy((void *)netdev_priv(net), &cfg, sizeof(struct bcm_cfg80211 *));
....@@ -2215,38 +2369,50 @@
22152369 #else
22162370 ASSERT(!net->netdev_ops);
22172371 net->netdev_ops = &wl_cfgp2p_if_ops;
2218
-#endif
2372
+#endif // endif
22192373
22202374 /* Register with a dummy MAC addr */
22212375 memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN);
22222376
2377
+#ifndef WL_NEWCFG_PRIVCMD_SUPPORT
22232378 wdev->wiphy = cfg->wdev->wiphy;
22242379
22252380 wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
22262381
22272382 net->ieee80211_ptr = wdev;
2383
+#else
2384
+ net->ieee80211_ptr = NULL;
2385
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
22282386
22292387 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
22302388 net->ethtool_ops = &cfgp2p_ethtool_ops;
22312389 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
22322390
2391
+#ifndef WL_NEWCFG_PRIVCMD_SUPPORT
22332392 SET_NETDEV_DEV(net, wiphy_dev(wdev->wiphy));
22342393
22352394 /* Associate p2p0 network interface with new wdev */
22362395 wdev->netdev = net;
2396
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
22372397
22382398 ret = register_netdev(net);
22392399 if (ret) {
22402400 CFGP2P_ERR((" register_netdevice failed (%d)\n", ret));
22412401 free_netdev(net);
2242
- kfree(wdev);
2402
+#ifndef WL_NEWCFG_PRIVCMD_SUPPORT
2403
+ MFREE(cfg->osh, wdev, sizeof(*wdev));
2404
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
22432405 return -ENODEV;
22442406 }
22452407
22462408 /* store p2p net ptr for further reference. Note that iflist won't have this
22472409 * entry as there corresponding firmware interface is a "Hidden" interface.
22482410 */
2411
+#ifndef WL_NEWCFG_PRIVCMD_SUPPORT
22492412 cfg->p2p_wdev = wdev;
2413
+#else
2414
+ cfg->p2p_wdev = NULL;
2415
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
22502416 cfg->p2p_net = net;
22512417
22522418 printk("%s: P2P Interface Registered\n", net->name);
....@@ -2292,7 +2458,11 @@
22922458 * For Android PRIV CMD handling map it to primary I/F
22932459 */
22942460 if (cmd == SIOCDEVPRIVATE+1) {
2295
- ret = wl_android_priv_cmd(ndev, ifr, cmd);
2461
+#if defined(OEM_ANDROID)
2462
+ ret = wl_android_priv_cmd(ndev, ifr);
2463
+#else
2464
+ (void)ndev;
2465
+#endif // endif
22962466
22972467 } else {
22982468 CFGP2P_ERR(("%s: IOCTL req 0x%x on p2p0 I/F. Ignoring. \n",
....@@ -2302,14 +2472,14 @@
23022472
23032473 return ret;
23042474 }
2305
-#endif
2475
+#endif /* WL_ENABLE_P2P_IF || WL_NEWCFG_PRIVCMD_SUPPORT */
23062476
23072477 #if defined(WL_ENABLE_P2P_IF)
23082478 static int wl_cfgp2p_if_open(struct net_device *net)
23092479 {
23102480 struct wireless_dev *wdev = net->ieee80211_ptr;
23112481
2312
- if (!wdev || !wl_cfg80211_is_p2p_active())
2482
+ if (!wdev || !wl_cfg80211_is_p2p_active(net))
23132483 return -EINVAL;
23142484 WL_TRACE(("Enter\n"));
23152485 #if !defined(WL_IFACE_COMB_NUM_CHANNELS)
....@@ -2330,11 +2500,12 @@
23302500 static int wl_cfgp2p_if_stop(struct net_device *net)
23312501 {
23322502 struct wireless_dev *wdev = net->ieee80211_ptr;
2503
+ struct bcm_cfg80211 *cfg = wl_get_cfg(net);
23332504
23342505 if (!wdev)
23352506 return -EINVAL;
23362507
2337
- wl_cfg80211_scan_stop(net);
2508
+ wl_cfg80211_scan_stop(cfg, net);
23382509
23392510 #if !defined(WL_IFACE_COMB_NUM_CHANNELS)
23402511 wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes)
....@@ -2363,27 +2534,54 @@
23632534 WL_TRACE(("Enter\n"));
23642535
23652536 if (cfg->p2p_wdev) {
2366
- /*
2367
- * This is not expected. This can happen due to
2368
- * supplicant crash/unclean de-initialization which
2369
- * didn't free the p2p discovery interface. Indicate
2370
- * driver hang to user space so that the framework
2371
- * can rei-init the Wi-Fi.
2372
- */
2537
+#ifndef EXPLICIT_DISCIF_CLEANUP
2538
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
2539
+#endif /* EXPLICIT_DISCIF_CLEANUP */
2540
+ /*
2541
+ * This is not expected. This can happen due to
2542
+ * supplicant crash/unclean de-initialization which
2543
+ * didn't free the p2p discovery interface. Indicate
2544
+ * driver hang to user space so that the framework
2545
+ * can rei-init the Wi-Fi.
2546
+ */
23732547 CFGP2P_ERR(("p2p_wdev defined already.\n"));
23742548 wl_probe_wdev_all(cfg);
2375
-
2549
+#ifdef EXPLICIT_DISCIF_CLEANUP
2550
+ /*
2551
+ * CUSTOMER_HW4 design doesn't delete the p2p discovery
2552
+ * interface on ifconfig wlan0 down context which comes
2553
+ * without a preceeding NL80211_CMD_DEL_INTERFACE for p2p
2554
+ * discovery. But during supplicant crash the DEL_IFACE
2555
+ * command will not happen and will cause a left over iface
2556
+ * even after ifconfig wlan0 down. So delete the iface
2557
+ * first and then indicate the HANG event
2558
+ */
2559
+ wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
2560
+#else
2561
+ dhd->hang_reason = HANG_REASON_IFACE_DEL_FAILURE;
2562
+#ifdef OEM_ANDROID
2563
+#if defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
2564
+ if (dhd->memdump_enabled) {
2565
+ /* Load the dongle side dump to host
2566
+ * memory and then BUG_ON()
2567
+ */
2568
+ dhd->memdump_type = DUMP_TYPE_IFACE_OP_FAILURE;
2569
+ dhd_bus_mem_dump(dhd);
2570
+ }
2571
+#endif /* BCMPCIE && DHD_FW_COREDUMP */
23762572 net_os_send_hang_message(bcmcfg_to_prmry_ndev(cfg));
2573
+#endif /* OEM_ANDROID */
23772574 return ERR_PTR(-ENODEV);
2575
+#endif /* EXPLICIT_DISCIF_CLEANUP */
23782576 }
23792577
2380
- wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
2578
+ wdev = (struct wireless_dev *)MALLOCZ(cfg->osh, sizeof(*wdev));
23812579 if (unlikely(!wdev)) {
23822580 WL_ERR(("Could not allocate wireless device\n"));
23832581 return ERR_PTR(-ENOMEM);
23842582 }
23852583
2386
- memset(&primary_mac, 0, sizeof(primary_mac));
2584
+ bzero(&primary_mac, sizeof(primary_mac));
23872585 get_primary_mac(cfg, &primary_mac);
23882586 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
23892587
....@@ -2391,12 +2589,16 @@
23912589 wdev->iftype = NL80211_IFTYPE_P2P_DEVICE;
23922590 memcpy(wdev->address, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE), ETHER_ADDR_LEN);
23932591
2592
+#if defined(WL_NEWCFG_PRIVCMD_SUPPORT)
2593
+ if (cfg->p2p_net)
2594
+ memcpy(cfg->p2p_net->dev_addr, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE),
2595
+ ETHER_ADDR_LEN);
2596
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
23942597
23952598 /* store p2p wdev ptr for further reference. */
23962599 cfg->p2p_wdev = wdev;
23972600
23982601 CFGP2P_ERR(("P2P interface registered\n"));
2399
-
24002602 return wdev;
24012603 }
24022604
....@@ -2426,7 +2628,7 @@
24262628 p2p_on(cfg) = true;
24272629 #if defined(P2P_IE_MISSING_FIX)
24282630 cfg->p2p_prb_noti = false;
2429
-#endif
2631
+#endif // endif
24302632
24312633 CFGP2P_DBG(("P2P interface started\n"));
24322634
....@@ -2438,6 +2640,7 @@
24382640 wl_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
24392641 {
24402642 int ret = 0;
2643
+ struct net_device *ndev = NULL;
24412644 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
24422645
24432646 if (!cfg)
....@@ -2445,13 +2648,28 @@
24452648
24462649 CFGP2P_DBG(("Enter\n"));
24472650
2448
- ret = wl_cfg80211_scan_stop(wdev);
2651
+ /* Check if cfg80211 interface is already down */
2652
+ ndev = bcmcfg_to_prmry_ndev(cfg);
2653
+ if (!wl_get_drv_status(cfg, READY, ndev)) {
2654
+ WL_DBG(("cfg80211 interface is already down\n"));
2655
+ return; /* it is even not ready */
2656
+ }
2657
+
2658
+ ret = wl_cfg80211_scan_stop(cfg, wdev);
24492659 if (unlikely(ret < 0)) {
24502660 CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret));
24512661 }
24522662
2453
- if (!cfg->p2p)
2663
+ if (!p2p_is_on(cfg)) {
24542664 return;
2665
+ }
2666
+
2667
+#ifdef P2P_LISTEN_OFFLOADING
2668
+ wl_cfg80211_p2plo_deinit(cfg);
2669
+#endif /* P2P_LISTEN_OFFLOADING */
2670
+
2671
+ /* Cancel any on-going listen */
2672
+ wl_cfgp2p_cancel_listen(cfg, bcmcfg_to_prmry_ndev(cfg), wdev, TRUE);
24552673
24562674 ret = wl_cfgp2p_disable_discovery(cfg);
24572675 if (unlikely(ret < 0)) {
....@@ -2470,10 +2688,12 @@
24702688 {
24712689 bool rollback_lock = false;
24722690
2473
- if (!wdev)
2691
+ if (!wdev || !cfg) {
2692
+ WL_ERR(("null ptr. wdev:%p cfg:%p\n", wdev, cfg));
24742693 return -EINVAL;
2694
+ }
24752695
2476
- WL_TRACE(("Enter\n"));
2696
+ WL_INFORM(("Enter\n"));
24772697
24782698 if (!rtnl_is_locked()) {
24792699 rtnl_lock();
....@@ -2487,10 +2707,9 @@
24872707
24882708 synchronize_rcu();
24892709
2490
- kfree(wdev);
2710
+ MFREE(cfg->osh, wdev, sizeof(*wdev));
24912711
2492
- if (cfg)
2493
- cfg->p2p_wdev = NULL;
2712
+ cfg->p2p_wdev = NULL;
24942713
24952714 CFGP2P_ERR(("P2P interface unregistered\n"));
24962715