diff options
author | Lin Ma <linm@broadcom.com> | 2011-07-18 11:42:36 -0700 |
---|---|---|
committer | Dmitry Shmidt <dimitrysh@google.com> | 2011-07-21 17:13:52 -0700 |
commit | 2f66cb426e32ac6c731e4eda09aded204a800d64 (patch) | |
tree | 35cc7eeb8ec6f72697259048e85e6b21c25dce9d /drivers/net/wireless/bcmdhd/wl_cfg80211.c | |
parent | b06f3b5edb8f9256f0435f13a439074291cd9055 (diff) | |
download | kernel_samsung_crespo-2f66cb426e32ac6c731e4eda09aded204a800d64.zip kernel_samsung_crespo-2f66cb426e32ac6c731e4eda09aded204a800d64.tar.gz kernel_samsung_crespo-2f66cb426e32ac6c731e4eda09aded204a800d64.tar.bz2 |
Update to 5.90.125.40
Add monitor interface support and fix cfg80211 management frame isses
Add support for hostapd
Use private command to get p2p device address
Change-Id: Ie490e38f1af9f259ff4a96b2f7d367119c65c377
Signed-off-by: Howard M. Harte <hharte@broadcom.com>
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'drivers/net/wireless/bcmdhd/wl_cfg80211.c')
-rw-r--r-- | drivers/net/wireless/bcmdhd/wl_cfg80211.c | 1143 |
1 files changed, 842 insertions, 301 deletions
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 22b636d..69180b5 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -29,6 +29,11 @@ #include <osl.h> #include <linux/kernel.h> +/* + * sys proc file will be REMOVED in next release + */ +#undef CONFIG_SYSCTL + #ifdef CONFIG_SYSCTL #include <linux/sysctl.h> #endif @@ -189,6 +194,7 @@ static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_pmksa *pmksa); static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev); +static void wl_notify_escan_complete(struct wl_priv *wl, bool aborted); /* * event & event Q handlers for cfg80211 interfaces */ @@ -331,6 +337,7 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl); static s32 __wl_cfg80211_down(struct wl_priv *wl); static s32 wl_dongle_probecap(struct wl_priv *wl); static void wl_init_conf(struct wl_conf *conf); +static s32 wl_dongle_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add); static s32 wl_dongle_eventmsg(struct net_device *ndev); /* @@ -353,6 +360,8 @@ static s32 wl_pattern_atoh(s8 *src, s8 *dst); static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode); static s32 wl_update_wiphybands(struct wl_priv *wl); #endif /* !EMBEDDED_PLATFORM */ +static __used void wl_dongle_poweron(struct wl_priv *wl); +static __used void wl_dongle_poweroff(struct wl_priv *wl); static s32 wl_config_dongle(struct wl_priv *wl, bool need_lock); /* @@ -404,6 +413,12 @@ static void wl_debugfs_remove_netdev(struct wl_priv *wl); static int wl_setup_rfkill(struct wl_priv *wl); static int wl_rfkill_set(void *data, bool blocked); +/* + * Some external functions, TODO: move them to dhd_linux.h + */ +int dhd_add_monitor(char *name, struct net_device **new_ndev); +int dhd_start_xmit(struct sk_buff *skb, struct net_device *net); + #define WL_PRIV_GET() \ ({ \ struct wl_iface *ci = NULL; \ @@ -418,13 +433,17 @@ static int wl_rfkill_set(void *data, bool blocked); #define CHECK_SYS_UP() \ do { \ struct wl_priv *wl = WL_PRIV_GET(); \ - if (unlikely(!test_bit(WL_STATUS_READY, &wl->status))) { \ + if (unlikely(!wl_get_drv_status(wl, READY))) { \ WL_INFO(("device is not ready : status (%d)\n", \ (int)wl->status)); \ return -EIO; \ } \ } while (0) +#define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE || \ + (akm) == RSN_AKM_UNSPECIFIED || \ + (akm) == RSN_AKM_PSK) + extern int dhd_wait_pend8021x(struct net_device *dev); #if (WL_DBG_LEVEL > 0) @@ -773,6 +792,16 @@ wl_dbg_dump_wps_ie(char *wps_ie) } } +static struct net_device* wl_cfg80211_add_monitor_if(char *name) +{ + int ret = 0; + struct net_device* ndev = NULL; + + ret = dhd_add_monitor(name, &ndev); + WL_ERR(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev)); + return ndev; +} + static struct net_device * wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, enum nl80211_iftype type, u32 *flags, @@ -780,7 +809,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, { s32 err; s32 timeout = -1; - s32 wlif_type; + s32 wlif_type = -1; s32 index = 0; s32 mode = 0; chanspec_t chspec; @@ -798,7 +827,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, mode = WL_MODE_IBSS; return NULL; case NL80211_IFTYPE_MONITOR: - return wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); + return wl_cfg80211_add_monitor_if(name); case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_STATION: wlif_type = WL_P2P_IF_CLIENT; @@ -819,35 +848,37 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, WL_ERR(("name is NULL\n")); return NULL; } + if (wl->p2p_supported && (wlif_type != -1)) { + if (wl_get_p2p_status(wl, IF_DELETING) == 1) { + /* wait till IF_DEL is complete + * release the lock for the unregister to proceed + */ + rtnl_unlock(); + WL_INFO(("%s: Released the lock and wait till IF_DEL is complete\n", + __func__)); + timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, + (wl_get_p2p_status(wl, IF_DELETING) == false), + msecs_to_jiffies(MAX_WAIT_TIME)); - if (wl_get_p2p_status(wl, IF_DELETING) == 1) { - /* wait till IF_DEL is complete - * release the lock for the unregister to proceed - */ - rtnl_unlock(); - WL_INFO(("%s: Released the lock and wait till IF_DEL is complete\n", __func__)); - timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, - (wl_get_p2p_status(wl, IF_DELETING) == FALSE), - msecs_to_jiffies(MAX_WAIT_TIME)); - - /* put back the rtnl_lock again */ - rtnl_lock(); - if (timeout > 0) { - WL_ERR(("IF DEL is Success\n")); + /* put back the rtnl_lock again */ + rtnl_lock(); + if (timeout > 0) { + WL_ERR(("IF DEL is Success\n")); - } else { - WL_ERR(("%s: timeount < 0, return -EAGAIN\n", __func__)); - return ERR_PTR(-EAGAIN); + } else { + WL_ERR(("%s: timeount < 0, return -EAGAIN\n", __func__)); + return ERR_PTR(-EAGAIN); + } + } + if (!p2p_on(wl) && strstr(name, WL_P2P_INTERFACE_PREFIX)) { + p2p_on(wl) = true; + wl_cfgp2p_set_firm_p2p(wl); + wl_cfgp2p_init_discovery(wl); } - } - if (!p2p_on(wl) && strstr(name, WL_P2P_INTERFACE_PREFIX)) { - p2p_on(wl) = true; - wl_cfgp2p_init_discovery(wl); - } - memset(wl->p2p.vir_ifname, 0, IFNAMSIZ); - strncpy(wl->p2p.vir_ifname, name, IFNAMSIZ - 1); - wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p.dev_addr, &wl->p2p.int_addr); + memset(wl->p2p->vir_ifname, 0, IFNAMSIZ); + strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1); + wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); /* Temporary use channel 11, in case GO will be changed with set_channel API */ chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN); @@ -856,13 +887,13 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, * bss: "wl p2p_ifadd" */ wl_set_p2p_status(wl, IF_ADD); - err = wl_cfgp2p_ifadd(wl, &wl->p2p.int_addr, htod32(wlif_type), chspec); + err = wl_cfgp2p_ifadd(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec); if (unlikely(err)) return ERR_PTR(-ENOMEM); timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, - (wl_get_p2p_status(wl, IF_ADD) == FALSE), + (wl_get_p2p_status(wl, IF_ADD) == false), msecs_to_jiffies(MAX_WAIT_TIME)); if (timeout > 0 && (!wl_get_p2p_status(wl, IF_ADD))) { @@ -873,7 +904,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, return ERR_PTR(-ENOMEM); } vwdev->wiphy = wl->wdev->wiphy; - WL_INFO((" virtual interface(%s) is created \n", wl->p2p.vir_ifname)); + WL_INFO((" virtual interface(%s) is created \n", wl->p2p->vir_ifname)); index = alloc_idx_vwdev(wl); wl->vwdev[index] = vwdev; vwdev->iftype = @@ -883,20 +914,19 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, _ndev->ieee80211_ptr = vwdev; SET_NETDEV_DEV(_ndev, wiphy_dev(vwdev->wiphy)); vwdev->netdev = _ndev; - set_bit(WL_STATUS_READY, &wl->status); - wl->p2p.vif_created = TRUE; + wl_set_drv_status(wl, READY); + wl->p2p->vif_created = true; set_mode_by_netdev(wl, _ndev, mode); wl = wdev_to_wl(vwdev); return _ndev; } else { wl_clr_p2p_status(wl, IF_ADD); - WL_ERR((" virtual interface(%s) is not created timeout=%d\n", - wl->p2p.vir_ifname, timeout)); - memset(wl->p2p.vir_ifname, '\0', IFNAMSIZ); - wl->p2p.vif_created = FALSE; + WL_ERR((" virtual interface(%s) is not created \n", wl->p2p->vir_ifname)); + memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ); + wl->p2p->vif_created = false; + } } - return ERR_PTR(-ENODEV); } @@ -906,19 +936,31 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) { struct ether_addr p2p_mac; struct wl_priv *wl = WL_PRIV_GET(); - memcpy(p2p_mac.octet, wl->p2p.int_addr.octet, ETHER_ADDR_LEN); - if (wl->p2p.vif_created) { - if (test_bit(WL_STATUS_SCANNING, &wl->status)) { - wl_cfg80211_scan_abort(wl, dev); - } - wl_cfgp2p_ifdel(wl, &p2p_mac); - WL_ERR(("ifdel command sent to Firmware.. " - "and we just come out without waiting..")); - wl_set_p2p_status(wl, IF_DELETING); + s32 timeout = -1; + + if (wl->p2p_supported) { + memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN); + if (wl->p2p->vif_created) { + if (wl_get_drv_status(wl, SCANNING)) { + wl_cfg80211_scan_abort(wl, dev); + } + wl_cfgp2p_ifdel(wl, &p2p_mac); + wl_set_p2p_status(wl, IF_DELETING); + + /* Wait for any pending scan req to get aborted from the sysioc context */ + timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, + (wl->scan_request == false), + msecs_to_jiffies(MAX_WAIT_TIME)); + + if (timeout > 0 && (!wl->scan_request)) { + WL_DBG(("IFDEL Operations Done")); + } else { + WL_ERR(("IFDEL didn't complete properly")); + } + } } - WL_DBG(("Done\n")); return 0; } @@ -935,7 +977,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, s32 mode = 0; chanspec_t chspec; struct wl_priv *wl = WL_PRIV_GET(); - CHECK_SYS_UP(); + WL_DBG(("Enter \n")); switch (type) { case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_WDS: @@ -963,21 +1005,36 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, } - if (ap && wl->p2p.vif_created) { - WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p.vif_created, - p2p_on(wl))); - chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN); - wlif_type = ap ? WL_P2P_IF_GO : WL_P2P_IF_CLIENT; - WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d)\n", ndev->name, ap, infra, type)); - wl_set_p2p_status(wl, IF_CHANGING); - wl_clr_p2p_status(wl, IF_CHANGED); - err = wl_cfgp2p_ifchange(wl, &wl->p2p.int_addr, htod32(wlif_type), chspec); - timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, - (wl_get_p2p_status(wl, IF_CHANGED) == TRUE), - msecs_to_jiffies(MAX_WAIT_TIME)); + if (ap) { set_mode_by_netdev(wl, ndev, mode); - wl_clr_p2p_status(wl, IF_CHANGING); - wl_clr_p2p_status(wl, IF_CHANGED); + if (wl->p2p_supported && wl->p2p->vif_created) { + WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p->vif_created, + p2p_on(wl))); + chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN); + wlif_type = ap ? WL_P2P_IF_GO : WL_P2P_IF_CLIENT; + WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d)\n", + ndev->name, ap, infra, type)); + wl_set_p2p_status(wl, IF_CHANGING); + wl_clr_p2p_status(wl, IF_CHANGED); + err = wl_cfgp2p_ifchange(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec); + timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, + (wl_get_p2p_status(wl, IF_CHANGED) == true), + msecs_to_jiffies(MAX_WAIT_TIME)); + set_mode_by_netdev(wl, ndev, mode); + wl_clr_p2p_status(wl, IF_CHANGING); + wl_clr_p2p_status(wl, IF_CHANGED); + } else if (ndev == wl_to_prmry_ndev(wl) && + !wl_get_drv_status(wl, AP_CREATED)) { + wl_set_drv_status(wl, AP_CREATING); + if (!wl->ap_info && + !(wl->ap_info = kzalloc(sizeof(struct ap_info), GFP_KERNEL))) { + WL_ERR(("struct ap_saved_ie allocation failed\n")); + return -ENOMEM; + } + } else { + WL_ERR(("Cannot change the interface for GO or SOFTAP\n")); + return -EINVAL; + } } ndev->ieee80211_ptr->iftype = type; @@ -993,20 +1050,22 @@ wl_cfg80211_notify_ifadd(struct net_device *net) WL_ERR(("net is NULL\n")); return 0; } - - WL_DBG(("IF_ADD event called from dongle, old interface name: %s, new name: %s\n", - net->name, wl->p2p.vir_ifname)); - /* Assign the net device to CONNECT BSSCFG */ - strncpy(net->name, wl->p2p.vir_ifname, IFNAMSIZ - 1); - wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = net; - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = P2PAPI_BSSCFG_CONNECTION; - wl_clr_p2p_status(wl, IF_ADD); - wake_up_interruptible(&wl->dongle_event_wait); + if (wl->p2p_supported) { + WL_DBG(("IF_ADD event called from dongle, old interface name: %s," + "new name: %s\n", net->name, wl->p2p->vir_ifname)); + /* Assign the net device to CONNECT BSSCFG */ + strncpy(net->name, wl->p2p->vir_ifname, IFNAMSIZ - 1); + wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = net; + wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = + P2PAPI_BSSCFG_CONNECTION; + wl_clr_p2p_status(wl, IF_ADD); + wake_up_interruptible(&wl->dongle_event_wait); + } return ret; } s32 -wl_cfg80211_notify_ifdel(struct net_device *net) +wl_cfg80211_ifdel_ops(struct net_device *net) { struct wl_priv *wl = WL_PRIV_GET(); @@ -1015,15 +1074,39 @@ wl_cfg80211_notify_ifdel(struct net_device *net) return 0; } - WL_DBG(("IF_DEL event called from dongle, _net name: %s, vif name: %s\n", - net->name, wl->p2p.vir_ifname)); - if (wl->p2p.vif_created) { + if ((wl->p2p->vif_created) && (wl->scan_request)) { + + /* Abort any pending scan requests */ + wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; + rtnl_lock(); + WL_INFO(("ESCAN COMPLETED\n")); + wl_notify_escan_complete(wl, true); + rtnl_unlock(); + } + + /* Wake up any waiting thread */ + wake_up_interruptible(&wl->dongle_event_wait); + + return 0; +} + +s32 +wl_cfg80211_notify_ifdel(struct net_device *net) +{ + struct wl_priv *wl = WL_PRIV_GET(); + + + if (wl->p2p->vif_created) { s32 index = 0; - memset(wl->p2p.vir_ifname, '\0', IFNAMSIZ); + + WL_DBG(("IF_DEL event called from dongle, _net name: %s, vif name: %s\n", + net->name, wl->p2p->vir_ifname)); + + memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ); index = wl_cfgp2p_find_idx(wl, net); wl_to_p2p_bss_ndev(wl, index) = NULL; wl_to_p2p_bss_bssidx(wl, index) = 0; - wl->p2p.vif_created = FALSE; + wl->p2p->vif_created = false; set_mode_by_netdev(wl, net, -1); wl_cfgp2p_clear_management_ie(wl, index); @@ -1032,12 +1115,13 @@ wl_cfg80211_notify_ifdel(struct net_device *net) if (index >= 0) { free_vwdev_by_index(wl, index); } - /* Another option.. Make the IF_ADD wait, if the IF_DEL is not complete.. */ + } + wl_clr_p2p_status(wl, IF_DELETING); - WL_ERR(("Cleared IF_DELETING status bit\n")); + + /* Wake up any waiting thread */ wake_up_interruptible(&wl->dongle_event_wait); - WL_ERR(("Cleared IF_DELETING status bit DONE WAKEUP Interruptible\n")); - } + return 0; } @@ -1144,7 +1228,7 @@ static s32 wl_do_iscan(struct wl_priv *wl) passive_scan = wl->active_scan ? 0 : 1; err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, - &passive_scan, sizeof(passive_scan), FALSE); + &passive_scan, sizeof(passive_scan), false); if (unlikely(err)) { WL_DBG(("error (%d)\n", err)); return err; @@ -1171,8 +1255,8 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, wlc_ssid_t *ssid, uint WL_DBG(("Enter \n")); - if ((ndev == wl_to_prmry_ndev(wl)) && - !p2p_scan(wl)) { + if (!wl->p2p_supported || ((ndev == wl_to_prmry_ndev(wl)) && + !p2p_scan(wl))) { /* LEGACY SCAN TRIGGER */ WL_DBG(("LEGACY SCAN START\n")); if (ssid && ssid->SSID_len) { @@ -1255,7 +1339,7 @@ wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev, wl wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING; passive_scan = wl->active_scan ? 0 : 1; err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, - &passive_scan, sizeof(passive_scan), FALSE); + &passive_scan, sizeof(passive_scan), false); if (unlikely(err)) { WL_DBG(("error (%d)\n", err)); return err; @@ -1284,11 +1368,11 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, bool spec_scan; s32 err = 0; - if (unlikely(test_bit(WL_STATUS_SCANNING, &wl->status))) { + if (unlikely(wl_get_drv_status(wl, SCANNING))) { WL_ERR(("Scanning already : status (%d)\n", (int)wl->status)); return -EAGAIN; } - if (unlikely(test_bit(WL_STATUS_SCAN_ABORTING, &wl->status))) { + if (unlikely(wl_get_drv_status(wl, SCAN_ABORTING))) { WL_ERR(("Scanning being aborted : status (%d)\n", (int)wl->status)); return -EAGAIN; @@ -1305,33 +1389,37 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, } else if (wl->escan_on) { escan_req = true; if (ssids->ssid_len && IS_P2P_SSID(ssids->ssid)) { - /* p2p scan trigger */ - if (p2p_on(wl) == false) { - /* p2p on at the first time */ - p2p_on(wl) = true; - wl_cfgp2p_set_firm_p2p(wl); + if (wl->p2p_supported) { + /* p2p scan trigger */ + if (p2p_on(wl) == false) { + /* p2p on at the first time */ + p2p_on(wl) = true; + wl_cfgp2p_set_firm_p2p(wl); + } + p2p_scan(wl) = true; } - p2p_scan(wl) = true; - } else { /* legacy scan trigger * So, we have to disable p2p discovery if p2p discovery is on */ - p2p_scan(wl) = false; - /* If Netdevice is not equals to primary and p2p is on - * , we will do p2p scan using P2PAPI_BSSCFG_DEVICE. - */ - if (p2p_on(wl) && (ndev != wl_to_prmry_ndev(wl))) - p2p_scan(wl) = true; + if (wl->p2p_supported) { + p2p_scan(wl) = false; + /* If Netdevice is not equals to primary and p2p is on + * , we will do p2p scan using P2PAPI_BSSCFG_DEVICE. + */ + if (p2p_on(wl) && (ndev != wl_to_prmry_ndev(wl))) + p2p_scan(wl) = true; + + if (p2p_scan(wl) == false) { + if (wl_get_p2p_status(wl, DISCOVERY_ON)) { + err = wl_cfgp2p_discover_enable_search(wl, + false); + if (unlikely(err)) { + goto scan_out; + } - if (p2p_scan(wl) == false) { - if (wl_get_p2p_status(wl, DISCOVERY_ON)) { - err = wl_cfgp2p_discover_enable_search(wl, FALSE); - if (unlikely(err)) { - goto scan_out; } - } } } @@ -1341,7 +1429,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, ssids = this_ssid; } wl->scan_request = request; - set_bit(WL_STATUS_SCANNING, &wl->status); + wl_set_drv_status(wl, SCANNING); if (iscan_req) { err = wl_do_iscan(wl); if (likely(!err)) @@ -1354,13 +1442,15 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, memcpy(ssid_info.SSID, ssids->ssid, ssids->ssid_len); ssid_info.SSID_len = ssids->ssid_len; + if (wl->p2p_supported) { + if (p2p_on(wl) && p2p_scan(wl)) { - if (p2p_on(wl) && p2p_scan(wl)) { - - err = wl_cfgp2p_enable_discovery(wl, ndev, request->ie, request->ie_len); + err = wl_cfgp2p_enable_discovery(wl, ndev, + request->ie, request->ie_len); - if (unlikely(err)) { - goto scan_out; + if (unlikely(err)) { + goto scan_out; + } } } err = wl_do_escan(wl, wiphy, ndev, &ssid_info); @@ -1386,13 +1476,13 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, WL_DBG(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len)); passive_scan = wl->active_scan ? 0 : 1; err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, - &passive_scan, sizeof(passive_scan), FALSE); + &passive_scan, sizeof(passive_scan), false); if (unlikely(err)) { WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n", err)); goto scan_out; } err = wldev_ioctl(ndev, WLC_SCAN, &sr->ssid, - sizeof(sr->ssid), FALSE); + sizeof(sr->ssid), false); if (err) { if (err == -EBUSY) { WL_INFO(("system busy : scan for \"%s\" " @@ -1407,7 +1497,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, return 0; scan_out: - clear_bit(WL_STATUS_SCANNING, &wl->status); + wl_clr_drv_status(wl, SCANNING); wl->scan_request = NULL; return err; } @@ -1439,7 +1529,7 @@ static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val) len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf)); BUG_ON(unlikely(!len)); - err = wldev_ioctl(dev, WLC_SET_VAR, buf, len, FALSE); + err = wldev_ioctl(dev, WLC_SET_VAR, buf, len, false); if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); } @@ -1461,7 +1551,7 @@ wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval) len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf)); BUG_ON(unlikely(!len)); - err = wldev_ioctl(dev, WLC_GET_VAR, &var, len, FALSE); + err = wldev_ioctl(dev, WLC_GET_VAR, &var, len, false); if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); } @@ -1500,7 +1590,7 @@ static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l) u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL); retry = htod32(retry); - err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), FALSE); + err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), false); if (unlikely(err)) { WL_ERR(("cmd (%d) , error (%d)\n", cmd, err)); return err; @@ -1612,7 +1702,7 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN); err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, - sizeof(join_params), FALSE); + sizeof(join_params), false); if (unlikely(err)) { WL_ERR(("Error (%d)\n", err)); return err; @@ -1985,12 +2075,12 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID, join_params.ssid.SSID_len)); } - err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, FALSE); + err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, false); if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); return err; } - set_bit(WL_STATUS_CONNECTING, &wl->status); + wl_set_drv_status(wl, CONNECTING); return err; } @@ -2012,7 +2102,7 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, memcpy(&scbval.ea, &wl->bssid, ETHER_ADDR_LEN); scbval.val = htod32(scbval.val); err = wldev_ioctl(dev, WLC_DISASSOC, &scbval, - sizeof(scb_val_t), FALSE); + sizeof(scb_val_t), false); if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); return err; @@ -2053,7 +2143,7 @@ wl_cfg80211_set_tx_power(struct wiphy *wiphy, /* Make sure radio is off or on as far as software is concerned */ disable = WL_RADIO_SW_DISABLE << 16; disable = htod32(disable); - err = wldev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable), FALSE); + err = wldev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable), false); if (unlikely(err)) { WL_ERR(("WLC_SET_RADIO error (%d)\n", err)); return err; @@ -2116,7 +2206,7 @@ wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, index = (u32) key_idx; index = htod32(index); err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index, - sizeof(index), FALSE); + sizeof(index), false); if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); } @@ -2132,7 +2222,7 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, struct wl_wsec_key key; s32 err = 0; s32 bssidx = wl_cfgp2p_find_idx(wl, dev); - + s32 mode = get_mode_by_netdev(wl, dev); memset(&key, 0, sizeof(key)); key.index = (u32) key_idx; @@ -2155,11 +2245,11 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("Invalid key length (%d)\n", key.len)); return -EINVAL; } - WL_DBG(("Setting the key index %d\n", key.index)); memcpy(key.data, params->key, key.len); - if (params->cipher == WLAN_CIPHER_SUITE_TKIP) { + if ((mode == WL_MODE_BSS) && + (params->cipher == WLAN_CIPHER_SUITE_TKIP)) { u8 keybuf[8]; memcpy(keybuf, &key.data[24], sizeof(keybuf)); memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); @@ -2225,10 +2315,10 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, s32 val = 0; s32 wsec = 0; s32 err = 0; - uint8 keybuf[8]; + u8 keybuf[8]; s32 bssidx = 0; struct wl_priv *wl = WL_PRIV_GET(); - + s32 mode = get_mode_by_netdev(wl, dev); WL_DBG(("key index (%d)\n", key_idx)); CHECK_SYS_UP(); @@ -2264,10 +2354,12 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, case WLAN_CIPHER_SUITE_TKIP: key.algo = CRYPTO_ALGO_TKIP; val = TKIP_ENABLED; - /* wpa_supplicant switches the third and fourth quarters of the TKIP key, linm */ - bcopy(&key.data[24], keybuf, sizeof(keybuf)); - bcopy(&key.data[16], &key.data[24], sizeof(keybuf)); - bcopy(keybuf, &key.data[16], sizeof(keybuf)); + /* wpa_supplicant switches the third and fourth quarters of the TKIP key */ + if (mode == WL_MODE_BSS) { + bcopy(&key.data[24], keybuf, sizeof(keybuf)); + bcopy(&key.data[16], &key.data[24], sizeof(keybuf)); + bcopy(keybuf, &key.data[16], sizeof(keybuf)); + } WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n")); break; case WLAN_CIPHER_SUITE_AES_CMAC: @@ -2312,7 +2404,7 @@ exit: /* TODO: Removed in P2P, check later --lm */ val = 1; /* assume shared key. otherwise 0 */ val = htod32(val); - err = wldev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val), FALSE); + err = wldev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val), false); if (unlikely(err)) { WL_ERR(("WLC_SET_AUTH error (%d)\n", err)); return err; @@ -2359,7 +2451,7 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, /* TODO: Removed in P2P twig, check later --lin */ val = 0; /* assume open key. otherwise 1 */ val = htod32(val); - err = wldev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val), FALSE); + err = wldev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val), false); if (unlikely(err)) { WL_ERR(("WLC_SET_AUTH error (%d)\n", err)); return err; @@ -2395,28 +2487,28 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("WLC_GET_WSEC error (%d)\n", err)); return err; } - switch (wsec) { - case WEP_ENABLED: - sec = wl_read_prof(wl, WL_PROF_SEC); - if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { - params.cipher = WLAN_CIPHER_SUITE_WEP40; - WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n")); - } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) { - params.cipher = WLAN_CIPHER_SUITE_WEP104; - WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n")); - } - break; - case TKIP_ENABLED: - params.cipher = WLAN_CIPHER_SUITE_TKIP; - WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n")); - break; - case AES_ENABLED: - params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; - WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n")); - break; - default: - WL_ERR(("Invalid algo (0x%x)\n", wsec)); - return -EINVAL; + switch (wsec & ~SES_OW_ENABLED) { + case WEP_ENABLED: + sec = wl_read_prof(wl, WL_PROF_SEC); + if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { + params.cipher = WLAN_CIPHER_SUITE_WEP40; + WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n")); + } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) { + params.cipher = WLAN_CIPHER_SUITE_WEP104; + WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n")); + } + break; + case TKIP_ENABLED: + params.cipher = WLAN_CIPHER_SUITE_TKIP; + WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n")); + break; + case AES_ENABLED: + params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; + WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n")); + break; + default: + WL_ERR(("Invalid algo (0x%x)\n", wsec)); + return -EINVAL; } callback(cookie, ¶ms); @@ -2450,7 +2542,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, } /* Report the current tx rate */ - err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), FALSE); + err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false); if (err) { WL_ERR(("Could not get rate (%d)\n", err)); } else { @@ -2460,11 +2552,11 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, WL_DBG(("Rate %d Mbps\n", (rate / 2))); } - if (test_bit(WL_STATUS_CONNECTED, &wl->status)) { + if (wl_get_drv_status(wl, CONNECTED)) { memset(&scb_val, 0, sizeof(scb_val)); scb_val.val = 0; err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val, - sizeof(scb_val_t), FALSE); + sizeof(scb_val_t), false); if (unlikely(err)) { WL_ERR(("Could not get rssi (%d)\n", err)); return err; @@ -2476,7 +2568,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, } #if defined(ANDROID_WIRELESS_PATCH) - err = wldev_ioctl(dev, WLC_GET_RATE, &sinfo->link_speed, sizeof(sinfo->link_speed), FALSE); + err = wldev_ioctl(dev, WLC_GET_RATE, &sinfo->link_speed, sizeof(sinfo->link_speed), false); sinfo->link_speed = sinfo->link_speed / 2; /* Convert internal 500Kbps to Mpbs */ if (!err) sinfo->filled |= STATION_LINK_SPEED; @@ -2498,7 +2590,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, pm = enabled ? PM_FAST : PM_OFF; pm = htod32(pm); WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled"))); - err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), FALSE); + err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), false); if (unlikely(err)) { if (err == -ENODEV) WL_DBG(("net_device is not ready yet\n")); @@ -2553,7 +2645,7 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev, /* addr param is always NULL. ignore it */ /* Get current rateset */ err = wldev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, - sizeof(rateset), FALSE); + sizeof(rateset), false); if (unlikely(err)) { WL_ERR(("could not get current rateset (%d)\n", err)); return err; @@ -2623,14 +2715,14 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy) return 0; } - set_bit(WL_STATUS_SCAN_ABORTING, &wl->status); + wl_set_drv_status(wl, SCAN_ABORTING); wl_term_iscan(wl); if (wl->scan_request) { cfg80211_scan_done(wl->scan_request, true); wl->scan_request = NULL; } - clear_bit(WL_STATUS_SCANNING, &wl->status); - clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status); + wl_clr_drv_status(wl, SCANNING); + wl_clr_drv_status(wl, SCAN_ABORTING); return err; } @@ -2640,6 +2732,18 @@ wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list, s32 err) { int i, j; + struct wl_priv *wl = WL_PRIV_GET(); + struct net_device *primary_dev = wl_to_prmry_ndev(wl); + + /* Firmware is supporting pmk list only for STA interface i.e. primary interface + * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init + * Do we really need to support PMK cache in P2P in firmware? + */ + if (primary_dev != dev) { + WL_ERR(("Not supporting Flushing pmklist on virtual" + " interfaces than primary interface\n")); + return err; + } WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid)); for (i = 0; i < pmk_list->pmkids.npmkid; i++) { @@ -2745,7 +2849,6 @@ wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev) { struct wl_priv *wl = WL_PRIV_GET(); s32 err = 0; - CHECK_SYS_UP(); memset(wl->pmk_list, 0, sizeof(*wl->pmk_list)); err = wl_update_pmklist(dev, wl->pmk_list, err); @@ -2806,20 +2909,11 @@ wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev) err = -ENOMEM; } /* Do a scan abort to stop the driver's scan engine */ - err = wldev_ioctl(ndev, WLC_SCAN, params, params_size, FALSE); + err = wldev_ioctl(ndev, WLC_SCAN, params, params_size, false); if (err < 0) { WL_ERR(("scan abort failed \n")); } - /* Report the scan abort to CFG driver too - * We will report it from the thread context, not from this context. - */ - { - wl_event_msg_t msg; - msg.event_type = hton32(WLC_E_ESCAN_RESULT); - msg.status = WLC_E_STATUS_ABORT; - wl_cfg80211_event(ndev, &msg, NULL); - } return err; } static s32 @@ -2834,7 +2928,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, struct wl_priv *wl = WL_PRIV_GET(); dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); WL_DBG(("Enter, netdev_ifidx: %d \n", dev->ifindex)); - if (likely(test_bit(WL_STATUS_SCANNING, &wl->status))) { + if (likely(wl_get_drv_status(wl, SCANNING))) { wl_cfg80211_scan_abort(wl, dev); } @@ -2845,7 +2939,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, cfg80211_ready_on_channel(dev, *cookie, channel, channel_type, duration, GFP_KERNEL); if (!p2p_on(wl)) { - wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p.dev_addr, &wl->p2p.int_addr); + wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); /* In case of p2p_listen command, supplicant send remain_on_channel * without turning on P2P @@ -2867,13 +2961,11 @@ exit: } static s32 -wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, u64 cookie) +wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, + u64 cookie) { - s32 err = 0; WL_DBG((" enter ) netdev_ifidx: %d \n", dev->ifindex)); - - return err; } @@ -2896,7 +2988,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, u32 p2pie_len = 0; u32 wpsie_len = 0; u16 fc; - bool ack = FALSE; + bool ack = false; WL_DBG(("Enter \n")); /* find bssidx based on ndev */ bssidx = wl_cfgp2p_find_idx(wl, dev); @@ -2909,24 +3001,20 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, return -ENODEV; } if (p2p_on(wl)) { - wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p.dev_addr, &wl->p2p.int_addr); - + wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); /* Suspend P2P discovery search-listen to prevent it from changing the * channel. */ - wl_cfgp2p_discover_enable_search(wl, FALSE); - /* Abort the dwell time of any previous off-channel action frame that may - * be still in effect. Sending off-channel action frames relies on the - * driver's scan engine. If a previous off-channel action frame tx is - * still in progress (including the dwell time), then this new action - * frame will not be sent out. - */ - wl_cfg80211_scan_abort(wl, dev); + if ((err = wl_cfgp2p_discover_enable_search(wl, false)) < 0) { + WL_ERR(("Can not disable discovery mode\n")); + return -EFAULT; + } } + mgmt = (const struct ieee80211_mgmt *) buf; fc = mgmt->frame_control; if (fc != IEEE80211_STYPE_ACTION) { - if (p2p_on(wl) && (fc == IEEE80211_STYPE_PROBE_RESP)) { + if (fc == IEEE80211_STYPE_PROBE_RESP) { s32 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN; s32 ie_len = len - ie_offset; if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)(buf + ie_offset), ie_len)) @@ -2953,12 +3041,23 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_PRBRSP_FLAG, (u8 *)wps_ie, wpsie_len + p2pie_len); - + /* remove WLC_E_PROBREQ_MSG event to prevent HOSTAPD + * from responding many probe request + */ + wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false); } } cfg80211_mgmt_tx_status(dev, *cookie, buf, len, true, GFP_KERNEL); goto exit; + } else { + /* Abort the dwell time of any previous off-channel action frame that may + * be still in effect. Sending off-channel action frames relies on the + * driver's scan engine. If a previous off-channel action frame tx is + * still in progress (including the dwell time), then this new action + * frame will not be sent out. + */ + wl_cfg80211_scan_abort(wl, dev); } af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL); @@ -2993,7 +3092,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len); - if (wl->p2p.vif_created) { + if (wl->p2p->vif_created) { wifi_p2p_pub_act_frame_t *act_frm = (wifi_p2p_pub_act_frame_t *) (action_frame->data); /* @@ -3017,7 +3116,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, } } - ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? FALSE : TRUE; + ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true; cfg80211_mgmt_tx_status(dev, *cookie, buf, len, ack, GFP_KERNEL); kfree(af_params); @@ -3077,28 +3176,31 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, channel = ieee80211_frequency_to_channel(chan->center_freq); WL_DBG(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n", dev->ifindex, channel_type, channel)); - wldev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel), FALSE); + wldev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel), false); return err; } static s32 -wl_check_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) +wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) { - s32 len = wpa2ie->len; + s32 len = 0; s32 err = BCME_OK; u16 auth = 0; /* d11 open authentication */ - u16 wpa_auth = 0; u16 count; u32 wsec; u32 pval = 0; u32 gval = 0; + u32 wpa_auth = 0; u8* tmp; wpa_suite_mcast_t *mcast; wpa_suite_ucast_t *ucast; wpa_suite_auth_key_mgmt_t *mgmt; if (wpa2ie == NULL) goto exit; + + WL_DBG(("Enter \n")); + len = wpa2ie->len; /* check the mcast cipher */ mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN]; tmp = mcast->oui; @@ -3141,7 +3243,6 @@ wl_check_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) break; default: WL_ERR(("No Security Info\n")); - break; } /* FOR WPS , set SEC_OW_ENABLED */ wsec = (pval | gval | SES_OW_ENABLED); @@ -3161,33 +3262,171 @@ wl_check_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) break; default: WL_ERR(("No Key Mgmt Info\n")); - break; } /* set auth */ err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx); if (err < 0) { WL_ERR(("auth error %d\n", err)); + return BCME_ERROR; } /* set wsec */ err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx); if (err < 0) { WL_ERR(("wsec error %d\n", err)); + return BCME_ERROR; } /* set upper-layer auth */ err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx); if (err < 0) { WL_ERR(("wpa_auth error %d\n", err)); + return BCME_ERROR; } exit: return 0; } static s32 -wl_check_wpaie(struct net_device *dev, bcm_tlv_t *wpaie, s32 bssidx) +wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx) { + wpa_suite_mcast_t *mcast; + wpa_suite_ucast_t *ucast; + wpa_suite_auth_key_mgmt_t *mgmt; + u16 auth = 0; /* d11 open authentication */ + u16 count; + s32 err = BCME_OK; + s32 len = 0; + u32 i; + u32 wsec; + u32 pval = 0; + u32 gval = 0; + u32 wpa_auth = 0; + u32 tmp = 0; + if (wpaie == NULL) goto exit; + WL_DBG(("Enter \n")); + len = wpaie->length; /* value length */ + len -= WPA_IE_TAG_FIXED_LEN; + /* check for multicast cipher suite */ + if (len < WPA_SUITE_LEN) { + WL_INFO(("no multicast cipher suite\n")); + goto exit; + } + /* pick up multicast cipher */ + mcast = (wpa_suite_mcast_t *)&wpaie[1]; + len -= WPA_SUITE_LEN; + if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) { + if (IS_WPA_CIPHER(mcast->type)) { + tmp = 0; + switch (mcast->type) { + case WPA_CIPHER_NONE: + tmp = 0; + break; + case WPA_CIPHER_WEP_40: + case WPA_CIPHER_WEP_104: + tmp = WEP_ENABLED; + break; + case WPA_CIPHER_TKIP: + tmp = TKIP_ENABLED; + break; + case WPA_CIPHER_AES_CCM: + tmp = AES_ENABLED; + break; + default: + WL_ERR(("No Security Info\n")); + } + gval |= tmp; + } + } + /* Check for unicast suite(s) */ + if (len < WPA_IE_SUITE_COUNT_LEN) { + WL_INFO(("no unicast suite\n")); + goto exit; + } + /* walk thru unicast cipher list and pick up what we recognize */ + ucast = (wpa_suite_ucast_t *)&mcast[1]; + count = ltoh16_ua(&ucast->count); + len -= WPA_IE_SUITE_COUNT_LEN; + for (i = 0; i < count && len >= WPA_SUITE_LEN; + i++, len -= WPA_SUITE_LEN) { + if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) { + if (IS_WPA_CIPHER(ucast->list[i].type)) { + tmp = 0; + switch (ucast->list[i].type) { + case WPA_CIPHER_NONE: + tmp = 0; + break; + case WPA_CIPHER_WEP_40: + case WPA_CIPHER_WEP_104: + tmp = WEP_ENABLED; + break; + case WPA_CIPHER_TKIP: + tmp = TKIP_ENABLED; + break; + case WPA_CIPHER_AES_CCM: + tmp = AES_ENABLED; + break; + default: + WL_ERR(("No Security Info\n")); + } + pval |= tmp; + } + } + } + len -= (count - i) * WPA_SUITE_LEN; + /* Check for auth key management suite(s) */ + if (len < WPA_IE_SUITE_COUNT_LEN) { + WL_INFO((" no auth key mgmt suite\n")); + goto exit; + } + /* walk thru auth management suite list and pick up what we recognize */ + mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count]; + count = ltoh16_ua(&mgmt->count); + len -= WPA_IE_SUITE_COUNT_LEN; + for (i = 0; i < count && len >= WPA_SUITE_LEN; + i++, len -= WPA_SUITE_LEN) { + if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) { + if (IS_WPA_AKM(mgmt->list[i].type)) { + tmp = 0; + switch (mgmt->list[i].type) { + case RSN_AKM_NONE: + tmp = WPA_AUTH_NONE; + break; + case RSN_AKM_UNSPECIFIED: + tmp = WPA_AUTH_UNSPECIFIED; + break; + case RSN_AKM_PSK: + tmp = WPA_AUTH_PSK; + break; + default: + WL_ERR(("No Key Mgmt Info\n")); + } + wpa_auth |= tmp; + } + } + + } + /* FOR WPS , set SEC_OW_ENABLED */ + wsec = (pval | gval | SES_OW_ENABLED); + /* set auth */ + err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx); + if (err < 0) { + WL_ERR(("auth error %d\n", err)); + return BCME_ERROR; + } + /* set wsec */ + err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx); + if (err < 0) { + WL_ERR(("wsec error %d\n", err)); + return BCME_ERROR; + } + /* set upper-layer auth */ + err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx); + if (err < 0) { + WL_ERR(("wpa_auth error %d\n", err)); + return BCME_ERROR; + } exit: return 0; } @@ -3198,27 +3437,29 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, { s32 err = BCME_OK; bcm_tlv_t *ssid_ie; + wlc_ssid_t ssid; + struct wl_priv *wl = WL_PRIV_GET(); + struct wl_join_params join_params; wpa_ie_fixed_t *wps_ie; wpa_ie_fixed_t *wpa_ie; bcm_tlv_t *wpa2_ie; wifi_p2p_ie_t *p2p_ie; - struct wl_priv *wl = WL_PRIV_GET(); bool is_bssup = false; + bool update_bss = false; u16 wpsie_len = 0; u16 p2pie_len = 0; u8 beacon_ie[IE_MAX_LEN]; s32 ie_offset = 0; s32 bssidx = wl_cfgp2p_find_idx(wl, dev); s32 infra = 1; - - memset(beacon_ie, 0, sizeof(beacon_ie)); - + s32 join_params_size = 0; + s32 ap = 0; WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n", info->interval, info->dtim_period, info->head_len, info->tail_len)); - - - if (p2p_on(wl) && (bssidx >= wl_to_p2p_bss_bssidx(wl, + if (wl->p2p_supported && p2p_on(wl) && + (bssidx >= wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION))) { + memset(beacon_ie, 0, sizeof(beacon_ie)); /* We don't need to set beacon for P2P_GO, * but need to parse ssid from beacon_parameters * because there is no way to set ssid @@ -3228,8 +3469,8 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset], info->head_len - ie_offset, DOT11_MNG_SSID_ID)) != NULL) { - memcpy(wl->p2p.ssid.SSID, ssid_ie->data, ssid_ie->len); - wl->p2p.ssid.SSID_len = ssid_ie->len; + memcpy(wl->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len); + wl->p2p->ssid.SSID_len = ssid_ie->len; WL_DBG(("SSID (%s) in Head \n", ssid_ie->data)); } else { @@ -3238,7 +3479,7 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, /* find the WPSIE */ if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)info->tail, info->tail_len)) != NULL) { - wpsie_len = wps_ie->length + sizeof(wps_ie->tag) + sizeof(wps_ie->length); + wpsie_len = wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN; /* * Should be compared with saved ie before saving it */ @@ -3269,10 +3510,7 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, beacon_ie, wpsie_len + p2pie_len); wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_ASSOCRSP_FLAG, beacon_ie, wpsie_len + p2pie_len); - /* find the WPA_IE */ - if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)info->tail, info->tail_len)) != NULL) { - WL_DBG((" WPA IE is found\n")); - } + /* find the RSN_IE */ if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len, DOT11_MNG_RSN_ID)) != NULL) { @@ -3280,19 +3518,209 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, } is_bssup = wl_cfgp2p_bss_isup(dev, bssidx); - if (!is_bssup && (wpa_ie != NULL || wpa2_ie != NULL)) { - wl_check_wpa2ie(dev, wpa2_ie, bssidx); - wl_check_wpaie(dev, (bcm_tlv_t *)wpa_ie, bssidx); - - err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), FALSE); + if (!is_bssup && (wpa2_ie != NULL)) { + if ((err = wl_validate_wpa2ie(dev, wpa2_ie, bssidx)) < 0) { + WL_ERR(("WPA2 IE parsing error")); + return BCME_ERROR; + } + err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), false); if (err < 0) { WL_ERR(("SET INFRA error %d\n", err)); + return err; } - - err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p.ssid, - sizeof(wl->p2p.ssid), ioctlbuf, sizeof(ioctlbuf), bssidx); - - wl_cfgp2p_bss(dev, bssidx, 1); + err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p->ssid, + sizeof(wl->p2p->ssid), ioctlbuf, sizeof(ioctlbuf), bssidx); + if (err < 0) { + WL_ERR(("GO SSID setting error %d\n", err)); + return err; + } + if ((err = wl_cfgp2p_bss(dev, bssidx, 1)) < 0) { + WL_ERR(("GO Bring up error %d\n", err)); + return err; + } + } + } else if (wl_get_drv_status(wl, AP_CREATING)) { + ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN; + ap = 1; + /* find the SSID */ + if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset], + info->head_len - ie_offset, + DOT11_MNG_SSID_ID)) != NULL) { + memset(&ssid, 0, sizeof(wlc_ssid_t)); + memcpy(ssid.SSID, ssid_ie->data, ssid_ie->len); + WL_DBG(("SSID is (%s) in Head \n", ssid.SSID)); + ssid.SSID_len = ssid_ie->len; + wldev_iovar_setint(dev, "mpc", 0); + wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), false); + wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), false); + wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), false); + /* find the RSN_IE */ + if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len, + DOT11_MNG_RSN_ID)) != NULL) { + WL_DBG((" WPA2 IE is found\n")); + } + /* find the WPA_IE */ + if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)info->tail, + info->tail_len)) != NULL) { + WL_DBG((" WPA IE is found\n")); + } + if ((wpa_ie != NULL || wpa2_ie != NULL)) { + if (wl_validate_wpa2ie(dev, wpa2_ie, bssidx) < 0 || + wl_validate_wpaie(dev, wpa_ie, bssidx) < 0) { + wl->ap_info->security_mode = false; + return BCME_ERROR; + } + wl->ap_info->security_mode = true; + kfree(wl->ap_info->rsn_ie); + kfree(wl->ap_info->wpa_ie); + kfree(wl->ap_info->wps_ie); + if (wpa_ie != NULL) { + /* WPAIE */ + wl->ap_info->rsn_ie = NULL; + wl->ap_info->wpa_ie = kmemdup(wpa_ie, + wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN, + GFP_KERNEL); + } else { + /* RSNIE */ + wl->ap_info->wpa_ie = NULL; + wl->ap_info->rsn_ie = kmemdup(wpa2_ie, + wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN, + GFP_KERNEL); + } + } else + wl->ap_info->security_mode = false; + /* find the WPSIE */ + if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)info->tail, + info->tail_len)) != NULL) { + wpsie_len = wps_ie->length +WPA_RSN_IE_TAG_FIXED_LEN; + /* + * Should be compared with saved ie before saving it + */ + if (wl_dbg_level & WL_DBG_INFO) + wl_dbg_dump_wps_ie((char *) wps_ie); + memcpy(beacon_ie, wps_ie, wpsie_len); + wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, + beacon_ie, wpsie_len); + wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); + /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ + wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true); + } else { + WL_ERR(("No WPSIE in beacon \n")); + } + wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), false); + + memset(&join_params, 0, sizeof(join_params)); + /* join parameters starts with ssid */ + join_params_size = sizeof(join_params.ssid); + memcpy(join_params.ssid.SSID, ssid.SSID, ssid.SSID_len); + join_params.ssid.SSID_len = htod32(ssid.SSID_len); + /* create softap */ + if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, + join_params_size, false)) == 0) { + wl_clr_drv_status(wl, AP_CREATING); + wl_set_drv_status(wl, AP_CREATED); + } + } + } else if (wl_get_drv_status(wl, AP_CREATED)) { + ap = 1; + /* find the WPSIE */ + if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)info->tail, info->tail_len)) != NULL) { + wpsie_len = wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN; + /* + * Should be compared with saved ie before saving it + */ + if (wl_dbg_level & WL_DBG_INFO) + wl_dbg_dump_wps_ie((char *) wps_ie); + memcpy(beacon_ie, wps_ie, wpsie_len); + wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, + beacon_ie, wpsie_len); + if (wl->ap_info->wps_ie && + memcmp(wl->ap_info->wps_ie, wps_ie, wpsie_len)) { + WL_DBG((" WPS IE is changed\n")); + kfree(wl->ap_info->wps_ie); + wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); + /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ + wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true); + } else if (wl->ap_info->wps_ie == NULL) { + WL_DBG((" WPS IE is added\n")); + wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); + /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ + wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true); + } + /* find the RSN_IE */ + if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len, + DOT11_MNG_RSN_ID)) != NULL) { + WL_DBG((" WPA2 IE is found\n")); + } + /* find the WPA_IE */ + if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)info->tail, + info->tail_len)) != NULL) { + WL_DBG((" WPA IE is found\n")); + } + if ((wpa_ie != NULL || wpa2_ie != NULL)) { + if (!wl->ap_info->security_mode) { + /* change from open mode to security mode */ + update_bss = true; + if (wpa_ie != NULL) { + wl->ap_info->wpa_ie = kmemdup(wpa_ie, + wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN, + GFP_KERNEL); + } else { + wl->ap_info->rsn_ie = kmemdup(wpa2_ie, + wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN, + GFP_KERNEL); + } + } else if (wl->ap_info->wpa_ie) { + /* change from WPA mode to WPA2 mode */ + if (wpa2_ie != NULL) { + update_bss = true; + kfree(wl->ap_info->wpa_ie); + wl->ap_info->rsn_ie = kmemdup(wpa2_ie, + wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN, + GFP_KERNEL); + wl->ap_info->wpa_ie = NULL; + } + else if (memcmp(wl->ap_info->wpa_ie, + wpa_ie, wpa_ie->length + + WPA_RSN_IE_TAG_FIXED_LEN)) { + kfree(wl->ap_info->wpa_ie); + update_bss = true; + wl->ap_info->wpa_ie = kmemdup(wpa_ie, + wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN, + GFP_KERNEL); + wl->ap_info->rsn_ie = NULL; + } + } else { + /* change from WPA2 mode to WPA mode */ + if (wpa_ie != NULL) { + update_bss = true; + kfree(wl->ap_info->rsn_ie); + wl->ap_info->rsn_ie = NULL; + wl->ap_info->wpa_ie = kmemdup(wpa_ie, + wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN, + GFP_KERNEL); + } else if (memcmp(wl->ap_info->rsn_ie, + wpa2_ie, wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN)) { + update_bss = true; + kfree(wl->ap_info->rsn_ie); + wl->ap_info->rsn_ie = kmemdup(wpa2_ie, + wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN, + GFP_KERNEL); + wl->ap_info->wpa_ie = NULL; + } + } + if (update_bss) { + wl->ap_info->security_mode = true; + wl_cfgp2p_bss(dev, bssidx, 0); + if (wl_validate_wpa2ie(dev, wpa2_ie, bssidx) < 0 || + wl_validate_wpaie(dev, wpa_ie, bssidx) < 0) { + return BCME_ERROR; + } + wl_cfgp2p_bss(dev, bssidx, 1); + } + } + } else { + WL_ERR(("No WPSIE in beacon \n")); } } return 0; @@ -3400,7 +3828,8 @@ static struct wireless_dev *wl_alloc_wdev(s32 sizeof_iface, wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; wdev->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); + BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) + | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR); wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; @@ -3455,6 +3884,7 @@ static void wl_free_wdev(struct wl_priv *wl) wiphy_unregister(wdev->wiphy); wiphy_free(wdev->wiphy); kfree(wdev); + wl_to_wdev(wl) = NULL; } static s32 wl_inform_bss(struct wl_priv *wl) @@ -3465,13 +3895,11 @@ static s32 wl_inform_bss(struct wl_priv *wl) s32 i; bss_list = wl->bss_list; - /* if (unlikely(bss_list->version != WL_BSS_INFO_VERSION)) { - WL_ERR(("Version %d != %d\n", - bss_list->version, WL_BSS_INFO_VERSION)); + WL_ERR(("Version %d != WL_BSS_INFO_VERSION\n", + bss_list->version)); return -EOPNOTSUPP; } - */ WL_DBG(("scanned AP count (%d)\n", bss_list->count)); bi = next_bss(bss_list, bi); for_each_bss(bss_list, bi, i) { @@ -3618,7 +4046,7 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data) { bool act; - bool isfree = FALSE; + bool isfree = false; s32 err = 0; s32 freq; s32 channel; @@ -3642,7 +4070,7 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, memcpy(body, data, len); wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", &da, sizeof(struct ether_addr), ioctlbuf, sizeof(ioctlbuf), bsscfgidx); - wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, FALSE); + wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); switch (event) { case WLC_E_ASSOC_IND: fc = FC_ASSOC_REQ; @@ -3663,7 +4091,7 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, fc = 0; goto exit; } - if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), FALSE))) + if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) return err; channel = dtoh32(ci.hw_channel); @@ -3682,14 +4110,14 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, &mgmt_frame, &len, body); if (err < 0) goto exit; - isfree = TRUE; + isfree = true; if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) { - cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); + cfg80211_send_rx_assoc(ndev, mgmt_frame, len); } else if (event == WLC_E_DISASSOC_IND) { - cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); + cfg80211_send_disassoc(ndev, mgmt_frame, len); } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) { - cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); + cfg80211_send_deauth(ndev, mgmt_frame, len); } } else { @@ -3712,16 +4140,16 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, act = true; wl_update_prof(wl, e, &act, WL_PROF_ACT); } else if (wl_is_linkdown(wl, e)) { - if (test_bit(WL_STATUS_CONNECTED, &wl->status)) { + if (wl_get_drv_status(wl, CONNECTED)) { printk("link down, call cfg80211_disconnected "); cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); - clear_bit(WL_STATUS_CONNECTED, &wl->status); + wl_clr_drv_status(wl, CONNECTED); wl_link_down(wl); wl_init_prof(wl->profile); } } else if (wl_is_nonetwork(wl, e)) { printk("connect failed e->status 0x%x", (int)ntoh32(e->status)); - if (test_bit(WL_STATUS_CONNECTING, &wl->status)) + if (wl_get_drv_status(wl, CONNECTING)) wl_bss_connect_done(wl, ndev, e, data, false); } else { printk("%s nothing\n", __FUNCTION__); @@ -3758,7 +4186,7 @@ wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len) buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX); BUG_ON(unlikely(!buflen)); - return wldev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen, FALSE); + return wldev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen, false); } static s32 @@ -3772,7 +4200,7 @@ wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf, len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX); BUG_ON(unlikely(!len)); err = wldev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf, - WL_IOCTL_LEN_MAX, FALSE); + WL_IOCTL_LEN_MAX, false); if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); return err; @@ -3897,7 +4325,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) WL_DBG(("Could not find the AP\n")); *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX); err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BSS_INFO, - wl->extra_buf, WL_EXTRA_BUF_MAX, FALSE); + wl->extra_buf, WL_EXTRA_BUF_MAX, false); if (unlikely(err)) { WL_ERR(("Could not get bss info %d\n", err)); goto update_bss_info_out; @@ -3932,7 +4360,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) * so we speficially query dtim information to dongle. */ err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_DTIMPRD, - &dtim_period, sizeof(dtim_period), FALSE); + &dtim_period, sizeof(dtim_period), false); if (unlikely(err)) { WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err)); goto update_bss_info_out; @@ -3966,7 +4394,7 @@ wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); WL_DBG(("Report roaming result\n")); - set_bit(WL_STATUS_CONNECTED, &wl->status); + wl_set_drv_status(wl, CONNECTED); return err; } @@ -3982,7 +4410,8 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, wl_get_assoc_ies(wl, ndev); memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN); wl_update_bss_info(wl, ndev); - if (test_and_clear_bit(WL_STATUS_CONNECTING, &wl->status)) { + if (wl_get_drv_status(wl, CONNECTING)) { + wl_clr_drv_status(wl, CONNECTING); cfg80211_connect_result(ndev, (u8 *)&wl->bssid, conn_info->req_ie, @@ -3994,6 +4423,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, WL_DBG(("Report connect result - connection %s\n", completed ? "succeeded" : "failed")); } else { + wl_clr_drv_status(wl, CONNECTING); cfg80211_roamed(ndev, #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) NULL, @@ -4004,7 +4434,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, GFP_KERNEL); WL_DBG(("Report roaming result\n")); } - set_bit(WL_STATUS_CONNECTED, &wl->status); + wl_set_drv_status(wl, CONNECTED); return err; } @@ -4038,20 +4468,21 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, u32 len = WL_SCAN_BUF_MAX; s32 err = 0; - WL_DBG(("Enter \n")); if (wl->iscan_on && wl->iscan_kickstart) return wl_wakeup_iscan(wl_to_iscan(wl)); - if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) { + if (unlikely(!wl_get_drv_status(wl, SCANNING))) { + wl_clr_drv_status(wl, SCANNING); WL_DBG(("Scan complete while device not scanning\n")); return -EINVAL; } + wl_clr_drv_status(wl, SCANNING); if (unlikely(!wl->scan_request)) { } rtnl_lock(); err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform, - sizeof(channel_inform), FALSE); + sizeof(channel_inform), false); if (unlikely(err)) { WL_ERR(("scan busy (%d)\n", err)); goto scan_done_out; @@ -4066,7 +4497,7 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, bss_list = wl->bss_list; memset(bss_list, 0, len); bss_list->buflen = htod32(len); - err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, FALSE); + err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false); if (unlikely(err)) { WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err)); err = -EINVAL; @@ -4138,7 +4569,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, struct wiphy *wiphy = wl_to_wiphy(wl); struct ether_addr da; struct ether_addr bssid; - bool isfree = FALSE; + bool isfree = false; s32 err = 0; s32 freq; wl_event_rx_frame_data_t *rxframe = @@ -4152,6 +4583,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, band = wiphy->bands[IEEE80211_BAND_2GHZ]; else band = wiphy->bands[IEEE80211_BAND_5GHZ]; + #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) freq = ieee80211_channel_to_frequency(channel); #else @@ -4160,7 +4592,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, if (event == WLC_E_ACTION_FRAME_RX) { wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", &da, sizeof(struct ether_addr), ioctlbuf, sizeof(ioctlbuf), bsscfgidx); - wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, FALSE); + wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid, &mgmt_frame, &mgmt_frame_len, (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1)); @@ -4169,7 +4601,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, __func__, mgmt_frame_len, channel, freq)); goto exit; } - isfree = TRUE; + isfree = true; } else { mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1); } @@ -4221,6 +4653,7 @@ static void wl_init_event_handler(struct wl_priv *wl) wl->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status; wl->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status; wl->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame; + wl->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame; wl->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame; wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete; wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete; @@ -4320,6 +4753,13 @@ static void wl_deinit_priv_mem(struct wl_priv *wl) wl->fw = NULL; kfree(wl->pmk_list); wl->pmk_list = NULL; + if (wl->ap_info) { + kfree(wl->ap_info->wpa_ie); + kfree(wl->ap_info->rsn_ie); + kfree(wl->ap_info->wps_ie); + kfree(wl->ap_info); + wl->ap_info = NULL; + } } static s32 wl_create_event_handler(struct wl_priv *wl) @@ -4352,7 +4792,7 @@ static void wl_term_iscan(struct wl_priv *wl) iscan->state = WL_ISCAN_STATE_IDLE; WL_INFO(("SIGTERM\n")); send_sig(SIGTERM, iscan->tsk, 1); - printk("kthread_stop\n"); + WL_DBG(("kthread_stop\n")); kthread_stop(iscan->tsk); iscan->tsk = NULL; } @@ -4363,10 +4803,12 @@ static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted) struct wl_priv *wl = iscan_to_wl(iscan); WL_DBG(("Enter \n")); - if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) { + if (unlikely(!wl_get_drv_status(wl, SCANNING))) { + wl_clr_drv_status(wl, SCANNING); WL_ERR(("Scan complete while device not scanning\n")); return; } + wl_clr_drv_status(wl, SCANNING); if (likely(wl->scan_request)) { cfg80211_scan_done(wl->scan_request, aborted); wl->scan_request = NULL; @@ -4556,11 +4998,13 @@ static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan) static void wl_notify_escan_complete(struct wl_priv *wl, bool aborted) { WL_DBG(("Enter \n")); - if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) { + if (unlikely(!wl_get_drv_status(wl, SCANNING))) { + wl_clr_drv_status(wl, SCANNING); WL_ERR(("Scan complete while device not scanning\n")); return; } - if (p2p_on(wl)) + wl_clr_drv_status(wl, SCANNING); + if (wl->p2p_supported && p2p_on(wl)) wl_clr_p2p_status(wl, SCANNING); if (likely(wl->scan_request)) { @@ -4584,7 +5028,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, WL_DBG((" enter event type : %d, status : %d \n", ntoh32(e->event_type), ntoh32(e->status))); if (!wl->escan_on && - !test_bit(WL_STATUS_SCANNING, &wl->status)) { + !wl_get_drv_status(wl, SCANNING)) { WL_ERR(("escan is not ready \n")); return err; } @@ -4733,7 +5177,6 @@ static s32 wl_init_priv(struct wl_priv *wl) wl_init_conf(wl->conf); wl_init_prof(wl->profile); wl_link_down(wl); - wl_cfgp2p_init_priv(wl); return err; } @@ -4757,10 +5200,10 @@ s32 wl_cfg80211_sysctl_export_devaddr(void *data) dhd_pub_t *dhd = (dhd_pub_t *)data; struct wl_priv *wl = WL_PRIV_GET(); - wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p.dev_addr, &wl->p2p.int_addr); + wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); - sprintf((char *)&wl_sysctl_macstring[0], MACSTR, MAC2STR(wl->p2p.dev_addr.octet)); - sprintf((char *)&wl_sysctl_macstring[1], MACSTR, MAC2STR(wl->p2p.int_addr.octet)); + sprintf((char *)&wl_sysctl_macstring[0], MACSTR, MAC2STR(wl->p2p->dev_addr.octet)); + sprintf((char *)&wl_sysctl_macstring[1], MACSTR, MAC2STR(wl->p2p->int_addr.octet)); return 0; } @@ -4776,18 +5219,24 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) return -ENODEV; } wl = WL_PRIV_GET(); - if (wl && !test_bit(WL_STATUS_READY, &wl->status)) { + if (wl && !wl_get_drv_status(wl, READY)) { if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) { - WL_INFO(("P2P is supported on Firmware \n")); wl->wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT)| BIT(NL80211_IFTYPE_P2P_GO)); + if ((err = wl_cfgp2p_init_priv(wl)) != 0) + goto fail; +#ifdef CONFIG_SYSCTL + wl_cfg80211_sysctl_export_devaddr(wl->pub); +#endif + wl->p2p_supported = true; } } else return -ENODEV; - set_bit(WL_STATUS_READY, &wl->status); + wl_set_drv_status(wl, READY); +fail: return err; } s32 wl_cfg80211_attach(struct net_device *ndev, void *data) @@ -4864,7 +5313,8 @@ void wl_cfg80211_detach(void) #endif rfkill_unregister(wl->rfkill); rfkill_destroy(wl->rfkill); - + if (wl->p2p_supported) + wl_cfgp2p_deinit_priv(wl); wl_deinit_priv(wl); wl_free_wdev(wl); wl_set_drvdata(wl_cfg80211_dev, NULL); @@ -5001,9 +5451,6 @@ static void wl_put_event(struct wl_event_q *e) kfree(e); } -/* TODO: this has been changed to wl_cfg80211_set_sdio_func in FALCON - * Keep is as-is in P2P Twig - */ void wl_cfg80211_set_sdio_func(void *func) { cfg80211_sdio_func = (struct sdio_func *)func; @@ -5035,16 +5482,22 @@ static s32 wl_dongle_mode(struct wl_priv *wl, struct net_device *ndev, s32 iftyp mode = WL_MODE_IBSS; break; case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_P2P_CLIENT: mode = WL_MODE_BSS; infra = 1; break; + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: + mode = WL_MODE_AP; + infra = 1; + break; default: err = -EINVAL; WL_ERR(("invalid type (%d)\n", iftype)); return err; } infra = htod32(infra); - err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), FALSE); + err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), false); if (unlikely(err)) { WL_ERR(("WLC_SET_INFRA error (%d)\n", err)); return err; @@ -5054,6 +5507,39 @@ static s32 wl_dongle_mode(struct wl_priv *wl, struct net_device *ndev, s32 iftyp return 0; } +static s32 wl_dongle_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add) +{ + s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; + + s8 eventmask[WL_EVENTING_MASK_LEN]; + s32 err = 0; + + /* Setup event_msgs */ + bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, + sizeof(iovbuf)); + err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false); + if (unlikely(err)) { + WL_ERR(("Get event_msgs error (%d)\n", err)); + goto dongle_eventmsg_out; + } + memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN); + if (add) { + setbit(eventmask, event); + } else { + clrbit(eventmask, event); + } + bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, + sizeof(iovbuf)); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false); + if (unlikely(err)) { + WL_ERR(("Set event_msgs error (%d)\n", err)); + goto dongle_eventmsg_out; + } + +dongle_eventmsg_out: + return err; + +} static s32 wl_dongle_eventmsg(struct net_device *ndev) { @@ -5065,7 +5551,7 @@ static s32 wl_dongle_eventmsg(struct net_device *ndev) /* Setup event_msgs */ bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE); + err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false); if (unlikely(err)) { WL_ERR(("Get event_msgs error (%d)\n", err)); goto dongle_eventmsg_out; @@ -5099,7 +5585,7 @@ static s32 wl_dongle_eventmsg(struct net_device *ndev) setbit(eventmask, WLC_E_ESCAN_RESULT); bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false); if (unlikely(err)) { WL_ERR(("Set event_msgs error (%d)\n", err)); goto dongle_eventmsg_out; @@ -5122,7 +5608,7 @@ static s32 wl_dongle_up(struct net_device *ndev, u32 up) { s32 err = 0; - err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), FALSE); + err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), false); if (unlikely(err)) { WL_ERR(("WLC_UP error (%d)\n", err)); } @@ -5134,7 +5620,7 @@ static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode) s32 err = 0; WL_TRACE(("In\n")); - err = wldev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode), FALSE); + err = wldev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode), false); if (unlikely(err)) { WL_ERR(("WLC_SET_PM error (%d)\n", err)); } @@ -5151,14 +5637,14 @@ wl_dongle_glom(struct net_device *ndev, u32 glom, u32 dongle_align) /* Match Host and Dongle rx alignment */ bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false); if (unlikely(err)) { WL_ERR(("txglomalign error (%d)\n", err)); goto dongle_glom_out; } /* disable glom option per default */ bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false); if (unlikely(err)) { WL_ERR(("txglom error (%d)\n", err)); goto dongle_glom_out; @@ -5178,7 +5664,7 @@ wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) if (roamvar) { bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false); if (unlikely(err)) { WL_ERR(("bcn_timeout error (%d)\n", err)); goto dongle_rom_out; @@ -5186,7 +5672,7 @@ wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) } /* Enable/Disable built-in roaming to allow supplicant to take care of roaming */ bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false); if (unlikely(err)) { WL_ERR(("roam_off error (%d)\n", err)); goto dongle_rom_out; @@ -5202,7 +5688,7 @@ wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, s32 err = 0; err = wldev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time, - sizeof(scan_assoc_time), FALSE); + sizeof(scan_assoc_time), false); if (err) { if (err == -EOPNOTSUPP) { WL_INFO(("Scan assoc time is not supported\n")); @@ -5212,7 +5698,7 @@ wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, goto dongle_scantime_out; } err = wldev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time, - sizeof(scan_unassoc_time), FALSE); + sizeof(scan_unassoc_time), false); if (err) { if (err == -EOPNOTSUPP) { WL_INFO(("Scan unassoc time is not supported\n")); @@ -5236,7 +5722,7 @@ wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol) /* Set ARP offload */ bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false); if (err) { if (err == -EOPNOTSUPP) WL_INFO(("arpoe is not supported\n")); @@ -5246,7 +5732,7 @@ wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol) goto dongle_offload_out; } bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false); if (err) { if (err == -EOPNOTSUPP) WL_INFO(("arp_ol is not supported\n")); @@ -5345,7 +5831,7 @@ static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode) memcpy((char *)pkt_filterp, &pkt_filter, WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN); - err = wldev_ioctl(ndev, WLC_SET_VAR, buf, buf_len, FALSE); + err = wldev_ioctl(ndev, WLC_SET_VAR, buf, buf_len, false); if (err) { if (err == -EOPNOTSUPP) { WL_INFO(("filter not supported\n")); @@ -5358,7 +5844,7 @@ static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode) /* set mode to allow pattern */ bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false); if (err) { if (err == -EOPNOTSUPP) { WL_INFO(("filter_mode not supported\n")); @@ -5445,7 +5931,7 @@ static s32 wl_update_wiphybands(struct wl_priv *wl) s32 err = 0; err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_PHYLIST, &phy_list, - sizeof(phy_list), FALSE); + sizeof(phy_list), false); if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); return err; @@ -5473,7 +5959,7 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl) return err; wl_invoke_iscan(wl); - set_bit(WL_STATUS_READY, &wl->status); + wl_set_drv_status(wl, READY); return err; } @@ -5483,25 +5969,32 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) WL_TRACE(("In\n")); /* Check if cfg80211 interface is already down */ - if (!test_bit(WL_STATUS_READY, &wl->status)) + if (!wl_get_drv_status(wl, READY)) return err; /* it is even not ready */ - set_bit(WL_STATUS_SCAN_ABORTING, &wl->status); + wl_set_drv_status(wl, SCAN_ABORTING); + wl_term_iscan(wl); if (wl->scan_request) { cfg80211_scan_done(wl->scan_request, true); - wl->scan_request = NULL; } - clear_bit(WL_STATUS_READY, &wl->status); - clear_bit(WL_STATUS_SCANNING, &wl->status); - clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status); - clear_bit(WL_STATUS_CONNECTED, &wl->status); - + wl_clr_drv_status(wl, READY); + wl_clr_drv_status(wl, SCANNING); + wl_clr_drv_status(wl, SCAN_ABORTING); + wl_clr_drv_status(wl, CONNECTED); + if (wl_get_drv_status(wl, AP_CREATED)) { + wl_clr_drv_status(wl, AP_CREATED); + wl_clr_drv_status(wl, AP_CREATING); + wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype = + NL80211_IFTYPE_STATION; + } wl->dongle_up = false; wl_flush_eq(wl); wl_link_down(wl); - wl_cfgp2p_down(wl); + if (wl->p2p_supported) + wl_cfgp2p_down(wl); + wl_debugfs_remove_netdev(wl); return err; @@ -5833,6 +6326,47 @@ s8 *wl_cfg80211_get_nvramname(void) return wl->fw->nvram_name; } +s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr) +{ + struct wl_priv *wl; + dhd_pub_t *dhd_pub; + struct ether_addr p2pif_addr; + + wl = WL_PRIV_GET(); + dhd_pub = (dhd_pub_t *)wl->pub; + wl_cfgp2p_generate_bss_mac(&dhd_pub->mac, p2pdev_addr, &p2pif_addr); + + return 0; +} + +static __used void wl_dongle_poweron(struct wl_priv *wl) +{ + + WL_DBG(("Enter \n")); + dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON); + +#if defined(BCMLXSDMMC) + sdioh_start(NULL, 0); +#endif +#if defined(BCMLXSDMMC) + sdioh_start(NULL, 1); +#endif + wl_cfg80211_resume(wl_to_wiphy(wl)); +} + +static __used void wl_dongle_poweroff(struct wl_priv *wl) +{ + + + WL_DBG(("Enter \n")); + wl_cfg80211_suspend(wl_to_wiphy(wl)); + +#if defined(BCMLXSDMMC) + sdioh_stop(NULL); +#endif + /* clean up dtim_skip setting */ + dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); +} static int wl_debugfs_add_netdev_params(struct wl_priv *wl) { char buf[10+IFNAMSIZ]; @@ -5872,6 +6406,13 @@ static const struct rfkill_ops wl_rfkill_ops = { static int wl_rfkill_set(void *data, bool blocked) { + struct wl_priv *wl = (struct wl_priv *)data; + + WL_DBG(("Enter \n")); + WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked")); + + wl->rf_blocked = blocked; + return 0; } |