From 23cbfabf0b519478262989d70ea95cca13e462c0 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 4 Oct 2011 13:42:24 -0700 Subject: [PATCH] net: wireless: bcmdhd: Improve join functionality Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 11 ++++- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 68 +++++++++++++++++++++++++++++- drivers/net/wireless/bcmdhd/wl_cfgp2p.c | 2 +- drivers/net/wireless/bcmdhd/wldev_common.c | 5 ++- 4 files changed, 79 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 09e3d8176809..397492ce6ddf 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -22,7 +22,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: dhd_linux.c 285933 2011-09-23 21:45:31Z $ + * $Id: dhd_linux.c 287541 2011-10-03 23:48:17Z $ */ #include @@ -1404,9 +1404,16 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) struct dot11_llc_snap_header *lsh; ifp = dhd->iflist[ifidx]; + if (ifp == NULL) { + DHD_ERROR(("%s: ifp is NULL. drop packet\n", + __FUNCTION__)); + PKTFREE(dhdp->osh, pktbuf, TRUE); + continue; + } /* Dropping packets before registering net device to avoid kernel panic */ - if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) { + if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED || + !dhd->pub.up) { DHD_ERROR(("%s: net device is NOT registered yet. drop packet\n", __FUNCTION__)); PKTFREE(dhdp->osh, pktbuf, TRUE); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index e89114549958..1eaf512b6f2e 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -2175,6 +2175,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, { struct wl_priv *wl = wiphy_priv(wiphy); struct ieee80211_channel *chan = sme->channel; + wl_extjoin_params_t *ext_join_params; struct wl_join_params join_params; size_t join_params_size; s32 err = 0; @@ -2184,6 +2185,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, u8* wpaie = 0; u32 wpaie_len = 0; u32 wpsie_len = 0; + u32 chan_cnt = 0; u8 wpsie[IE_MAX_LEN]; WL_DBG(("In\n")); CHECK_SYS_UP(wl); @@ -2264,6 +2266,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, } if (chan) { wl->channel = ieee80211_frequency_to_channel(chan->center_freq); + chan_cnt = 1; WL_DBG(("channel (%d), center_req (%d)\n", wl->channel, chan->center_freq)); } else @@ -2304,6 +2307,67 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, * Join with specific BSSID and cached SSID * If SSID is zero join based on BSSID only */ + join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE + + chan_cnt * sizeof(chanspec_t); + ext_join_params = (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL); + if (ext_join_params == NULL) { + err = -ENOMEM; + wl_clr_drv_status(wl, CONNECTING); + goto exit; + } + ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len); + memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len); + ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len); + /* Set up join scan parameters */ + ext_join_params->scan.scan_type = DOT11_SCANTYPE_ACTIVE; + ext_join_params->scan.nprobes = 2; + /* increate dwell time to receive probe response + * from target AP at a noisy air + */ + if (chan_cnt) + ext_join_params->scan.active_time = 150; + else + ext_join_params->scan.active_time = -1; + ext_join_params->scan.home_time = -1; + if (sme->bssid) + memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN); + else + memcpy(&ext_join_params->assoc.bssid, ðer_bcast, ETH_ALEN); + ext_join_params->assoc.chanspec_num = chan_cnt; + if (chan_cnt) { + u16 channel, band, bw, ctl_sb; + chanspec_t chspec; + channel = wl->channel; + band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G + : WL_CHANSPEC_BAND_5G; + bw = WL_CHANSPEC_BW_20; + ctl_sb = WL_CHANSPEC_CTL_SB_NONE; + chspec = (channel | band | bw | ctl_sb); + ext_join_params->assoc.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK; + ext_join_params->assoc.chanspec_list[0] |= chspec; + ext_join_params->assoc.chanspec_list[0] = + htodchanspec(ext_join_params->assoc.chanspec_list[0]); + } + ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num); + if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) { + WL_INFO(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID, + ext_join_params->ssid.SSID_len)); + } + wl_set_drv_status(wl, CONNECTING); + err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size, ioctlbuf, + sizeof(ioctlbuf), wl_cfgp2p_find_idx(wl, dev)); + kfree(ext_join_params); + if (err) { + wl_clr_drv_status(wl, CONNECTING); + if (err == BCME_UNSUPPORTED) { + WL_DBG(("join iovar is not supported\n")); + goto set_ssid; + } else + WL_ERR(("error (%d)\n", err)); + } else + goto exit; + +set_ssid: memset(&join_params, 0, sizeof(join_params)); join_params_size = sizeof(join_params.ssid); @@ -2325,11 +2389,11 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, } wl_set_drv_status(wl, CONNECTING); err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true); - if (unlikely(err)) { + if (err) { WL_ERR(("error (%d)\n", err)); wl_clr_drv_status(wl, CONNECTING); - return err; } +exit: return err; } diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index 9a148cd45b2d..0251d822bc90 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -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,v 1.1.4.1.2.14 2011-02-09 01:40:07 Exp $ + * $Id: wl_cfgp2p.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 $ * */ #include diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c index 92c419863764..bb3eaea90d0f 100644 --- a/drivers/net/wireless/bcmdhd/wldev_common.c +++ b/drivers/net/wireless/bcmdhd/wldev_common.c @@ -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: wldev_common.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 Exp $ + * $Id: wldev_common.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 $ */ #include @@ -318,7 +318,8 @@ int wldev_set_country( bzero(&scbval, sizeof(scb_val_t)); error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), 1); if (error < 0) { - DHD_ERROR(("%s: set country failed due to Disassoc error\n", __FUNCTION__)); + DHD_ERROR(("%s: set country failed due to Disassoc error %d\n", + __FUNCTION__, error)); return error; } } -- 2.11.0