diff options
author | Dmitry Shmidt <dimitrysh@google.com> | 2012-06-13 11:22:56 -0700 |
---|---|---|
committer | Dmitry Shmidt <dimitrysh@google.com> | 2012-06-13 11:29:39 -0700 |
commit | cb786ee756155411b65212d4ee76050a382ac674 (patch) | |
tree | a5f7922e330ad1df2821e1c8317ea55cb8f62144 /drivers/net | |
parent | 9d8a0e5b42c03e2dc8dffc7eebff45ec6665fdf1 (diff) | |
download | kernel_samsung_crespo-cb786ee756155411b65212d4ee76050a382ac674.zip kernel_samsung_crespo-cb786ee756155411b65212d4ee76050a382ac674.tar.gz kernel_samsung_crespo-cb786ee756155411b65212d4ee76050a382ac674.tar.bz2 |
net: wireless: bcmdhd: Combined P2P fixes
- Fix p2p scan
- Fix p2p processing for channels 12 and 13
- Fix service discovery
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/bcmdhd/wl_cfg80211.c | 103 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/wl_cfgp2p.c | 6 |
2 files changed, 77 insertions, 32 deletions
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index bee7d55..cccc4d1 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -84,17 +84,15 @@ u32 wl_dbg_level = WL_DBG_ERR; * All the chnages in world regulatory domain are to be done here. */ static const struct ieee80211_regdomain brcm_regdom = { - .n_reg_rules = 5, + .n_reg_rules = 4, .alpha2 = "99", .reg_rules = { /* IEEE 802.11b/g, channels 1..11 */ - REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), + REG_RULE(2412-10, 2472+10, 40, 6, 20, 0), /* IEEE 802.11b/g, channels 12..13. No HT40 * channel fits here. */ - REG_RULE(2467-10, 2472+10, 20, 6, 20, - NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS), + /* If any */ /* * IEEE 802.11 channel 14 - is for JP only, * we need cfg80211 to allow it (reg_flags = 0); so that @@ -2343,8 +2341,9 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, */ WL_DBG(("ASSOC2 p2p index : %d sme->ie_len %d\n", wl_cfgp2p_find_idx(wl, dev), sme->ie_len)); - wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), - VNDR_IE_PRBREQ_FLAG, sme->ie, sme->ie_len); + wl_cfgp2p_set_management_ie(wl, dev, + wl_cfgp2p_find_idx(wl, dev), VNDR_IE_PRBREQ_FLAG, + sme->ie, sme->ie_len); wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len); } @@ -3455,8 +3454,8 @@ wl_cfg80211_send_at_common_channel(struct wl_priv *wl, if (wl->afx_hdl->peer_chan != WL_INVALID) wl_cfg80211_send_pending_tx_act_frm(wl); else { - WL_ERR(("Couldn't find the peer after %d retries\n", - wl->afx_hdl->retry)); + WL_ERR(("Couldn't find the peer " MACSTR " after %d retries\n", + MAC2STR(wl->afx_hdl->pending_tx_dst_addr.octet), wl->afx_hdl->retry)); } wl->afx_hdl->dev = NULL; wl->afx_hdl->bssidx = WL_INVALID; @@ -3674,7 +3673,8 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, WL_DBG(("Service Discovery action_frame->len: %d chan %d category %d action %d\n", action_frame->len, af_params->channel, sd_act_frm->category, sd_act_frm->action)); - + af_params->dwell_time = WL_MED_DWELL_TIME; + retry_cnt = WL_ACT_FRAME_RETRY; } wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len); /* @@ -3691,6 +3691,18 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, /* channel offload for action request frame */ ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params); + /* We need to retry Service discovery frames as they don't get retried immediately by supplicant*/ + if ((!ack) && (IS_GAS_REQ(sd_act_frm, action_frame->len))) { + for (retry = 1; retry < retry_cnt; retry++) { + WL_DBG(("Service Discovery action_frame retry %d len: %d chan %d category %d action %d\n", + retry, action_frame->len, af_params->channel, + sd_act_frm->category, sd_act_frm->action)); + ack = (wl_cfgp2p_tx_action_frame(wl, dev, + af_params, bssidx)) ? false : true; + if (ack) + break; + } + } } else { ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true; if (!ack) { @@ -6315,7 +6327,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, wl_scan_results_t *list; u32 bi_length; u32 i; - + u8 *p2p_dev_addr = NULL; WL_DBG((" enter event type : %d, status : %d \n", ntoh32(e->event_type), ntoh32(e->status))); /* P2P SCAN is coming from primary interface */ @@ -6363,10 +6375,12 @@ static s32 wl_escan_handler(struct wl_priv *wl, } if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) { - if (!memcmp(bi->BSSID.octet, + p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length); + if (p2p_dev_addr && !memcmp(p2p_dev_addr, wl->afx_hdl->pending_tx_dst_addr.octet, ETHER_ADDR_LEN)) { s32 channel = CHSPEC_CHANNEL(dtohchanspec(bi->chanspec)); - WL_DBG(("ACTION FRAME SCAN : Peer found, channel : %d\n", channel)); + WL_DBG(("ACTION FRAME SCAN : Peer " MACSTR " found, channel : %d\n", + MAC2STR(wl->afx_hdl->pending_tx_dst_addr.octet), channel)); wl_clr_p2p_status(wl, SCANNING); wl->afx_hdl->peer_chan = channel; complete(&wl->act_frm_scan); @@ -7155,29 +7169,33 @@ s32 wl_update_wiphybands(struct wl_priv *wl) } } + err = wl_construct_reginfo(wl, bw_cap); + if (err) { + WL_ERR(("wl_construct_reginfo() fails err=%d\n", err)); + return err; + } for (i = 1; i <= nband && i < sizeof(bandlist)/sizeof(u32); i++) { index = -1; - if (bandlist[i] == WLC_BAND_5G) { + if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) { wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; - index = IEEE80211_BAND_5GHZ; - } else if (bandlist[i] == WLC_BAND_2G) { + index = IEEE80211_BAND_5GHZ; + if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G) + wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + } else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) { wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; - index = IEEE80211_BAND_2GHZ; + index = IEEE80211_BAND_2GHZ; + if (bandlist[i] == WLC_BAND_2G && bw_cap == WLC_N_BW_40ALL) + wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; } if ((index >= 0) && nmode) { - wiphy->bands[index]->ht_cap.cap = - IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40 | - IEEE80211_HT_CAP_MAX_AMSDU; + wiphy->bands[index]->ht_cap.cap |= + IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40; wiphy->bands[index]->ht_cap.ht_supported = TRUE; wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; } - - if ((index >= 0) && bw_cap) { - wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; - } } wiphy_apply_custom_regulatory(wiphy, &brcm_regdom); @@ -7559,17 +7577,44 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, { struct wl_priv *wl; struct net_device *ndev = NULL; + struct ether_addr primary_mac; s32 ret = 0; s32 bssidx = 0; s32 pktflag = 0; wl = wlcfg_drv_priv; - if (wl->p2p && wl->p2p->vif_created) { - ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); - bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION); - } else if (wl_get_drv_status(wl, AP_CREATING, net) || + + if (wl_get_drv_status(wl, AP_CREATING, net) || wl_get_drv_status(wl, AP_CREATED, net)) { ndev = net; bssidx = 0; + } else if (wl->p2p) { + if (net == wl->p2p_net) { + net = wl_to_prmry_ndev(wl); + } + + if (!wl->p2p->on) { + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, + &wl->p2p->int_addr); + /* In case of p2p_listen command, supplicant send remain_on_channel + * without turning on P2P + */ + p2p_on(wl) = true; + ret = wl_cfgp2p_enable_discovery(wl, ndev, NULL, 0); + + if (unlikely(ret)) { + goto exit; + } + } + if (net != wl_to_prmry_ndev(wl)) { + if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) { + ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); + bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION); + } + } else { + ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY); + bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); + } } if (ndev != NULL) { switch (type) { @@ -7586,7 +7631,7 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, if (pktflag) ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len); } - +exit: return ret; } diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index a902666..bdcfa95 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -1229,6 +1229,7 @@ wl_cfgp2p_listen_expired(unsigned long data) struct wl_priv *wl = (struct wl_priv *) data; CFGP2P_DBG((" Enter\n")); + memset(&msg, 0, sizeof(wl_event_msg_t)); msg.event_type = hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE); wl_cfg80211_event(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), &msg, NULL); } @@ -1401,13 +1402,12 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); if (ret < 0) { - CFGP2P_ERR((" sending action frame is failed\n")); goto exit; } timeout = wait_event_interruptible_timeout(wl->netif_change_event, - (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || wl_get_p2p_status(wl, ACTION_TX_NOACK)), - msecs_to_jiffies(MAX_WAIT_TIME)); + (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || wl_get_p2p_status(wl, ACTION_TX_NOACK)), + msecs_to_jiffies(MAX_WAIT_TIME)); if (timeout > 0 && wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) { CFGP2P_INFO(("tx action frame operation is completed\n")); |