diff options
author | Hante Meuleman <meuleman@broadcom.com> | 2013-02-08 09:53:50 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-02-08 14:51:40 -0500 |
commit | f2058dde8c2be70cc22dbd8f718ab6c33cf6ea11 (patch) | |
tree | e448dcde83aee495c94acde27889d6834946a2ee /drivers/net/wireless/brcm80211/brcmfmac | |
parent | 18e2f61db3b708e0a22ccc403cb6ab2203d6faab (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.c | 61 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/p2p.h | 6 |
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 | */ | ||
923 | static s32 | ||
924 | brcmf_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 | } | ||
951 | exit: | ||
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 | ||
954 | exit: | 986 | exit: |
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 | */ |
68 | enum brcmf_p2p_status { | 68 | enum 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 | }; |