mirror of https://gitee.com/openkylin/linux.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 <arend@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Hante Meuleman <meuleman@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
18e2f61db3
commit
f2058dde8c
|
@ -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.
|
* 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_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||||
struct brcmf_p2p_info *p2p = &cfg->p2p;
|
struct brcmf_p2p_info *p2p = &cfg->p2p;
|
||||||
struct brcmf_cfg80211_vif *vif;
|
|
||||||
s32 err;
|
s32 err;
|
||||||
u16 chanspec;
|
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter, channel: %d, duration ms (%d)\n",
|
brcmf_dbg(TRACE, "Enter, channel: %d, duration ms (%d)\n",
|
||||||
ieee80211_frequency_to_channel(channel->center_freq),
|
ieee80211_frequency_to_channel(channel->center_freq),
|
||||||
duration);
|
duration);
|
||||||
|
|
||||||
*cookie = 0;
|
|
||||||
err = brcmf_p2p_enable_discovery(p2p);
|
err = brcmf_p2p_enable_discovery(p2p);
|
||||||
if (err)
|
if (err)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
err = brcmf_p2p_discover_listen(p2p, channel, duration);
|
||||||
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);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
memcpy(&p2p->remain_on_channel, channel,
|
memcpy(&p2p->remain_on_channel, channel, sizeof(*channel));
|
||||||
sizeof(p2p->remain_on_channel));
|
*cookie = p2p->remain_on_channel_cookie;
|
||||||
|
|
||||||
set_bit(BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL, &p2p->status);
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
cfg80211_ready_on_channel(wdev, *cookie, channel, duration, GFP_KERNEL);
|
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;
|
struct brcmf_p2p_info *p2p = &cfg->p2p;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
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))
|
&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,
|
&p2p->remain_on_channel,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -63,7 +63,7 @@ struct p2p_bss {
|
||||||
* @BRCMF_P2P_STATUS_ACTION_TX_COMPLETED: action frame tx completed.
|
* @BRCMF_P2P_STATUS_ACTION_TX_COMPLETED: action frame tx completed.
|
||||||
* @BRCMF_P2P_STATUS_ACTION_TX_NOACK: action frame tx not acked.
|
* @BRCMF_P2P_STATUS_ACTION_TX_NOACK: action frame tx not acked.
|
||||||
* @BRCMF_P2P_STATUS_GO_NEG_PHASE: P2P GO negotiation ongoing.
|
* @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 {
|
enum brcmf_p2p_status {
|
||||||
BRCMF_P2P_STATUS_IF_ADD = 0,
|
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_COMPLETED,
|
||||||
BRCMF_P2P_STATUS_ACTION_TX_NOACK,
|
BRCMF_P2P_STATUS_ACTION_TX_NOACK,
|
||||||
BRCMF_P2P_STATUS_GO_NEG_PHASE,
|
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.
|
* @ssid: ssid for P2P GO.
|
||||||
* @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state.
|
* @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state.
|
||||||
* @remain_on_channel: contains copy of struct used by cfg80211.
|
* @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.
|
* @next_af_subtype: expected action frame subtype.
|
||||||
* @send_af_done: indication that action frame tx is complete.
|
* @send_af_done: indication that action frame tx is complete.
|
||||||
*/
|
*/
|
||||||
|
@ -102,6 +103,7 @@ struct brcmf_p2p_info {
|
||||||
struct brcmf_ssid ssid;
|
struct brcmf_ssid ssid;
|
||||||
u8 listen_channel;
|
u8 listen_channel;
|
||||||
struct ieee80211_channel remain_on_channel;
|
struct ieee80211_channel remain_on_channel;
|
||||||
|
u32 remain_on_channel_cookie;
|
||||||
u8 next_af_subtype;
|
u8 next_af_subtype;
|
||||||
struct completion send_af_done;
|
struct completion send_af_done;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue