From: Hante Meuleman Date: Fri, 8 Feb 2013 14:53:50 +0000 (+0100) Subject: brcmfmac: Use real cookie value for p2p remain on channel. X-Git-Tag: firefly_0821_release~3680^2~1092^2~31^2^2~36 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=f2058dde8c2be70cc22dbd8f718ab6c33cf6ea11;p=firefly-linux-kernel-4.4.55.git brcmfmac: Use real cookie value for p2p remain on channel. In some rare situations the wpa_supplicant can lock up on a remain on channel command. Use actual cookies for the remain on channel related commands and allow for additional remain on channel while still having one set. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 0c42910a6b36..aac054cc0069 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c @@ -912,6 +912,47 @@ int brcmf_p2p_scan_prep(struct wiphy *wiphy, } +/** + * brcmf_p2p_discover_listen() - set firmware to discover listen state. + * + * @p2p: p2p device. + * @freq: center frequency for discover listen. + * #@duration: time in ms to stay on channel. + * + */ +static s32 +brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, + struct ieee80211_channel *channel, u32 duration) +{ + struct brcmf_cfg80211_vif *vif; + s32 err = 0; + u16 chanspec; + + vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; + if (!vif) { + brcmf_err("Discovery is not set, so we have nothing to do\n"); + err = -EPERM; + goto exit; + } + + if (test_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status)) { + brcmf_err("Previous LISTEN is not completed yet\n"); + /* WAR: prevent cookie mismatch in wpa_supplicant return OK */ + goto exit; + } + + chanspec = channel_to_chanspec(channel); + err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN, + chanspec, (u16)duration); + if (!err) { + set_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status); + p2p->remain_on_channel_cookie++; + } +exit: + return err; +} + + /** * brcmf_p2p_remain_on_channel() - put device on channel and stay there. * @@ -926,30 +967,21 @@ int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_p2p_info *p2p = &cfg->p2p; - struct brcmf_cfg80211_vif *vif; s32 err; - u16 chanspec; brcmf_dbg(TRACE, "Enter, channel: %d, duration ms (%d)\n", ieee80211_frequency_to_channel(channel->center_freq), duration); - *cookie = 0; err = brcmf_p2p_enable_discovery(p2p); if (err) goto exit; - - chanspec = channel_to_chanspec(channel); - vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; - err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN, - chanspec, (u16)duration); + err = brcmf_p2p_discover_listen(p2p, channel, duration); if (err) goto exit; - memcpy(&p2p->remain_on_channel, channel, - sizeof(p2p->remain_on_channel)); - - set_bit(BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL, &p2p->status); + memcpy(&p2p->remain_on_channel, channel, sizeof(*channel)); + *cookie = p2p->remain_on_channel_cookie; exit: cfg80211_ready_on_channel(wdev, *cookie, channel, duration, GFP_KERNEL); @@ -973,9 +1005,10 @@ int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp, struct brcmf_p2p_info *p2p = &cfg->p2p; brcmf_dbg(TRACE, "Enter\n"); - if (test_and_clear_bit(BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL, + if (test_and_clear_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status)) - cfg80211_remain_on_channel_expired(&ifp->vif->wdev, 0, + cfg80211_remain_on_channel_expired(&ifp->vif->wdev, + p2p->remain_on_channel_cookie, &p2p->remain_on_channel, GFP_KERNEL); return 0; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h index 0610dcff43fc..0594018a7f9e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h @@ -63,7 +63,7 @@ struct p2p_bss { * @BRCMF_P2P_STATUS_ACTION_TX_COMPLETED: action frame tx completed. * @BRCMF_P2P_STATUS_ACTION_TX_NOACK: action frame tx not acked. * @BRCMF_P2P_STATUS_GO_NEG_PHASE: P2P GO negotiation ongoing. - * @BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL: P2P listen, remaining on channel. + * @BRCMF_P2P_STATUS_DISCOVER_LISTEN: P2P listen, remaining on channel. */ enum brcmf_p2p_status { BRCMF_P2P_STATUS_IF_ADD = 0, @@ -74,7 +74,7 @@ enum brcmf_p2p_status { BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, BRCMF_P2P_STATUS_ACTION_TX_NOACK, BRCMF_P2P_STATUS_GO_NEG_PHASE, - BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL + BRCMF_P2P_STATUS_DISCOVER_LISTEN }; /** @@ -89,6 +89,7 @@ enum brcmf_p2p_status { * @ssid: ssid for P2P GO. * @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state. * @remain_on_channel: contains copy of struct used by cfg80211. + * @remain_on_channel_cookie: cookie counter for remain on channel cmd * @next_af_subtype: expected action frame subtype. * @send_af_done: indication that action frame tx is complete. */ @@ -102,6 +103,7 @@ struct brcmf_p2p_info { struct brcmf_ssid ssid; u8 listen_channel; struct ieee80211_channel remain_on_channel; + u32 remain_on_channel_cookie; u8 next_af_subtype; struct completion send_af_done; };