diff options
Diffstat (limited to 'drivers/net/wireless/bcmdhd/wl_cfgp2p.c')
-rw-r--r-- | drivers/net/wireless/bcmdhd/wl_cfgp2p.c | 1020 |
1 files changed, 648 insertions, 372 deletions
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index 00334f5..12b4949 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -1,7 +1,7 @@ /* * Linux cfgp2p driver * - * Copyright (C) 1999-2012, Broadcom Corporation + * Copyright (C) 1999-2014, Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_cfgp2p.c 391443 2013-03-18 07:53:46Z $ + * $Id: wl_cfgp2p.c 454364 2014-02-10 09:20:25Z $ * */ #include <typedefs.h> @@ -53,22 +53,41 @@ static bool wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type); static u32 -wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 pktflag, +wl_cfgp2p_vndr_ie(struct bcm_cfg80211 *cfg, u8 *iebuf, s32 pktflag, s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd); +static s32 wl_cfgp2p_cancel_listen(struct bcm_cfg80211 *cfg, struct net_device *ndev, + struct wireless_dev *wdev, bool notify); +#if defined(WL_ENABLE_P2P_IF) static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev); static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd); static int wl_cfgp2p_if_open(struct net_device *net); static int wl_cfgp2p_if_stop(struct net_device *net); -static s32 wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev, - bool notify); static const struct net_device_ops wl_cfgp2p_if_ops = { - .ndo_open = wl_cfgp2p_if_open, - .ndo_stop = wl_cfgp2p_if_stop, - .ndo_do_ioctl = wl_cfgp2p_do_ioctl, - .ndo_start_xmit = wl_cfgp2p_start_xmit, + .ndo_open = wl_cfgp2p_if_open, + .ndo_stop = wl_cfgp2p_if_stop, + .ndo_do_ioctl = wl_cfgp2p_do_ioctl, + .ndo_start_xmit = wl_cfgp2p_start_xmit, }; +#endif /* WL_ENABLE_P2P_IF */ + +#if defined(WL_NEWCFG_PRIVCMD_SUPPORT) +static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev); +static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd); + +static int wl_cfgp2p_if_dummy(struct net_device *net) +{ + return 0; +} + +static const struct net_device_ops wl_cfgp2p_if_ops = { + .ndo_open = wl_cfgp2p_if_dummy, + .ndo_stop = wl_cfgp2p_if_dummy, + .ndo_do_ioctl = wl_cfgp2p_do_ioctl, + .ndo_start_xmit = wl_cfgp2p_start_xmit, +}; +#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */ bool wl_cfgp2p_is_pub_action(void *frame, u32 frame_len) { @@ -109,7 +128,6 @@ bool wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len) return false; } -#ifdef WL11U #define GAS_RESP_LEN 2 #define DOUBLE_TLV_BODY_OFF 4 #define GAS_RESP_OFFSET 4 @@ -141,7 +159,6 @@ bool wl_cfgp2p_find_gas_subtype(u8 subtype, u8* data, u32 len) return false; } -#endif /* WL11U */ bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len) { @@ -152,7 +169,7 @@ bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len) return false; sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame; - if (frame_len < sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1) + if (frame_len < (sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1)) return false; if (sd_act_frm->category != P2PSD_ACTION_CATEGORY) return false; @@ -182,6 +199,29 @@ bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len) return false; #endif /* WL11U */ } +#ifdef CUSTOMER_HW4 +bool wl_cfgp2p_is_p2p_gas_action(void *frame, u32 frame_len) +{ + + wifi_p2psd_gas_pub_act_frame_t *sd_act_frm; + + if (frame == NULL) + return false; + + sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame; + if (frame_len < (sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1)) + return false; + if (sd_act_frm->category != P2PSD_ACTION_CATEGORY) + return false; + + if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ) + return wl_cfgp2p_find_gas_subtype(P2PSD_GAS_OUI_SUBTYPE, + (u8 *)sd_act_frm->query_data, + frame_len); + else + return false; +} +#endif /* CUSTOMER_HW4 */ void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len, u32 channel) { wifi_p2p_pub_act_frame_t *pact_frm; @@ -292,17 +332,17 @@ void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len, u32 channel) * */ s32 -wl_cfgp2p_init_priv(struct wl_priv *wl) +wl_cfgp2p_init_priv(struct bcm_cfg80211 *cfg) { - if (!(wl->p2p = kzalloc(sizeof(struct p2p_info), GFP_KERNEL))) { + if (!(cfg->p2p = kzalloc(sizeof(struct p2p_info), GFP_KERNEL))) { CFGP2P_ERR(("struct p2p_info allocation failed\n")); return -ENOMEM; } #define INIT_IE(IE_TYPE, BSS_TYPE) \ do { \ - memset(wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie, 0, \ - sizeof(wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie)); \ - wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie_len = 0; \ + memset(wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie, 0, \ + sizeof(wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie)); \ + wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie_len = 0; \ } while (0); INIT_IE(probe_req, P2PAPI_BSSCFG_PRIMARY); @@ -321,12 +361,12 @@ wl_cfgp2p_init_priv(struct wl_priv *wl) INIT_IE(assoc_res, P2PAPI_BSSCFG_CONNECTION); INIT_IE(beacon, P2PAPI_BSSCFG_CONNECTION); #undef INIT_IE - wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY) = wl_to_prmry_ndev(wl); - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY) = 0; - wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE) = NULL; - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) = 0; - wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = NULL; - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = 0; + wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY) = bcmcfg_to_prmry_ndev(cfg); + wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY) = 0; + wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL; + wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0; + wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION) = NULL; + wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION) = 0; return BCME_OK; } @@ -335,22 +375,22 @@ wl_cfgp2p_init_priv(struct wl_priv *wl) * */ void -wl_cfgp2p_deinit_priv(struct wl_priv *wl) +wl_cfgp2p_deinit_priv(struct bcm_cfg80211 *cfg) { CFGP2P_DBG(("In\n")); - if (wl->p2p) { - kfree(wl->p2p); - wl->p2p = NULL; + if (cfg->p2p) { + kfree(cfg->p2p); + cfg->p2p = NULL; } - wl->p2p_supported = 0; + cfg->p2p_supported = 0; } /* * Set P2P functions into firmware */ s32 -wl_cfgp2p_set_firm_p2p(struct wl_priv *wl) +wl_cfgp2p_set_firm_p2p(struct bcm_cfg80211 *cfg) { - struct net_device *ndev = wl_to_prmry_ndev(wl); + struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg); struct ether_addr null_eth_addr = { { 0, 0, 0, 0, 0, 0 } }; s32 ret = BCME_OK; s32 val = 0; @@ -380,7 +420,7 @@ wl_cfgp2p_set_firm_p2p(struct wl_priv *wl) * firmware for P2P device address */ ret = wldev_iovar_setbuf_bsscfg(ndev, "p2p_da_override", &null_eth_addr, - sizeof(null_eth_addr), wl->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &wl->ioctl_buf_sync); + sizeof(null_eth_addr), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &cfg->ioctl_buf_sync); if (ret && ret != BCME_UNSUPPORTED) { CFGP2P_ERR(("failed to update device address ret %d\n", ret)); } @@ -395,74 +435,74 @@ wl_cfgp2p_set_firm_p2p(struct wl_priv *wl) * Returns 0 if success. */ s32 -wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, +wl_cfgp2p_ifadd(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type, chanspec_t chspec) { wl_p2p_if_t ifreq; s32 err; u32 scb_timeout = WL_SCB_TIMEOUT; - struct net_device *ndev = wl_to_prmry_ndev(wl); + struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg); ifreq.type = if_type; ifreq.chspec = chspec; memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet)); - CFGP2P_DBG(("---wl p2p_ifadd "MACDBG" %s %u\n", + CFGP2P_DBG(("---cfg p2p_ifadd "MACDBG" %s %u\n", MAC2STRDBG(ifreq.addr.octet), (if_type == WL_P2P_IF_GO) ? "go" : "client", (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT)); err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq), - wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); + cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync); if (unlikely(err < 0)) - printk("'wl p2p_ifadd' error %d\n", err); + printk("'cfg p2p_ifadd' error %d\n", err); else if (if_type == WL_P2P_IF_GO) { err = wldev_ioctl(ndev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true); if (unlikely(err < 0)) - printk("'wl scb_timeout' error %d\n", err); + printk("'cfg scb_timeout' error %d\n", err); } return err; } /* Disable a P2P BSS. * Parameters: - * @mac : MAC address of the BSS to create + * @mac : MAC address of the BSS to disable * Returns 0 if success. */ s32 -wl_cfgp2p_ifdisable(struct wl_priv *wl, struct ether_addr *mac) +wl_cfgp2p_ifdisable(struct bcm_cfg80211 *cfg, struct ether_addr *mac) { s32 ret; - struct net_device *netdev = wl_to_prmry_ndev(wl); + struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg); - CFGP2P_INFO(("------primary idx %d : wl p2p_ifdis "MACDBG"\n", + CFGP2P_INFO(("------primary idx %d : cfg p2p_ifdis "MACDBG"\n", netdev->ifindex, MAC2STRDBG(mac->octet))); ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac), - wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); + cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync); if (unlikely(ret < 0)) { - printk("'wl p2p_ifdis' error %d\n", ret); + printk("'cfg p2p_ifdis' error %d\n", ret); } return ret; } /* Delete a P2P BSS. * Parameters: - * @mac : MAC address of the BSS to create + * @mac : MAC address of the BSS to delete * Returns 0 if success. */ s32 -wl_cfgp2p_ifdel(struct wl_priv *wl, struct ether_addr *mac) +wl_cfgp2p_ifdel(struct bcm_cfg80211 *cfg, struct ether_addr *mac) { s32 ret; - struct net_device *netdev = wl_to_prmry_ndev(wl); + struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg); - CFGP2P_INFO(("------primary idx %d : wl p2p_ifdel "MACDBG"\n", + CFGP2P_INFO(("------primary idx %d : cfg p2p_ifdel "MACDBG"\n", netdev->ifindex, MAC2STRDBG(mac->octet))); ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac), - wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); + cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync); if (unlikely(ret < 0)) { - printk("'wl p2p_ifdel' error %d\n", ret); + printk("'cfg p2p_ifdel' error %d\n", ret); } return ret; } @@ -473,34 +513,34 @@ wl_cfgp2p_ifdel(struct wl_priv *wl, struct ether_addr *mac) * Returns 0 if success. */ s32 -wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, +wl_cfgp2p_ifchange(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type, chanspec_t chspec) { wl_p2p_if_t ifreq; s32 err; u32 scb_timeout = WL_SCB_TIMEOUT; - struct net_device *netdev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); + struct net_device *netdev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION); ifreq.type = if_type; ifreq.chspec = chspec; memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet)); - CFGP2P_INFO(("---wl p2p_ifchange "MACDBG" %s %u" + CFGP2P_INFO(("---cfg p2p_ifchange "MACDBG" %s %u" " chanspec 0x%04x\n", MAC2STRDBG(ifreq.addr.octet), (if_type == WL_P2P_IF_GO) ? "go" : "client", (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT, ifreq.chspec)); err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq), - wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); + cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync); if (unlikely(err < 0)) { - printk("'wl p2p_ifupd' error %d\n", err); + printk("'cfg p2p_ifupd' error %d\n", err); } else if (if_type == WL_P2P_IF_GO) { err = wldev_ioctl(netdev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true); if (unlikely(err < 0)) - printk("'wl scb_timeout' error %d\n", err); + printk("'cfg scb_timeout' error %d\n", err); } return err; } @@ -513,30 +553,30 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, * Returns 0 if success. */ s32 -wl_cfgp2p_ifidx(struct wl_priv *wl, struct ether_addr *mac, s32 *index) +wl_cfgp2p_ifidx(struct bcm_cfg80211 *cfg, struct ether_addr *mac, s32 *index) { s32 ret; u8 getbuf[64]; - struct net_device *dev = wl_to_prmry_ndev(wl); + struct net_device *dev = bcmcfg_to_prmry_ndev(cfg); - CFGP2P_INFO(("---wl p2p_if "MACDBG"\n", MAC2STRDBG(mac->octet))); + CFGP2P_INFO(("---cfg p2p_if "MACDBG"\n", MAC2STRDBG(mac->octet))); ret = wldev_iovar_getbuf_bsscfg(dev, "p2p_if", mac, sizeof(*mac), getbuf, - sizeof(getbuf), wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY), NULL); + sizeof(getbuf), wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY), NULL); if (ret == 0) { memcpy(index, getbuf, sizeof(s32)); - CFGP2P_INFO(("---wl p2p_if ==> %d\n", *index)); + CFGP2P_INFO(("---cfg p2p_if ==> %d\n", *index)); } return ret; } static s32 -wl_cfgp2p_set_discovery(struct wl_priv *wl, s32 on) +wl_cfgp2p_set_discovery(struct bcm_cfg80211 *cfg, s32 on) { s32 ret = BCME_OK; - struct net_device *ndev = wl_to_prmry_ndev(wl); + struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg); CFGP2P_DBG(("enter\n")); ret = wldev_iovar_setint(ndev, "p2p_disc", on); @@ -558,7 +598,7 @@ wl_cfgp2p_set_discovery(struct wl_priv *wl, s32 on) */ s32 -wl_cfgp2p_set_p2p_mode(struct wl_priv *wl, u8 mode, u32 channel, u16 listen_ms, int bssidx) +wl_cfgp2p_set_p2p_mode(struct bcm_cfg80211 *cfg, u8 mode, u32 channel, u16 listen_ms, int bssidx) { wl_p2p_disc_st_t discovery_mode; s32 ret; @@ -570,7 +610,7 @@ wl_cfgp2p_set_p2p_mode(struct wl_priv *wl, u8 mode, u32 channel, u16 listen_ms, return -1; } - dev = wl_cfgp2p_find_ndev(wl, bssidx); + dev = wl_cfgp2p_find_ndev(cfg, bssidx); if (unlikely(dev == NULL)) { CFGP2P_ERR(("bssidx %d is not assigned\n", bssidx)); return BCME_NOTFOUND; @@ -581,18 +621,18 @@ wl_cfgp2p_set_p2p_mode(struct wl_priv *wl, u8 mode, u32 channel, u16 listen_ms, discovery_mode.chspec = wl_ch_host_to_driver(channel); discovery_mode.dwell = listen_ms; ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_state", &discovery_mode, - sizeof(discovery_mode), wl->ioctl_buf, WLC_IOCTL_MAXLEN, - bssidx, &wl->ioctl_buf_sync); + sizeof(discovery_mode), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, + bssidx, &cfg->ioctl_buf_sync); return ret; } /* Get the index of the P2P Discovery BSS */ static s32 -wl_cfgp2p_get_disc_idx(struct wl_priv *wl, s32 *index) +wl_cfgp2p_get_disc_idx(struct bcm_cfg80211 *cfg, s32 *index) { s32 ret; - struct net_device *dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY); + struct net_device *dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY); ret = wldev_iovar_getint(dev, "p2p_dev", index); CFGP2P_INFO(("p2p_dev bsscfg_idx=%d ret=%d\n", *index, ret)); @@ -605,7 +645,7 @@ wl_cfgp2p_get_disc_idx(struct wl_priv *wl, s32 *index) } s32 -wl_cfgp2p_init_discovery(struct wl_priv *wl) +wl_cfgp2p_init_discovery(struct bcm_cfg80211 *cfg) { s32 index = 0; @@ -613,35 +653,35 @@ wl_cfgp2p_init_discovery(struct wl_priv *wl) CFGP2P_DBG(("enter\n")); - if (wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) != 0) { + if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) != 0) { CFGP2P_ERR(("do nothing, already initialized\n")); return ret; } - ret = wl_cfgp2p_set_discovery(wl, 1); + ret = wl_cfgp2p_set_discovery(cfg, 1); if (ret < 0) { CFGP2P_ERR(("set discover error\n")); return ret; } /* Enable P2P Discovery in the WL Driver */ - ret = wl_cfgp2p_get_disc_idx(wl, &index); + ret = wl_cfgp2p_get_disc_idx(cfg, &index); if (ret < 0) { return ret; } - wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE) = - wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY); - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) = index; + wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = + wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY); + wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = index; /* Set the initial discovery state to SCAN */ - ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); + ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, + wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE)); if (unlikely(ret != 0)) { CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n")); - wl_cfgp2p_set_discovery(wl, 0); - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) = 0; - wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE) = NULL; + wl_cfgp2p_set_discovery(cfg, 0); + wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0; + wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL; return 0; } return ret; @@ -649,24 +689,24 @@ wl_cfgp2p_init_discovery(struct wl_priv *wl) /* Deinitialize P2P Discovery * Parameters : - * @wl : wl_private data + * @cfg : wl_private data * Returns 0 if succes */ static s32 -wl_cfgp2p_deinit_discovery(struct wl_priv *wl) +wl_cfgp2p_deinit_discovery(struct bcm_cfg80211 *cfg) { s32 ret = BCME_OK; CFGP2P_DBG(("enter\n")); - if (wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) == 0) { + if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) == 0) { CFGP2P_ERR(("do nothing, not initialized\n")); return -1; } /* Set the discovery state to SCAN */ - ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); + ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, + wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE)); /* Disable P2P discovery in the WL driver (deletes the discovery BSSCFG) */ - ret = wl_cfgp2p_set_discovery(wl, 0); + ret = wl_cfgp2p_set_discovery(cfg, 0); /* Clear our saved WPS and P2P IEs for the discovery BSS. The driver * deleted these IEs when wl_cfgp2p_set_discovery() deleted the discovery @@ -676,42 +716,36 @@ wl_cfgp2p_deinit_discovery(struct wl_priv *wl) /* Clear the saved bsscfg index of the discovery BSSCFG to indicate we * have no discovery BSS. */ - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) = WL_INVALID; - wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE) = NULL; + wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = WL_INVALID; + wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL; return ret; } /* Enable P2P Discovery * Parameters: - * @wl : wl_private data + * @cfg : wl_private data * @ie : probe request ie (WPS IE + P2P IE) * @ie_len : probe request ie length * Returns 0 if success. */ s32 -wl_cfgp2p_enable_discovery(struct wl_priv *wl, struct net_device *dev, +wl_cfgp2p_enable_discovery(struct bcm_cfg80211 *cfg, struct net_device *dev, const u8 *ie, u32 ie_len) { s32 ret = BCME_OK; s32 bssidx; - if (wl_to_prmry_ndev(wl) == dev) { - bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); - } else if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { - WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); - return BCME_ERROR; - } - if (wl_get_p2p_status(wl, DISCOVERY_ON)) { + if (wl_get_p2p_status(cfg, DISCOVERY_ON)) { CFGP2P_INFO((" DISCOVERY is already initialized, we have nothing to do\n")); goto set_ie; } - wl_set_p2p_status(wl, DISCOVERY_ON); + wl_set_p2p_status(cfg, DISCOVERY_ON); CFGP2P_DBG(("enter\n")); - ret = wl_cfgp2p_init_discovery(wl); + ret = wl_cfgp2p_init_discovery(cfg); if (unlikely(ret < 0)) { CFGP2P_ERR((" init discovery error %d\n", ret)); goto exit; @@ -720,14 +754,21 @@ wl_cfgp2p_enable_discovery(struct wl_priv *wl, struct net_device *dev, * P2P probe responses have the privacy bit set in the 802.11 WPA IE. * Some peer devices may not initiate WPS with us if this bit is not set. */ - ret = wldev_iovar_setint_bsscfg(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), - "wsec", AES_ENABLED, wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); + ret = wldev_iovar_setint_bsscfg(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), + "wsec", AES_ENABLED, wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE)); if (unlikely(ret < 0)) { CFGP2P_ERR((" wsec error %d\n", ret)); } set_ie: if (ie_len) { - ret = wl_cfgp2p_set_management_ie(wl, dev, + if (bcmcfg_to_prmry_ndev(cfg) == dev) { + bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE); + } else if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } + + ret = wl_cfgp2p_set_management_ie(cfg, dev, bssidx, VNDR_IE_PRBREQ_FLAG, ie, ie_len); @@ -742,23 +783,23 @@ exit: /* Disable P2P Discovery * Parameters: - * @wl : wl_private_data + * @cfg : wl_private_data * Returns 0 if success. */ s32 -wl_cfgp2p_disable_discovery(struct wl_priv *wl) +wl_cfgp2p_disable_discovery(struct bcm_cfg80211 *cfg) { s32 ret = BCME_OK; CFGP2P_DBG((" enter\n")); - wl_clr_p2p_status(wl, DISCOVERY_ON); + wl_clr_p2p_status(cfg, DISCOVERY_ON); - if (wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) == 0) { + if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) == 0) { CFGP2P_ERR((" do nothing, not initialized\n")); goto exit; } - ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); + ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, + wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE)); if (unlikely(ret < 0)) { @@ -768,21 +809,22 @@ wl_cfgp2p_disable_discovery(struct wl_priv *wl) * waiting out an action frame tx dwell time. */ #ifdef NOT_YET - if (wl_get_p2p_status(wl, SCANNING)) { + if (wl_get_p2p_status(cfg, SCANNING)) { p2pwlu_scan_abort(hdl, FALSE); } #endif - wl_clr_p2p_status(wl, DISCOVERY_ON); - ret = wl_cfgp2p_deinit_discovery(wl); + wl_clr_p2p_status(cfg, DISCOVERY_ON); + ret = wl_cfgp2p_deinit_discovery(cfg); exit: return ret; } s32 -wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, +wl_cfgp2p_escan(struct bcm_cfg80211 *cfg, struct net_device *dev, u16 active, u32 num_chans, u16 *channels, - s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr) + s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr, + p2p_scan_purpose_t p2p_scan_purpose) { s32 ret = BCME_OK; s32 memsize; @@ -800,7 +842,7 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, #define P2PAPI_SCAN_NPROBS_TIME_MS 30 #define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100 - struct net_device *pri_dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY); + struct net_device *pri_dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY); /* Allocate scan params which need space for 3 channels and 0 ssids */ eparams_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params)) + @@ -814,13 +856,13 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, return -1; } memset(memblk, 0, memsize); - memset(wl->ioctl_buf, 0, WLC_IOCTL_MAXLEN); + memset(cfg->ioctl_buf, 0, WLC_IOCTL_MAXLEN); if (search_state == WL_P2P_DISC_ST_SEARCH) { /* * If we in SEARCH STATE, we don't need to set SSID explictly * because dongle use P2P WILDCARD internally by default */ - wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SEARCH, 0, 0, bssidx); + wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SEARCH, 0, 0, bssidx); /* use null ssid */ ssid.SSID_len = 0; memset(&ssid.SSID, 0, sizeof(ssid.SSID)); @@ -831,7 +873,7 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, * we have to set ssid to P2P WILDCARD because * we just do broadcast scan unless setting SSID */ - wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx); + wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx); /* use wild card ssid */ ssid.SSID_len = WL_P2P_WILDCARD_SSID_LEN; memset(&ssid.SSID, 0, sizeof(ssid.SSID)); @@ -863,26 +905,32 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS); - /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by - * the supplicant - */ - if ((num_chans == SOCIAL_CHAN_CNT) || (num_chans == SOCIAL_CHAN_CNT + 1)) + switch (p2p_scan_purpose) { + case P2P_SCAN_SOCIAL_CHANNEL: eparams->params.active_time = htod32(P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS); - else if (num_chans == AF_PEER_SEARCH_CNT) + break; + case P2P_SCAN_AFX_PEER_NORMAL: + case P2P_SCAN_AFX_PEER_REDUCED: eparams->params.active_time = htod32(P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS); - else if (wl_get_drv_status_all(wl, CONNECTED)) + break; + case P2P_SCAN_CONNECT_TRY: + eparams->params.active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS); + break; + default : + if (wl_get_drv_status_all(cfg, CONNECTED)) eparams->params.active_time = -1; else eparams->params.active_time = htod32(P2PAPI_SCAN_DWELL_TIME_MS); - eparams->params.nprobes = htod32((eparams->params.active_time / - P2PAPI_SCAN_NPROBS_TIME_MS)); + break; + } - /* Override scan params to find a peer for a connection */ - if (num_chans == 1) { - eparams->params.active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS); + if (p2p_scan_purpose == P2P_SCAN_CONNECT_TRY) eparams->params.nprobes = htod32(eparams->params.active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS); - } + else + eparams->params.nprobes = htod32((eparams->params.active_time / + P2PAPI_SCAN_NPROBS_TIME_MS)); + if (eparams->params.nprobes <= 0) eparams->params.nprobes = 1; @@ -897,11 +945,8 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, } eparams->version = htod32(ESCAN_REQ_VERSION); eparams->action = htod16(action); -#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) - eparams->sync_id = wl->escan_info.cur_sync_id; -#else - eparams->sync_id = htod16(0x1234); -#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ + wl_escan_set_sync_id(eparams->sync_id, cfg); + wl_escan_set_type(cfg, WL_SCANTYPE_P2P); CFGP2P_INFO(("SCAN CHANNELS : ")); for (i = 0; i < num_chans; i++) { @@ -912,35 +957,46 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, CFGP2P_INFO(("\n")); ret = wldev_iovar_setbuf_bsscfg(pri_dev, "p2p_scan", - memblk, memsize, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); + memblk, memsize, cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync); if (ret == BCME_OK) - wl_set_p2p_status(wl, SCANNING); + wl_set_p2p_status(cfg, SCANNING); return ret; } /* search function to reach at common channel to send action frame * Parameters: - * @wl : wl_private data + * @cfg : wl_private data * @ndev : net device for bssidx * @bssidx : bssidx for BSS * Returns 0 if success. */ s32 -wl_cfgp2p_act_frm_search(struct wl_priv *wl, struct net_device *ndev, +wl_cfgp2p_act_frm_search(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 channel, struct ether_addr *tx_dst_addr) { s32 ret = 0; u32 chan_cnt = 0; u16 *default_chan_list = NULL; - if (!p2p_is_on(wl) || ndev == NULL || bssidx == WL_INVALID) + p2p_scan_purpose_t p2p_scan_purpose = P2P_SCAN_AFX_PEER_NORMAL; + if (!p2p_is_on(cfg) || ndev == NULL || bssidx == WL_INVALID) return -BCME_ERROR; CFGP2P_ERR((" Enter\n")); - if (bssidx == wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY)) - bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); + if (bssidx == wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY)) + bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE); if (channel) chan_cnt = AF_PEER_SEARCH_CNT; else chan_cnt = SOCIAL_CHAN_CNT; +#ifdef CUSTOMER_HW4 + if (cfg->afx_hdl->pending_tx_act_frm && cfg->afx_hdl->is_active) { + wl_action_frame_t *action_frame; + action_frame = &(cfg->afx_hdl->pending_tx_act_frm->action_frame); + if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len)) { + chan_cnt = 1; + p2p_scan_purpose = P2P_SCAN_AFX_PEER_REDUCED; + } + } +#endif /* CUSTOMER_HW4 */ default_chan_list = kzalloc(chan_cnt * sizeof(*default_chan_list), GFP_KERNEL); if (default_chan_list == NULL) { CFGP2P_ERR(("channel list allocation failed \n")); @@ -958,9 +1014,9 @@ wl_cfgp2p_act_frm_search(struct wl_priv *wl, struct net_device *ndev, default_chan_list[1] = SOCIAL_CHAN_2; default_chan_list[2] = SOCIAL_CHAN_3; } - ret = wl_cfgp2p_escan(wl, ndev, true, chan_cnt, + ret = wl_cfgp2p_escan(cfg, ndev, true, chan_cnt, default_chan_list, WL_P2P_DISC_ST_SEARCH, - WL_SCAN_ACTION_START, bssidx, tx_dst_addr); + WL_SCAN_ACTION_START, bssidx, NULL, p2p_scan_purpose); kfree(default_chan_list); exit: return ret; @@ -1041,7 +1097,7 @@ end: /* Delete and Set a management vndr ie to firmware * Parameters: - * @wl : wl_private data + * @cfg : wl_private data * @ndev : net device for bssidx * @bssidx : bssidx for BSS * @pktflag : packet flag for IE (VNDR_IE_PRBREQ_FLAG,VNDR_IE_PRBRSP_FLAG, VNDR_IE_ASSOCRSP_FLAG, @@ -1052,7 +1108,7 @@ end: */ s32 -wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, +wl_cfgp2p_set_management_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len) { s32 ret = BCME_OK; @@ -1069,13 +1125,13 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss u8 *ptr; s32 type = -1; s32 remained_buf_len; -#define IE_TYPE(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie) -#define IE_TYPE_LEN(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie_len) +#define IE_TYPE(type, bsstype) (wl_to_p2p_bss_saved_ie(cfg, bsstype).p2p_ ## type ## _ie) +#define IE_TYPE_LEN(type, bsstype) (wl_to_p2p_bss_saved_ie(cfg, bsstype).p2p_ ## type ## _ie_len) memset(g_mgmt_ie_buf, 0, sizeof(g_mgmt_ie_buf)); curr_ie_buf = g_mgmt_ie_buf; CFGP2P_DBG((" bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag)); - if (wl->p2p != NULL) { - if (wl_cfgp2p_find_type(wl, bssidx, &type)) { + if (cfg->p2p != NULL) { + if (wl_cfgp2p_find_type(cfg, bssidx, &type)) { CFGP2P_ERR(("cannot find type from bssidx : %d\n", bssidx)); return BCME_ERROR; } @@ -1112,17 +1168,17 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss CFGP2P_ERR(("not suitable type\n")); return BCME_ERROR; } - } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { + } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) { switch (pktflag) { case VNDR_IE_PRBRSP_FLAG : - mgmt_ie_buf = wl->ap_info->probe_res_ie; - mgmt_ie_len = &wl->ap_info->probe_res_ie_len; - mgmt_ie_buf_len = sizeof(wl->ap_info->probe_res_ie); + mgmt_ie_buf = cfg->ap_info->probe_res_ie; + mgmt_ie_len = &cfg->ap_info->probe_res_ie_len; + mgmt_ie_buf_len = sizeof(cfg->ap_info->probe_res_ie); break; case VNDR_IE_BEACON_FLAG : - mgmt_ie_buf = wl->ap_info->beacon_ie; - mgmt_ie_len = &wl->ap_info->beacon_ie_len; - mgmt_ie_buf_len = sizeof(wl->ap_info->beacon_ie); + mgmt_ie_buf = cfg->ap_info->beacon_ie; + mgmt_ie_len = &cfg->ap_info->beacon_ie_len; + mgmt_ie_buf_len = sizeof(cfg->ap_info->beacon_ie); break; default: mgmt_ie_buf = NULL; @@ -1131,17 +1187,17 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss return BCME_ERROR; } bssidx = 0; - } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) { + } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_BSS) { switch (pktflag) { case VNDR_IE_PRBREQ_FLAG : - mgmt_ie_buf = wl->sta_info->probe_req_ie; - mgmt_ie_len = &wl->sta_info->probe_req_ie_len; - mgmt_ie_buf_len = sizeof(wl->sta_info->probe_req_ie); + mgmt_ie_buf = cfg->sta_info->probe_req_ie; + mgmt_ie_len = &cfg->sta_info->probe_req_ie_len; + mgmt_ie_buf_len = sizeof(cfg->sta_info->probe_req_ie); break; case VNDR_IE_ASSOCREQ_FLAG : - mgmt_ie_buf = wl->sta_info->assoc_req_ie; - mgmt_ie_len = &wl->sta_info->assoc_req_ie_len; - mgmt_ie_buf_len = sizeof(wl->sta_info->assoc_req_ie); + mgmt_ie_buf = cfg->sta_info->assoc_req_ie; + mgmt_ie_len = &cfg->sta_info->assoc_req_ie_len; + mgmt_ie_buf_len = sizeof(cfg->sta_info->assoc_req_ie); break; default: mgmt_ie_buf = NULL; @@ -1197,7 +1253,7 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1], vndrie_info->vndrie.oui[2])); - del_add_ie_buf_len = wl_cfgp2p_vndr_ie(wl, curr_ie_buf, + del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf, pktflag, vndrie_info->vndrie.oui, vndrie_info->vndrie.id, vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN, @@ -1227,7 +1283,7 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1], vndrie_info->vndrie.oui[2])); - del_add_ie_buf_len = wl_cfgp2p_vndr_ie(wl, curr_ie_buf, + del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf, pktflag, vndrie_info->vndrie.oui, vndrie_info->vndrie.id, vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN, @@ -1246,7 +1302,7 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss break; } - /* save the parsed IE in wl struct */ + /* save the parsed IE in cfg struct */ memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr, vndrie_info->ie_len); *mgmt_ie_len += vndrie_info->ie_len; @@ -1257,8 +1313,8 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss } if (total_ie_buf_len) { ret = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf, - total_ie_buf_len, wl->ioctl_buf, WLC_IOCTL_MAXLEN, - bssidx, &wl->ioctl_buf_sync); + total_ie_buf_len, cfg->ioctl_buf, WLC_IOCTL_MAXLEN, + bssidx, &cfg->ioctl_buf_sync); if (ret) CFGP2P_ERR(("vndr ie set error : %d\n", ret)); } @@ -1271,25 +1327,25 @@ exit: /* Clear the manament IE buffer of BSSCFG * Parameters: - * @wl : wl_private data + * @cfg : wl_private data * @bssidx : bssidx for BSS * * Returns 0 if success. */ s32 -wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx) +wl_cfgp2p_clear_management_ie(struct bcm_cfg80211 *cfg, s32 bssidx) { s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG, VNDR_IE_ASSOCRSP_FLAG, VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG}; s32 index = -1; s32 type = -1; - struct net_device *ndev = wl_cfgp2p_find_ndev(wl, bssidx); + struct net_device *ndev = wl_cfgp2p_find_ndev(cfg, bssidx); #define INIT_IE(IE_TYPE, BSS_TYPE) \ do { \ - memset(wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie, 0, \ - sizeof(wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie)); \ - wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie_len = 0; \ + memset(wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie, 0, \ + sizeof(wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie)); \ + wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie_len = 0; \ } while (0); if (bssidx < 0 || ndev == NULL) { @@ -1297,13 +1353,13 @@ wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx) return BCME_BADARG; } - if (wl_cfgp2p_find_type(wl, bssidx, &type)) { + if (wl_cfgp2p_find_type(cfg, bssidx, &type)) { CFGP2P_ERR(("invalid argument\n")); return BCME_BADARG; } for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) { /* clean up vndr ies in dongle */ - wl_cfgp2p_set_management_ie(wl, ndev, bssidx, vndrie_flag[index], NULL, 0); + wl_cfgp2p_set_management_ie(cfg, ndev, bssidx, vndrie_flag[index], NULL, 0); } INIT_IE(probe_req, type); INIT_IE(probe_res, type); @@ -1391,7 +1447,7 @@ wl_cfgp2p_find_wfdie(u8 *parse, u32 len) return NULL; } static u32 -wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 pktflag, +wl_cfgp2p_vndr_ie(struct bcm_cfg80211 *cfg, u8 *iebuf, s32 pktflag, s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd) { vndr_ie_setbuf_t hdr; /* aligned temporary vndr_ie buffer header */ @@ -1446,20 +1502,20 @@ wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 pktflag, /* * Search the bssidx based on dev argument * Parameters: - * @wl : wl_private data + * @cfg : wl_private data * @ndev : net device to search bssidx * @bssidx : output arg to store bssidx of the bsscfg of firmware. * Returns error */ s32 -wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev, s32 *bssidx) +wl_cfgp2p_find_idx(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 *bssidx) { u32 i; if (ndev == NULL || bssidx == NULL) { CFGP2P_ERR((" argument is invalid\n")); return BCME_BADARG; } - if (!wl->p2p_supported) { + if (!cfg->p2p_supported) { *bssidx = P2PAPI_BSSCFG_PRIMARY; return BCME_OK; } @@ -1467,15 +1523,15 @@ wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev, s32 *bssidx) * because the ndev is same with ndev of PRIMARY BSS. */ for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { - if (ndev == wl_to_p2p_bss_ndev(wl, i)) { - *bssidx = wl_to_p2p_bss_bssidx(wl, i); + if (ndev == wl_to_p2p_bss_ndev(cfg, i)) { + *bssidx = wl_to_p2p_bss_bssidx(cfg, i); return BCME_OK; } } return BCME_BADARG; } struct net_device * -wl_cfgp2p_find_ndev(struct wl_priv *wl, s32 bssidx) +wl_cfgp2p_find_ndev(struct bcm_cfg80211 *cfg, s32 bssidx) { u32 i; struct net_device *ndev = NULL; @@ -1485,8 +1541,8 @@ wl_cfgp2p_find_ndev(struct wl_priv *wl, s32 bssidx) } for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { - if (bssidx == wl_to_p2p_bss_bssidx(wl, i)) { - ndev = wl_to_p2p_bss_ndev(wl, i); + if (bssidx == wl_to_p2p_bss_bssidx(cfg, i)) { + ndev = wl_to_p2p_bss_ndev(cfg, i); break; } } @@ -1497,14 +1553,14 @@ exit: /* * Search the driver array idx based on bssidx argument * Parameters: - * @wl : wl_private data + * @cfg : wl_private data * @bssidx : bssidx which indicate bsscfg->idx of firmware. * @type : output arg to store array idx of p2p->bss. * Returns error */ s32 -wl_cfgp2p_find_type(struct wl_priv *wl, s32 bssidx, s32 *type) +wl_cfgp2p_find_type(struct bcm_cfg80211 *cfg, s32 bssidx, s32 *type) { u32 i; if (bssidx < 0 || type == NULL) { @@ -1513,7 +1569,7 @@ wl_cfgp2p_find_type(struct wl_priv *wl, s32 bssidx, s32 *type) } for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { - if (bssidx == wl_to_p2p_bss_bssidx(wl, i)) { + if (bssidx == wl_to_p2p_bss_bssidx(cfg, i)) { *type = i; return BCME_OK; } @@ -1527,65 +1583,70 @@ exit: * Callback function for WLC_E_P2P_DISC_LISTEN_COMPLETE */ s32 -wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev, - const wl_event_msg_t *e, void *data) +wl_cfgp2p_listen_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, + const wl_event_msg_t *e, void *data) { s32 ret = BCME_OK; - struct net_device *netdev; - if (!wl || !wl->p2p) + struct net_device *ndev = NULL; + + if (!cfg || !cfg->p2p) return BCME_ERROR; - if (wl->p2p_net == ndev) { - netdev = wl_to_prmry_ndev(wl); - } else { - netdev = ndev; - } + CFGP2P_DBG((" Enter\n")); - if (wl_get_p2p_status(wl, LISTEN_EXPIRED) == 0) { - wl_set_p2p_status(wl, LISTEN_EXPIRED); - if (timer_pending(&wl->p2p->listen_timer)) { - del_timer_sync(&wl->p2p->listen_timer); + + ndev = cfgdev_to_wlc_ndev(cfgdev, cfg); + + if (wl_get_p2p_status(cfg, LISTEN_EXPIRED) == 0) { + wl_set_p2p_status(cfg, LISTEN_EXPIRED); + if (timer_pending(&cfg->p2p->listen_timer)) { + del_timer_sync(&cfg->p2p->listen_timer); } - if (wl->afx_hdl->is_listen == TRUE && - wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) { + if (cfg->afx_hdl->is_listen == TRUE && + wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) { WL_DBG(("Listen DONE for action frame\n")); - complete(&wl->act_frm_scan); + complete(&cfg->act_frm_scan); } #ifdef WL_CFG80211_SYNC_GON - else if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) { - wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM_LISTEN, netdev); + else if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) { + wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, ndev); WL_DBG(("Listen DONE and wake up wait_next_af !!(%d)\n", - jiffies_to_msecs(jiffies - wl->af_tx_sent_jiffies))); + jiffies_to_msecs(jiffies - cfg->af_tx_sent_jiffies))); - if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) - wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, netdev); + if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) + wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev); - complete(&wl->wait_next_af); + complete(&cfg->wait_next_af); } #endif /* WL_CFG80211_SYNC_GON */ #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST - if (wl_get_drv_status_all(wl, REMAINING_ON_CHANNEL)) { + if (wl_get_drv_status_all(cfg, REMAINING_ON_CHANNEL)) { #else - if (wl_get_drv_status_all(wl, REMAINING_ON_CHANNEL) || - wl_get_drv_status_all(wl, FAKE_REMAINING_ON_CHANNEL)) { + if (wl_get_drv_status_all(cfg, REMAINING_ON_CHANNEL) || + wl_get_drv_status_all(cfg, FAKE_REMAINING_ON_CHANNEL)) { #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ WL_DBG(("Listen DONE for ramain on channel expired\n")); - wl_clr_drv_status(wl, REMAINING_ON_CHANNEL, netdev); + wl_clr_drv_status(cfg, REMAINING_ON_CHANNEL, ndev); #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST - wl_clr_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, netdev); + wl_clr_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev); #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ if (ndev && (ndev->ieee80211_ptr != NULL)) { - cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, - &wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL); +#if defined(WL_CFG80211_P2P_DEV_IF) + cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id, + &cfg->remain_on_chan, GFP_KERNEL); +#else + cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id, + &cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL); +#endif /* WL_CFG80211_P2P_DEV_IF */ } } - if (wl_add_remove_eventmsg(wl_to_prmry_ndev(wl), + if (wl_add_remove_eventmsg(bcmcfg_to_prmry_ndev(cfg), WLC_E_P2P_PROBREQ_MSG, false) != BCME_OK) { CFGP2P_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n")); } } else - wl_clr_p2p_status(wl, LISTEN_EXPIRED); + wl_clr_p2p_status(cfg, LISTEN_EXPIRED); return ret; @@ -1600,35 +1661,44 @@ void wl_cfgp2p_listen_expired(unsigned long data) { wl_event_msg_t msg; - struct wl_priv *wl = (struct wl_priv *) data; + struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *) data; CFGP2P_DBG((" Enter\n")); bzero(&msg, sizeof(wl_event_msg_t)); msg.event_type = hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE); - wl_cfg80211_event(wl->p2p_net ? wl->p2p_net : - wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), &msg, NULL); +#if defined(WL_ENABLE_P2P_IF) + wl_cfg80211_event(cfg->p2p_net ? cfg->p2p_net : + wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), &msg, NULL); +#else + wl_cfg80211_event(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), &msg, + NULL); +#endif /* WL_ENABLE_P2P_IF */ } /* * Routine for cancelling the P2P LISTEN */ static s32 -wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev, - bool notify) +wl_cfgp2p_cancel_listen(struct bcm_cfg80211 *cfg, struct net_device *ndev, + struct wireless_dev *wdev, bool notify) { WL_DBG(("Enter \n")); /* Irrespective of whether timer is running or not, reset * the LISTEN state. */ #ifdef NOT_YET - wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); + wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, + wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE)); #endif /* NOT_YET */ - if (timer_pending(&wl->p2p->listen_timer)) { - del_timer_sync(&wl->p2p->listen_timer); + if (timer_pending(&cfg->p2p->listen_timer)) { + del_timer_sync(&cfg->p2p->listen_timer); if (notify) if (ndev && ndev->ieee80211_ptr) { - cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, - &wl->remain_on_chan, wl->remain_on_chan_type, - GFP_KERNEL); +#if defined(WL_CFG80211_P2P_DEV_IF) + cfg80211_remain_on_channel_expired(wdev, cfg->last_roc_id, + &cfg->remain_on_chan, GFP_KERNEL); +#else + cfg80211_remain_on_channel_expired(ndev, cfg->last_roc_id, + &cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL); +#endif /* WL_CFG80211_P2P_DEV_IF */ } } return 0; @@ -1640,43 +1710,43 @@ wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev, * * This fn assumes dongle p2p device discovery is already enabled. * Parameters : - * @wl : wl_private data + * @cfg : wl_private data * @channel : channel to listen * @duration_ms : the time (milli seconds) to wait */ s32 -wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms) +wl_cfgp2p_discover_listen(struct bcm_cfg80211 *cfg, s32 channel, u32 duration_ms) { #define EXTRA_DELAY_TIME 100 s32 ret = BCME_OK; struct timer_list *_timer; s32 extra_delay; - struct net_device *netdev = wl_to_prmry_ndev(wl); + struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg); CFGP2P_DBG((" Enter Listen Channel : %d, Duration : %d\n", channel, duration_ms)); - if (unlikely(wl_get_p2p_status(wl, DISCOVERY_ON) == 0)) { + if (unlikely(wl_get_p2p_status(cfg, DISCOVERY_ON) == 0)) { CFGP2P_ERR((" Discovery is not set, so we have noting to do\n")); ret = BCME_NOTREADY; goto exit; } - if (timer_pending(&wl->p2p->listen_timer)) { + if (timer_pending(&cfg->p2p->listen_timer)) { CFGP2P_DBG(("previous LISTEN is not completed yet\n")); goto exit; } #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST else - wl_clr_p2p_status(wl, LISTEN_EXPIRED); + wl_clr_p2p_status(cfg, LISTEN_EXPIRED); #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ if (wl_add_remove_eventmsg(netdev, WLC_E_P2P_PROBREQ_MSG, true) != BCME_OK) { CFGP2P_ERR((" failed to set WLC_E_P2P_PROPREQ_MSG\n")); } - ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_LISTEN, channel, (u16) duration_ms, - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); - _timer = &wl->p2p->listen_timer; + ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_LISTEN, channel, (u16) duration_ms, + wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE)); + _timer = &cfg->p2p->listen_timer; /* We will wait to receive WLC_E_P2P_DISC_LISTEN_COMPLETE from dongle , * otherwise we will wait up to duration_ms + 100ms + duration / 10 @@ -1691,7 +1761,7 @@ wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms) INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration_ms, extra_delay); #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST - wl_clr_p2p_status(wl, LISTEN_EXPIRED); + wl_clr_p2p_status(cfg, LISTEN_EXPIRED); #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ #undef EXTRA_DELAY_TIME @@ -1701,28 +1771,28 @@ exit: s32 -wl_cfgp2p_discover_enable_search(struct wl_priv *wl, u8 enable) +wl_cfgp2p_discover_enable_search(struct bcm_cfg80211 *cfg, u8 enable) { s32 ret = BCME_OK; CFGP2P_DBG((" Enter\n")); - if (!wl_get_p2p_status(wl, DISCOVERY_ON)) { + if (!wl_get_p2p_status(cfg, DISCOVERY_ON)) { CFGP2P_DBG((" do nothing, discovery is off\n")); return ret; } - if (wl_get_p2p_status(wl, SEARCH_ENABLED) == enable) { + if (wl_get_p2p_status(cfg, SEARCH_ENABLED) == enable) { CFGP2P_DBG(("already : %d\n", enable)); return ret; } - wl_chg_p2p_status(wl, SEARCH_ENABLED); + wl_chg_p2p_status(cfg, SEARCH_ENABLED); /* When disabling Search, reset the WL driver's p2p discovery state to * WL_P2P_DISC_ST_SCAN. */ if (!enable) { - wl_clr_p2p_status(wl, SCANNING); - ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); + wl_clr_p2p_status(cfg, SCANNING); + ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, + wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE)); } return ret; @@ -1732,35 +1802,36 @@ wl_cfgp2p_discover_enable_search(struct wl_priv *wl, u8 enable) * Callback function for WLC_E_ACTION_FRAME_COMPLETE, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE */ s32 -wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev, +wl_cfgp2p_action_tx_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data) { s32 ret = BCME_OK; u32 event_type = ntoh32(e->event_type); u32 status = ntoh32(e->status); + struct net_device *ndev = NULL; CFGP2P_DBG((" Enter\n")); - if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) { + + ndev = cfgdev_to_wlc_ndev(cfgdev, cfg); + + if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) { if (event_type == WLC_E_ACTION_FRAME_COMPLETE) { CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status)); if (status == WLC_E_STATUS_SUCCESS) { - wl_set_p2p_status(wl, ACTION_TX_COMPLETED); + wl_set_p2p_status(cfg, ACTION_TX_COMPLETED); CFGP2P_DBG(("WLC_E_ACTION_FRAME_COMPLETE : ACK\n")); - } - else { - if (!wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) { - wl_set_p2p_status(wl, ACTION_TX_NOACK); - CFGP2P_INFO(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n")); - wl_stop_wait_next_action_frame(wl, ndev); - } + else if (!wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) { + wl_set_p2p_status(cfg, ACTION_TX_NOACK); + CFGP2P_INFO(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n")); + wl_stop_wait_next_action_frame(cfg, ndev); } } else { CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received," "status : %d\n", status)); - if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) - complete(&wl->send_af_done); + if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) + complete(&cfg->send_af_done); } } return ret; @@ -1774,40 +1845,45 @@ wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev, * 802.11 ack has been received for the sent action frame. */ s32 -wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, +wl_cfgp2p_tx_action_frame(struct bcm_cfg80211 *cfg, struct net_device *dev, wl_af_params_t *af_params, s32 bssidx) { s32 ret = BCME_OK; + s32 evt_ret = BCME_OK; s32 timeout = 0; + wl_eventmsg_buf_t buf; CFGP2P_INFO(("\n")); CFGP2P_INFO(("channel : %u , dwell time : %u\n", af_params->channel, af_params->dwell_time)); - wl_clr_p2p_status(wl, ACTION_TX_COMPLETED); - wl_clr_p2p_status(wl, ACTION_TX_NOACK); - if (bssidx == P2PAPI_BSSCFG_PRIMARY) - bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); + wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED); + wl_clr_p2p_status(cfg, ACTION_TX_NOACK); + + bzero(&buf, sizeof(wl_eventmsg_buf_t)); + wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, true); + wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_COMPLETE, true); + if ((evt_ret = wl_cfg80211_apply_eventbuffer(bcmcfg_to_prmry_ndev(cfg), cfg, &buf)) < 0) + return evt_ret; - wl->af_sent_channel = af_params->channel; + cfg->af_sent_channel = af_params->channel; #ifdef WL_CFG80211_SYNC_GON - wl->af_tx_sent_jiffies = jiffies; + cfg->af_tx_sent_jiffies = jiffies; #endif /* WL_CFG80211_SYNC_GON */ ret = wldev_iovar_setbuf_bsscfg(dev, "actframe", af_params, sizeof(*af_params), - wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); + cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync); if (ret < 0) { - CFGP2P_ERR((" sending action frame is failed\n")); goto exit; } - timeout = wait_for_completion_timeout(&wl->send_af_done, + timeout = wait_for_completion_timeout(&cfg->send_af_done, msecs_to_jiffies(af_params->dwell_time + WL_AF_TX_EXTRA_TIME_MAX)); - if (timeout > 0 && wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) { + if (timeout >= 0 && wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) { CFGP2P_INFO(("tx action frame operation is completed\n")); ret = BCME_OK; } else { @@ -1815,11 +1891,20 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, CFGP2P_INFO(("tx action frame operation is failed\n")); } /* clear status bit for action tx */ - wl_clr_p2p_status(wl, ACTION_TX_COMPLETED); - wl_clr_p2p_status(wl, ACTION_TX_NOACK); + wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED); + wl_clr_p2p_status(cfg, ACTION_TX_NOACK); exit: CFGP2P_INFO((" via act frame iovar : status = %d\n", ret)); + + bzero(&buf, sizeof(wl_eventmsg_buf_t)); + wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, false); + wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_COMPLETE, false); + if ((evt_ret = wl_cfg80211_apply_eventbuffer(bcmcfg_to_prmry_ndev(cfg), cfg, &buf)) < 0) { + WL_ERR(("TX frame events revert back failed \n")); + return evt_ret; + } + return ret; } @@ -1917,13 +2002,13 @@ wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx) result = wldev_iovar_getbuf_bsscfg(ndev, "bss", &bsscfg_idx, sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0, NULL); if (result != 0) { - CFGP2P_ERR(("'wl bss -C %d' failed: %d\n", bsscfg_idx, result)); + CFGP2P_ERR(("'cfg bss -C %d' failed: %d\n", bsscfg_idx, result)); CFGP2P_ERR(("NOTE: this ioctl error is normal " "when the BSS has not been created yet.\n")); } else { val = *(int*)getbuf; val = dtoh32(val); - CFGP2P_INFO(("---wl bss -C %d ==> %d\n", bsscfg_idx, val)); + CFGP2P_INFO(("---cfg bss -C %d ==> %d\n", bsscfg_idx, val)); isup = (val ? TRUE : FALSE); } return isup; @@ -1932,7 +2017,7 @@ wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx) /* Bring up or down a BSS */ s32 -wl_cfgp2p_bss(struct wl_priv *wl, struct net_device *ndev, s32 bsscfg_idx, s32 up) +wl_cfgp2p_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bsscfg_idx, s32 up) { s32 ret = BCME_OK; s32 val = up ? 1 : 0; @@ -1944,9 +2029,9 @@ wl_cfgp2p_bss(struct wl_priv *wl, struct net_device *ndev, s32 bsscfg_idx, s32 u bss_setbuf.cfg = htod32(bsscfg_idx); bss_setbuf.val = htod32(val); - CFGP2P_INFO(("---wl bss -C %d %s\n", bsscfg_idx, up ? "up" : "down")); + CFGP2P_INFO(("---cfg bss -C %d %s\n", bsscfg_idx, up ? "up" : "down")); ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf), - wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); + cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync); if (ret != 0) { CFGP2P_ERR(("'bss %d' failed with %d\n", up, ret)); @@ -1957,15 +2042,20 @@ wl_cfgp2p_bss(struct wl_priv *wl, struct net_device *ndev, s32 bsscfg_idx, s32 u /* Check if 'p2p' is supported in the driver */ s32 -wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev) +wl_cfgp2p_supported(struct bcm_cfg80211 *cfg, struct net_device *ndev) { s32 ret = BCME_OK; s32 p2p_supported = 0; ret = wldev_iovar_getint(ndev, "p2p", &p2p_supported); if (ret < 0) { - CFGP2P_ERR(("wl p2p error %d\n", ret)); - return 0; + if (ret == BCME_UNSUPPORTED) { + CFGP2P_INFO(("p2p is unsupported\n")); + return 0; + } else { + CFGP2P_ERR(("cfg p2p error %d\n", ret)); + return ret; + } } if (p2p_supported == 1) { CFGP2P_INFO(("p2p is supported\n")); @@ -1977,21 +2067,34 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev) } /* Cleanup P2P resources */ s32 -wl_cfgp2p_down(struct wl_priv *wl) +wl_cfgp2p_down(struct bcm_cfg80211 *cfg) { + struct net_device *ndev = NULL; + struct wireless_dev *wdev = NULL; s32 i = 0, index = -1; - wl_cfgp2p_cancel_listen(wl, - wl->p2p_net ? wl->p2p_net : wl_to_prmry_ndev(wl), TRUE); + +#if defined(WL_CFG80211_P2P_DEV_IF) + ndev = bcmcfg_to_prmry_ndev(cfg); + wdev = bcmcfg_to_p2p_wdev(cfg); +#elif defined(WL_ENABLE_P2P_IF) + ndev = cfg->p2p_net ? cfg->p2p_net : bcmcfg_to_prmry_ndev(cfg); + wdev = ndev_to_wdev(ndev); +#endif /* WL_CFG80211_P2P_DEV_IF */ + + wl_cfgp2p_cancel_listen(cfg, ndev, wdev, TRUE); for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { - index = wl_to_p2p_bss_bssidx(wl, i); + index = wl_to_p2p_bss_bssidx(cfg, i); if (index != WL_INVALID) - wl_cfgp2p_clear_management_ie(wl, index); + wl_cfgp2p_clear_management_ie(cfg, index); } - wl_cfgp2p_deinit_priv(wl); +#if defined(WL_CFG80211_P2P_DEV_IF) + wl_cfgp2p_del_p2p_disc_if(wdev, cfg); +#endif /* WL_CFG80211_P2P_DEV_IF */ + wl_cfgp2p_deinit_priv(cfg); return 0; } s32 -wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len) +wl_cfgp2p_set_p2p_noa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len) { s32 ret = -1; int count, start, duration; @@ -2001,37 +2104,47 @@ wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, in memset(&dongle_noa, 0, sizeof(dongle_noa)); - if (wl->p2p && wl->p2p->vif_created) { + if (cfg->p2p && cfg->p2p->vif_created) { - wl->p2p->noa.desc[0].start = 0; + cfg->p2p->noa.desc[0].start = 0; sscanf(buf, "%10d %10d %10d", &count, &start, &duration); CFGP2P_DBG(("set_p2p_noa count %d start %d duration %d\n", count, start, duration)); if (count != -1) - wl->p2p->noa.desc[0].count = count; + cfg->p2p->noa.desc[0].count = count; /* supplicant gives interval as start */ if (start != -1) - wl->p2p->noa.desc[0].interval = start; + cfg->p2p->noa.desc[0].interval = start; if (duration != -1) - wl->p2p->noa.desc[0].duration = duration; + cfg->p2p->noa.desc[0].duration = duration; - if (wl->p2p->noa.desc[0].count != 255) { - wl->p2p->noa.desc[0].start = 200; + if (cfg->p2p->noa.desc[0].count < 255 && cfg->p2p->noa.desc[0].count > 1) { + cfg->p2p->noa.desc[0].start = 0; + dongle_noa.type = WL_P2P_SCHED_TYPE_ABS; + dongle_noa.action = WL_P2P_SCHED_ACTION_NONE; + dongle_noa.option = WL_P2P_SCHED_OPTION_TSFOFS; + } + else if (cfg->p2p->noa.desc[0].count == 1) { + cfg->p2p->noa.desc[0].start = 200; dongle_noa.type = WL_P2P_SCHED_TYPE_REQ_ABS; dongle_noa.action = WL_P2P_SCHED_ACTION_GOOFF; dongle_noa.option = WL_P2P_SCHED_OPTION_TSFOFS; } + else if (cfg->p2p->noa.desc[0].count == 0) { + cfg->p2p->noa.desc[0].start = 0; + dongle_noa.action = WL_P2P_SCHED_ACTION_RESET; + } else { /* Continuous NoA interval. */ dongle_noa.action = WL_P2P_SCHED_ACTION_NONE; dongle_noa.type = WL_P2P_SCHED_TYPE_ABS; - if ((wl->p2p->noa.desc[0].interval == 102) || - (wl->p2p->noa.desc[0].interval == 100)) { - wl->p2p->noa.desc[0].start = 100 - - wl->p2p->noa.desc[0].duration; + if ((cfg->p2p->noa.desc[0].interval == 102) || + (cfg->p2p->noa.desc[0].interval == 100)) { + cfg->p2p->noa.desc[0].start = 100 - + cfg->p2p->noa.desc[0].duration; dongle_noa.option = WL_P2P_SCHED_OPTION_BCNPCT; } else { @@ -2039,20 +2152,20 @@ wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, in } } /* Put the noa descriptor in dongle format for dongle */ - dongle_noa.desc[0].count = htod32(wl->p2p->noa.desc[0].count); + dongle_noa.desc[0].count = htod32(cfg->p2p->noa.desc[0].count); if (dongle_noa.option == WL_P2P_SCHED_OPTION_BCNPCT) { - dongle_noa.desc[0].start = htod32(wl->p2p->noa.desc[0].start); - dongle_noa.desc[0].duration = htod32(wl->p2p->noa.desc[0].duration); + dongle_noa.desc[0].start = htod32(cfg->p2p->noa.desc[0].start); + dongle_noa.desc[0].duration = htod32(cfg->p2p->noa.desc[0].duration); } else { - dongle_noa.desc[0].start = htod32(wl->p2p->noa.desc[0].start*1000); - dongle_noa.desc[0].duration = htod32(wl->p2p->noa.desc[0].duration*1000); + dongle_noa.desc[0].start = htod32(cfg->p2p->noa.desc[0].start*1000); + dongle_noa.desc[0].duration = htod32(cfg->p2p->noa.desc[0].duration*1000); } - dongle_noa.desc[0].interval = htod32(wl->p2p->noa.desc[0].interval*1000); + dongle_noa.desc[0].interval = htod32(cfg->p2p->noa.desc[0].interval*1000); - ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION), - "p2p_noa", &dongle_noa, sizeof(dongle_noa), wl->ioctl_buf, WLC_IOCTL_MAXLEN, - &wl->ioctl_buf_sync); + ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION), + "p2p_noa", &dongle_noa, sizeof(dongle_noa), cfg->ioctl_buf, + WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync); if (ret < 0) { CFGP2P_ERR(("fw set p2p_noa failed %d\n", ret)); @@ -2064,7 +2177,7 @@ wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, in return ret; } s32 -wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int buf_len) +wl_cfgp2p_get_p2p_noa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int buf_len) { wifi_p2p_noa_desc_t *noa_desc; @@ -2073,18 +2186,18 @@ wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, in CFGP2P_DBG((" Enter\n")); buf[0] = '\0'; - if (wl->p2p && wl->p2p->vif_created) { - if (wl->p2p->noa.desc[0].count || wl->p2p->ops.ops) { + if (cfg->p2p && cfg->p2p->vif_created) { + if (cfg->p2p->noa.desc[0].count || cfg->p2p->ops.ops) { _buf[0] = 1; /* noa index */ - _buf[1] = (wl->p2p->ops.ops ? 0x80: 0) | - (wl->p2p->ops.ctw & 0x7f); /* ops + ctw */ + _buf[1] = (cfg->p2p->ops.ops ? 0x80: 0) | + (cfg->p2p->ops.ctw & 0x7f); /* ops + ctw */ len += 2; - if (wl->p2p->noa.desc[0].count) { + if (cfg->p2p->noa.desc[0].count) { noa_desc = (wifi_p2p_noa_desc_t*)&_buf[len]; - noa_desc->cnt_type = wl->p2p->noa.desc[0].count; - noa_desc->duration = wl->p2p->noa.desc[0].duration; - noa_desc->interval = wl->p2p->noa.desc[0].interval; - noa_desc->start = wl->p2p->noa.desc[0].start; + noa_desc->cnt_type = cfg->p2p->noa.desc[0].count; + noa_desc->duration = cfg->p2p->noa.desc[0].duration; + noa_desc->interval = cfg->p2p->noa.desc[0].interval; + noa_desc->start = cfg->p2p->noa.desc[0].start; len += sizeof(wifi_p2p_noa_desc_t); } if (buf_len <= len * 2) { @@ -2107,36 +2220,38 @@ wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, in return len * 2; } s32 -wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int len) +wl_cfgp2p_set_p2p_ps(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len) { int ps, ctw; int ret = -1; s32 legacy_ps; + struct net_device *dev; CFGP2P_DBG((" Enter\n")); - if (wl->p2p && wl->p2p->vif_created) { + if (cfg->p2p && cfg->p2p->vif_created) { sscanf(buf, "%10d %10d %10d", &legacy_ps, &ps, &ctw); CFGP2P_DBG((" Enter legacy_ps %d ps %d ctw %d\n", legacy_ps, ps, ctw)); + dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION); if (ctw != -1) { - wl->p2p->ops.ctw = ctw; + cfg->p2p->ops.ctw = ctw; ret = 0; } if (ps != -1) { - wl->p2p->ops.ops = ps; - ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION), - "p2p_ops", &wl->p2p->ops, sizeof(wl->p2p->ops), - wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); + cfg->p2p->ops.ops = ps; + ret = wldev_iovar_setbuf(dev, + "p2p_ops", &cfg->p2p->ops, sizeof(cfg->p2p->ops), + cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync); if (ret < 0) { CFGP2P_ERR(("fw set p2p_ops failed %d\n", ret)); } } if ((legacy_ps != -1) && ((legacy_ps == PM_MAX) || (legacy_ps == PM_OFF))) { - ret = wldev_ioctl(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION), + ret = wldev_ioctl(dev, WLC_SET_PM, &legacy_ps, sizeof(legacy_ps), true); - if (unlikely(ret)) { + if (unlikely(ret)) CFGP2P_ERR(("error (%d)\n", ret)); - } + wl_cfg80211_update_power_mode(dev); } else CFGP2P_ERR(("ilegal setting\n")); @@ -2200,20 +2315,47 @@ wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id) } #define P2P_GROUP_CAPAB_GO_BIT 0x01 + +u8* +wl_cfgp2p_find_attrib_in_all_p2p_Ies(u8 *parse, u32 len, u32 attrib) +{ + bcm_tlv_t *ie; + u8* pAttrib; + + CFGP2P_INFO(("Starting parsing parse %p attrib %d remaining len %d ", parse, attrib, len)); + while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) { + if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len) == TRUE) { + /* Have the P2p ie. Now check for attribute */ + if ((pAttrib = wl_cfgp2p_retreive_p2pattrib(parse, attrib)) != NULL) { + CFGP2P_INFO(("P2P attribute %d was found at parse %p", + attrib, parse)); + return pAttrib; + } + else { + parse += (ie->len + TLV_HDR_LEN); + len -= (ie->len + TLV_HDR_LEN); + CFGP2P_INFO(("P2P Attribute %d not found Moving parse" + " to %p len to %d", attrib, parse, len)); + } + } + else { + /* It was not p2p IE. parse will get updated automatically to next TLV */ + CFGP2P_INFO(("IT was NOT P2P IE parse %p len %d", parse, len)); + } + } + CFGP2P_ERR(("P2P attribute %d was NOT found", attrib)); + return NULL; +} + u8 * wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length) { - wifi_p2p_ie_t * p2p_ie = NULL; u8 *capability = NULL; bool p2p_go = 0; u8 *ptr = NULL; - if (!(p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset, bi->ie_length))) { - WL_ERR(("P2P IE not found")); - return NULL; - } - - if (!(capability = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_P2P_INFO))) { + if ((capability = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset, + bi->ie_length, P2P_SEID_P2P_INFO)) == NULL) { WL_ERR(("P2P Capability attribute not found")); return NULL; } @@ -2225,11 +2367,13 @@ wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length) } /* In probe responses, DEVICE INFO attribute will be present */ - if (!(ptr = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_DEV_INFO))) { + if (!(ptr = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset, + bi->ie_length, P2P_SEID_DEV_INFO))) { /* If DEVICE_INFO is not found, this might be a beacon frame. * check for DEVICE_ID in the beacon frame. */ - ptr = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_DEV_ID); + ptr = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset, + bi->ie_length, P2P_SEID_DEV_ID); } if (!ptr) @@ -2251,37 +2395,42 @@ struct ethtool_ops cfgp2p_ethtool_ops = { }; #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ +#if defined(WL_ENABLE_P2P_IF) || defined(WL_NEWCFG_PRIVCMD_SUPPORT) s32 -wl_cfgp2p_register_ndev(struct wl_priv *wl) +wl_cfgp2p_register_ndev(struct bcm_cfg80211 *cfg) { int ret = 0; struct net_device* net = NULL; +#ifndef WL_NEWCFG_PRIVCMD_SUPPORT struct wireless_dev *wdev = NULL; +#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */ uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x33, 0x22, 0x11 }; - if (wl->p2p_net) { + if (cfg->p2p_net) { CFGP2P_ERR(("p2p_net defined already.\n")); return -EINVAL; } /* Allocate etherdev, including space for private structure */ - if (!(net = alloc_etherdev(sizeof(struct wl_priv *)))) { + if (!(net = alloc_etherdev(sizeof(struct bcm_cfg80211 *)))) { CFGP2P_ERR(("%s: OOM - alloc_etherdev\n", __FUNCTION__)); return -ENODEV; } +#ifndef WL_NEWCFG_PRIVCMD_SUPPORT wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); if (unlikely(!wdev)) { WL_ERR(("Could not allocate wireless device\n")); free_netdev(net); return -ENOMEM; } +#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */ strncpy(net->name, "p2p%d", sizeof(net->name) - 1); net->name[IFNAMSIZ - 1] = '\0'; - /* Copy the reference to wl_priv */ - memcpy((void *)netdev_priv(net), &wl, sizeof(struct wl_priv *)); + /* Copy the reference to bcm_cfg80211 */ + memcpy((void *)netdev_priv(net), &cfg, sizeof(struct bcm_cfg80211 *)); #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) ASSERT(!net->open); @@ -2297,34 +2446,42 @@ wl_cfgp2p_register_ndev(struct wl_priv *wl) /* Register with a dummy MAC addr */ memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN); - wdev->wiphy = wl->wdev->wiphy; +#ifndef WL_NEWCFG_PRIVCMD_SUPPORT + wdev->wiphy = cfg->wdev->wiphy; wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS); net->ieee80211_ptr = wdev; +#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) net->ethtool_ops = &cfgp2p_ethtool_ops; #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ +#ifndef WL_NEWCFG_PRIVCMD_SUPPORT SET_NETDEV_DEV(net, wiphy_dev(wdev->wiphy)); /* Associate p2p0 network interface with new wdev */ wdev->netdev = net; +#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */ ret = register_netdev(net); if (ret) { CFGP2P_ERR((" register_netdevice failed (%d)\n", ret)); free_netdev(net); +#ifndef WL_NEWCFG_PRIVCMD_SUPPORT kfree(wdev); +#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */ return -ENODEV; } /* store p2p net ptr for further reference. Note that iflist won't have this * entry as there corresponding firmware interface is a "Hidden" interface. */ - wl->p2p_wdev = wdev; - wl->p2p_net = net; +#ifndef WL_NEWCFG_PRIVCMD_SUPPORT + cfg->p2p_wdev = wdev; +#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */ + cfg->p2p_net = net; printk("%s: P2P Interface Registered\n", net->name); @@ -2332,35 +2489,38 @@ wl_cfgp2p_register_ndev(struct wl_priv *wl) } s32 -wl_cfgp2p_unregister_ndev(struct wl_priv *wl) +wl_cfgp2p_unregister_ndev(struct bcm_cfg80211 *cfg) { - if (!wl || !wl->p2p_net) { + if (!cfg || !cfg->p2p_net) { CFGP2P_ERR(("Invalid Ptr\n")); return -EINVAL; } - unregister_netdev(wl->p2p_net); - free_netdev(wl->p2p_net); + unregister_netdev(cfg->p2p_net); + free_netdev(cfg->p2p_net); return 0; } + static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev) { + if (skb) { CFGP2P_DBG(("(%s) is not used for data operations.Droping the packet.\n", ndev->name)); dev_kfree_skb_any(skb); } + return 0; } static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd) { int ret = 0; - struct wl_priv *wl = *(struct wl_priv **)netdev_priv(net); - struct net_device *ndev = wl_to_prmry_ndev(wl); + struct bcm_cfg80211 *cfg = *(struct bcm_cfg80211 **)netdev_priv(net); + struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg); /* There is no ifidx corresponding to p2p0 in our firmware. So we should * not Handle any IOCTL cmds on p2p0 other than ANDROID PRIVATE CMDs. @@ -2377,16 +2537,17 @@ static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd return ret; } +#endif /* WL_ENABLE_P2P_IF || WL_NEWCFG_PRIVCMD_SUPPORT */ +#if defined(WL_ENABLE_P2P_IF) static int wl_cfgp2p_if_open(struct net_device *net) { - extern struct wl_priv *wlcfg_drv_priv; struct wireless_dev *wdev = net->ieee80211_ptr; - struct wl_priv *wl = NULL; - wl = wlcfg_drv_priv; - if (!wdev || !wl || !wl->p2p) + + if (!wdev || !wl_cfg80211_is_p2p_active()) return -EINVAL; WL_TRACE(("Enter\n")); +#if !defined(WL_IFACE_COMB_NUM_CHANNELS) /* If suppose F/W download (ifconfig wlan0 up) hasn't been done by now, * do it here. This will make sure that in concurrent mode, supplicant * is not dependent on a particular order of interface initialization. @@ -2395,6 +2556,7 @@ static int wl_cfgp2p_if_open(struct net_device *net) */ wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO)); +#endif /* !WL_IFACE_COMB_NUM_CHANNELS */ wl_cfg80211_do_driver_init(net); return 0; @@ -2402,30 +2564,18 @@ static int wl_cfgp2p_if_open(struct net_device *net) static int wl_cfgp2p_if_stop(struct net_device *net) { - extern struct wl_priv *wlcfg_drv_priv; - struct wl_priv *wl = NULL; - unsigned long flags; struct wireless_dev *wdev = net->ieee80211_ptr; - int clear_flag = 0; + if (!wdev) return -EINVAL; - WL_TRACE(("Enter\n")); - wl = wlcfg_drv_priv; - if (!wl) - return -EINVAL; - spin_lock_irqsave(&wl->cfgdrv_lock, flags); - if (wl->scan_request && wl->scan_request->dev == net) { - cfg80211_scan_done(wl->scan_request, true); - wl->scan_request = NULL; - clear_flag = 1; - } - spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); - if (clear_flag) - wl_clr_drv_status(wl, SCANNING, net); + wl_cfg80211_scan_stop(net); + +#if !defined(WL_IFACE_COMB_NUM_CHANNELS) wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes) & (~(BIT(NL80211_IFTYPE_P2P_CLIENT)| BIT(NL80211_IFTYPE_P2P_GO))); +#endif /* !WL_IFACE_COMB_NUM_CHANNELS */ return 0; } @@ -2433,3 +2583,129 @@ bool wl_cfgp2p_is_ifops(const struct net_device_ops *if_ops) { return (if_ops == &wl_cfgp2p_if_ops); } +#endif /* WL_ENABLE_P2P_IF */ + +#if defined(WL_CFG80211_P2P_DEV_IF) +struct wireless_dev * +wl_cfgp2p_add_p2p_disc_if(struct bcm_cfg80211 *cfg) +{ + struct wireless_dev *wdev = NULL; + struct ether_addr primary_mac; + + if (!cfg) + return ERR_PTR(-EINVAL); + + WL_TRACE(("Enter\n")); + + if (cfg->p2p_wdev) { + CFGP2P_ERR(("p2p_wdev defined already.\n")); + return ERR_PTR(-ENFILE); + } + + wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); + if (unlikely(!wdev)) { + WL_ERR(("Could not allocate wireless device\n")); + return ERR_PTR(-ENOMEM); + } + + memset(&primary_mac, 0, sizeof(primary_mac)); + get_primary_mac(cfg, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, + &cfg->p2p->dev_addr, &cfg->p2p->int_addr); + + wdev->wiphy = cfg->wdev->wiphy; + wdev->iftype = NL80211_IFTYPE_P2P_DEVICE; + memcpy(wdev->address, &cfg->p2p->dev_addr, ETHER_ADDR_LEN); + +#if defined(WL_NEWCFG_PRIVCMD_SUPPORT) + if (cfg->p2p_net) + memcpy(cfg->p2p_net->dev_addr, &cfg->p2p->dev_addr, ETHER_ADDR_LEN); +#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */ + + /* store p2p wdev ptr for further reference. */ + cfg->p2p_wdev = wdev; + + CFGP2P_ERR(("P2P interface registered\n")); + + return wdev; +} + +int +wl_cfgp2p_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev) +{ + int ret = 0; + struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); + + if (!cfg) + return -EINVAL; + + WL_TRACE(("Enter\n")); + + ret = wl_cfgp2p_set_firm_p2p(cfg); + if (unlikely(ret < 0)) { + CFGP2P_ERR(("Set P2P in firmware failed, ret=%d\n", ret)); + goto exit; + } + + ret = wl_cfgp2p_enable_discovery(cfg, bcmcfg_to_prmry_ndev(cfg), NULL, 0); + if (unlikely(ret < 0)) { + CFGP2P_ERR(("P2P enable discovery failed, ret=%d\n", ret)); + goto exit; + } + + p2p_on(cfg) = true; + + CFGP2P_DBG(("P2P interface started\n")); + +exit: + return ret; +} + +void +wl_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev) +{ + int ret = 0; + struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); + + if (!cfg) + return; + + WL_TRACE(("Enter\n")); + + ret = wl_cfg80211_scan_stop(wdev); + if (unlikely(ret < 0)) { + CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret)); + } + + ret = wl_cfgp2p_disable_discovery(cfg); + if (unlikely(ret < 0)) { + CFGP2P_ERR(("P2P disable discovery failed, ret=%d\n", ret)); + } + + p2p_on(cfg) = false; + + CFGP2P_DBG(("P2P interface stopped\n")); + + return; +} + +int +wl_cfgp2p_del_p2p_disc_if(struct wireless_dev *wdev, struct bcm_cfg80211 *cfg) +{ + if (!wdev) + return -EINVAL; + + WL_TRACE(("Enter\n")); + + cfg80211_unregister_wdev(wdev); + + kfree(wdev); + + if (cfg) + cfg->p2p_wdev = NULL; + + CFGP2P_ERR(("P2P interface unregistered\n")); + + return 0; +} +#endif /* WL_CFG80211_P2P_DEV_IF */ |