aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac
diff options
context:
space:
mode:
authorHante Meuleman <meuleman@broadcom.com>2013-02-08 09:53:50 -0500
committerJohn W. Linville <linville@tuxdriver.com>2013-02-08 14:51:40 -0500
commitf2058dde8c2be70cc22dbd8f718ab6c33cf6ea11 (patch)
treee448dcde83aee495c94acde27889d6834946a2ee /drivers/net/wireless/brcm80211/brcmfmac
parent18e2f61db3b708e0a22ccc403cb6ab2203d6faab (diff)
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>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/p2p.c61
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/p2p.h6
2 files changed, 51 insertions, 16 deletions
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
@@ -913,6 +913,47 @@ int brcmf_p2p_scan_prep(struct wiphy *wiphy,
913 913
914 914
915/** 915/**
916 * brcmf_p2p_discover_listen() - set firmware to discover listen state.
917 *
918 * @p2p: p2p device.
919 * @freq: center frequency for discover listen.
920 * #@duration: time in ms to stay on channel.
921 *
922 */
923static s32
924brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p,
925 struct ieee80211_channel *channel, u32 duration)
926{
927 struct brcmf_cfg80211_vif *vif;
928 s32 err = 0;
929 u16 chanspec;
930
931 vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
932 if (!vif) {
933 brcmf_err("Discovery is not set, so we have nothing to do\n");
934 err = -EPERM;
935 goto exit;
936 }
937
938 if (test_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status)) {
939 brcmf_err("Previous LISTEN is not completed yet\n");
940 /* WAR: prevent cookie mismatch in wpa_supplicant return OK */
941 goto exit;
942 }
943
944 chanspec = channel_to_chanspec(channel);
945 err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN,
946 chanspec, (u16)duration);
947 if (!err) {
948 set_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status);
949 p2p->remain_on_channel_cookie++;
950 }
951exit:
952 return err;
953}
954
955
956/**
916 * brcmf_p2p_remain_on_channel() - put device on channel and stay there. 957 * brcmf_p2p_remain_on_channel() - put device on channel and stay there.
917 * 958 *
918 * @wiphy: wiphy device. 959 * @wiphy: wiphy device.
@@ -926,30 +967,21 @@ int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
926{ 967{
927 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); 968 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
928 struct brcmf_p2p_info *p2p = &cfg->p2p; 969 struct brcmf_p2p_info *p2p = &cfg->p2p;
929 struct brcmf_cfg80211_vif *vif;
930 s32 err; 970 s32 err;
931 u16 chanspec;
932 971
933 brcmf_dbg(TRACE, "Enter, channel: %d, duration ms (%d)\n", 972 brcmf_dbg(TRACE, "Enter, channel: %d, duration ms (%d)\n",
934 ieee80211_frequency_to_channel(channel->center_freq), 973 ieee80211_frequency_to_channel(channel->center_freq),
935 duration); 974 duration);
936 975
937 *cookie = 0;
938 err = brcmf_p2p_enable_discovery(p2p); 976 err = brcmf_p2p_enable_discovery(p2p);
939 if (err) 977 if (err)
940 goto exit; 978 goto exit;
941 979 err = brcmf_p2p_discover_listen(p2p, channel, duration);
942 chanspec = channel_to_chanspec(channel);
943 vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
944 err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN,
945 chanspec, (u16)duration);
946 if (err) 980 if (err)
947 goto exit; 981 goto exit;
948 982
949 memcpy(&p2p->remain_on_channel, channel, 983 memcpy(&p2p->remain_on_channel, channel, sizeof(*channel));
950 sizeof(p2p->remain_on_channel)); 984 *cookie = p2p->remain_on_channel_cookie;
951
952 set_bit(BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL, &p2p->status);
953 985
954exit: 986exit:
955 cfg80211_ready_on_channel(wdev, *cookie, channel, duration, GFP_KERNEL); 987 cfg80211_ready_on_channel(wdev, *cookie, channel, duration, GFP_KERNEL);
@@ -973,9 +1005,10 @@ int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp,
973 struct brcmf_p2p_info *p2p = &cfg->p2p; 1005 struct brcmf_p2p_info *p2p = &cfg->p2p;
974 1006
975 brcmf_dbg(TRACE, "Enter\n"); 1007 brcmf_dbg(TRACE, "Enter\n");
976 if (test_and_clear_bit(BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL, 1008 if (test_and_clear_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN,
977 &p2p->status)) 1009 &p2p->status))
978 cfg80211_remain_on_channel_expired(&ifp->vif->wdev, 0, 1010 cfg80211_remain_on_channel_expired(&ifp->vif->wdev,
1011 p2p->remain_on_channel_cookie,
979 &p2p->remain_on_channel, 1012 &p2p->remain_on_channel,
980 GFP_KERNEL); 1013 GFP_KERNEL);
981 return 0; 1014 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 {
63 * @BRCMF_P2P_STATUS_ACTION_TX_COMPLETED: action frame tx completed. 63 * @BRCMF_P2P_STATUS_ACTION_TX_COMPLETED: action frame tx completed.
64 * @BRCMF_P2P_STATUS_ACTION_TX_NOACK: action frame tx not acked. 64 * @BRCMF_P2P_STATUS_ACTION_TX_NOACK: action frame tx not acked.
65 * @BRCMF_P2P_STATUS_GO_NEG_PHASE: P2P GO negotiation ongoing. 65 * @BRCMF_P2P_STATUS_GO_NEG_PHASE: P2P GO negotiation ongoing.
66 * @BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL: P2P listen, remaining on channel. 66 * @BRCMF_P2P_STATUS_DISCOVER_LISTEN: P2P listen, remaining on channel.
67 */ 67 */
68enum brcmf_p2p_status { 68enum brcmf_p2p_status {
69 BRCMF_P2P_STATUS_IF_ADD = 0, 69 BRCMF_P2P_STATUS_IF_ADD = 0,
@@ -74,7 +74,7 @@ enum brcmf_p2p_status {
74 BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, 74 BRCMF_P2P_STATUS_ACTION_TX_COMPLETED,
75 BRCMF_P2P_STATUS_ACTION_TX_NOACK, 75 BRCMF_P2P_STATUS_ACTION_TX_NOACK,
76 BRCMF_P2P_STATUS_GO_NEG_PHASE, 76 BRCMF_P2P_STATUS_GO_NEG_PHASE,
77 BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL 77 BRCMF_P2P_STATUS_DISCOVER_LISTEN
78}; 78};
79 79
80/** 80/**
@@ -89,6 +89,7 @@ enum brcmf_p2p_status {
89 * @ssid: ssid for P2P GO. 89 * @ssid: ssid for P2P GO.
90 * @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state. 90 * @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state.
91 * @remain_on_channel: contains copy of struct used by cfg80211. 91 * @remain_on_channel: contains copy of struct used by cfg80211.
92 * @remain_on_channel_cookie: cookie counter for remain on channel cmd
92 * @next_af_subtype: expected action frame subtype. 93 * @next_af_subtype: expected action frame subtype.
93 * @send_af_done: indication that action frame tx is complete. 94 * @send_af_done: indication that action frame tx is complete.
94 */ 95 */
@@ -102,6 +103,7 @@ struct brcmf_p2p_info {
102 struct brcmf_ssid ssid; 103 struct brcmf_ssid ssid;
103 u8 listen_channel; 104 u8 listen_channel;
104 struct ieee80211_channel remain_on_channel; 105 struct ieee80211_channel remain_on_channel;
106 u32 remain_on_channel_cookie;
105 u8 next_af_subtype; 107 u8 next_af_subtype;
106 struct completion send_af_done; 108 struct completion send_af_done;
107}; 109};