]>
git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/net/wireless/ath/wil6210/p2p.c
2 * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #define P2P_WILDCARD_SSID "DIRECT-"
22 #define P2P_DMG_SOCIAL_CHANNEL 2
23 #define P2P_SEARCH_DURATION_MS 500
24 #define P2P_DEFAULT_BI 100
26 static int wil_p2p_start_listen(struct wil6210_vif
*vif
)
28 struct wil6210_priv
*wil
= vif_to_wil(vif
);
29 struct wil_p2p_info
*p2p
= &vif
->p2p
;
30 u8 channel
= p2p
->listen_chan
.hw_value
;
33 lockdep_assert_held(&wil
->mutex
);
35 rc
= wmi_p2p_cfg(vif
, channel
, P2P_DEFAULT_BI
);
37 wil_err(wil
, "wmi_p2p_cfg failed\n");
41 rc
= wmi_set_ssid(vif
, strlen(P2P_WILDCARD_SSID
), P2P_WILDCARD_SSID
);
43 wil_err(wil
, "wmi_set_ssid failed\n");
47 rc
= wmi_start_listen(vif
);
49 wil_err(wil
, "wmi_start_listen failed\n");
53 INIT_WORK(&p2p
->discovery_expired_work
, wil_p2p_listen_expired
);
54 mod_timer(&p2p
->discovery_timer
,
55 jiffies
+ msecs_to_jiffies(p2p
->listen_duration
));
58 wmi_stop_discovery(vif
);
64 bool wil_p2p_is_social_scan(struct cfg80211_scan_request
*request
)
66 return (request
->n_channels
== 1) &&
67 (request
->channels
[0]->hw_value
== P2P_DMG_SOCIAL_CHANNEL
);
70 int wil_p2p_search(struct wil6210_vif
*vif
,
71 struct cfg80211_scan_request
*request
)
73 struct wil6210_priv
*wil
= vif_to_wil(vif
);
75 struct wil_p2p_info
*p2p
= &vif
->p2p
;
77 wil_dbg_misc(wil
, "p2p_search: channel %d\n", P2P_DMG_SOCIAL_CHANNEL
);
79 lockdep_assert_held(&wil
->mutex
);
81 if (p2p
->discovery_started
) {
82 wil_err(wil
, "search failed. discovery already ongoing\n");
87 rc
= wmi_p2p_cfg(vif
, P2P_DMG_SOCIAL_CHANNEL
, P2P_DEFAULT_BI
);
89 wil_err(wil
, "wmi_p2p_cfg failed\n");
93 rc
= wmi_set_ssid(vif
, strlen(P2P_WILDCARD_SSID
), P2P_WILDCARD_SSID
);
95 wil_err(wil
, "wmi_set_ssid failed\n");
99 /* Set application IE to probe request and probe response */
100 rc
= wmi_set_ie(vif
, WMI_FRAME_PROBE_REQ
,
101 request
->ie_len
, request
->ie
);
103 wil_err(wil
, "wmi_set_ie(WMI_FRAME_PROBE_REQ) failed\n");
107 /* supplicant doesn't provide Probe Response IEs. As a workaround -
108 * re-use Probe Request IEs
110 rc
= wmi_set_ie(vif
, WMI_FRAME_PROBE_RESP
,
111 request
->ie_len
, request
->ie
);
113 wil_err(wil
, "wmi_set_ie(WMI_FRAME_PROBE_RESP) failed\n");
117 rc
= wmi_start_search(vif
);
119 wil_err(wil
, "wmi_start_search failed\n");
123 p2p
->discovery_started
= 1;
124 INIT_WORK(&p2p
->discovery_expired_work
, wil_p2p_search_expired
);
125 mod_timer(&p2p
->discovery_timer
,
126 jiffies
+ msecs_to_jiffies(P2P_SEARCH_DURATION_MS
));
130 wmi_stop_discovery(vif
);
136 int wil_p2p_listen(struct wil6210_priv
*wil
, struct wireless_dev
*wdev
,
137 unsigned int duration
, struct ieee80211_channel
*chan
,
140 struct wil6210_vif
*vif
= wdev_to_vif(wil
, wdev
);
141 struct wil_p2p_info
*p2p
= &vif
->p2p
;
147 wil_dbg_misc(wil
, "p2p_listen: duration %d\n", duration
);
149 mutex_lock(&wil
->mutex
);
151 if (p2p
->discovery_started
) {
152 wil_err(wil
, "discovery already ongoing\n");
157 memcpy(&p2p
->listen_chan
, chan
, sizeof(*chan
));
158 *cookie
= ++p2p
->cookie
;
159 p2p
->listen_duration
= duration
;
161 mutex_lock(&wil
->vif_mutex
);
162 if (vif
->scan_request
) {
163 wil_dbg_misc(wil
, "Delaying p2p listen until scan done\n");
164 p2p
->pending_listen_wdev
= wdev
;
165 p2p
->discovery_started
= 1;
167 mutex_unlock(&wil
->vif_mutex
);
170 mutex_unlock(&wil
->vif_mutex
);
172 rc
= wil_p2p_start_listen(vif
);
176 p2p
->discovery_started
= 1;
178 wil
->radio_wdev
= wdev
;
180 cfg80211_ready_on_channel(wdev
, *cookie
, chan
, duration
,
184 mutex_unlock(&wil
->mutex
);
188 u8
wil_p2p_stop_discovery(struct wil6210_vif
*vif
)
190 struct wil_p2p_info
*p2p
= &vif
->p2p
;
191 u8 started
= p2p
->discovery_started
;
193 if (p2p
->discovery_started
) {
194 if (p2p
->pending_listen_wdev
) {
195 /* discovery not really started, only pending */
196 p2p
->pending_listen_wdev
= NULL
;
198 del_timer_sync(&p2p
->discovery_timer
);
199 wmi_stop_discovery(vif
);
201 p2p
->discovery_started
= 0;
207 int wil_p2p_cancel_listen(struct wil6210_vif
*vif
, u64 cookie
)
209 struct wil6210_priv
*wil
= vif_to_wil(vif
);
210 struct wil_p2p_info
*p2p
= &vif
->p2p
;
213 mutex_lock(&wil
->mutex
);
215 if (cookie
!= p2p
->cookie
) {
216 wil_info(wil
, "Cookie mismatch: 0x%016llx vs. 0x%016llx\n",
217 p2p
->cookie
, cookie
);
218 mutex_unlock(&wil
->mutex
);
222 started
= wil_p2p_stop_discovery(vif
);
224 mutex_unlock(&wil
->mutex
);
227 wil_err(wil
, "listen not started\n");
231 mutex_lock(&wil
->vif_mutex
);
232 cfg80211_remain_on_channel_expired(vif_to_radio_wdev(wil
, vif
),
237 wil
->radio_wdev
= wil
->main_ndev
->ieee80211_ptr
;
238 mutex_unlock(&wil
->vif_mutex
);
242 void wil_p2p_listen_expired(struct work_struct
*work
)
244 struct wil_p2p_info
*p2p
= container_of(work
,
245 struct wil_p2p_info
, discovery_expired_work
);
246 struct wil6210_vif
*vif
= container_of(p2p
,
247 struct wil6210_vif
, p2p
);
248 struct wil6210_priv
*wil
= vif_to_wil(vif
);
251 wil_dbg_misc(wil
, "p2p_listen_expired\n");
253 mutex_lock(&wil
->mutex
);
254 started
= wil_p2p_stop_discovery(vif
);
255 mutex_unlock(&wil
->mutex
);
260 mutex_lock(&wil
->vif_mutex
);
261 cfg80211_remain_on_channel_expired(vif_to_radio_wdev(wil
, vif
),
266 wil
->radio_wdev
= wil
->main_ndev
->ieee80211_ptr
;
267 mutex_unlock(&wil
->vif_mutex
);
270 void wil_p2p_search_expired(struct work_struct
*work
)
272 struct wil_p2p_info
*p2p
= container_of(work
,
273 struct wil_p2p_info
, discovery_expired_work
);
274 struct wil6210_vif
*vif
= container_of(p2p
,
275 struct wil6210_vif
, p2p
);
276 struct wil6210_priv
*wil
= vif_to_wil(vif
);
279 wil_dbg_misc(wil
, "p2p_search_expired\n");
281 mutex_lock(&wil
->mutex
);
282 started
= wil_p2p_stop_discovery(vif
);
283 mutex_unlock(&wil
->mutex
);
286 struct cfg80211_scan_info info
= {
290 mutex_lock(&wil
->vif_mutex
);
291 if (vif
->scan_request
) {
292 cfg80211_scan_done(vif
->scan_request
, &info
);
293 vif
->scan_request
= NULL
;
296 wil
->main_ndev
->ieee80211_ptr
;
298 mutex_unlock(&wil
->vif_mutex
);
302 void wil_p2p_delayed_listen_work(struct work_struct
*work
)
304 struct wil_p2p_info
*p2p
= container_of(work
,
305 struct wil_p2p_info
, delayed_listen_work
);
306 struct wil6210_vif
*vif
= container_of(p2p
,
307 struct wil6210_vif
, p2p
);
308 struct wil6210_priv
*wil
= vif_to_wil(vif
);
311 mutex_lock(&wil
->mutex
);
313 wil_dbg_misc(wil
, "Checking delayed p2p listen\n");
314 if (!p2p
->discovery_started
|| !p2p
->pending_listen_wdev
)
317 mutex_lock(&wil
->vif_mutex
);
318 if (vif
->scan_request
) {
319 /* another scan started, wait again... */
320 mutex_unlock(&wil
->vif_mutex
);
323 mutex_unlock(&wil
->vif_mutex
);
325 rc
= wil_p2p_start_listen(vif
);
327 mutex_lock(&wil
->vif_mutex
);
329 cfg80211_remain_on_channel_expired(p2p
->pending_listen_wdev
,
334 wil
->radio_wdev
= wil
->main_ndev
->ieee80211_ptr
;
336 cfg80211_ready_on_channel(p2p
->pending_listen_wdev
, p2p
->cookie
,
338 p2p
->listen_duration
, GFP_KERNEL
);
340 wil
->radio_wdev
= p2p
->pending_listen_wdev
;
342 p2p
->pending_listen_wdev
= NULL
;
343 mutex_unlock(&wil
->vif_mutex
);
346 mutex_unlock(&wil
->mutex
);
349 void wil_p2p_stop_radio_operations(struct wil6210_priv
*wil
)
351 struct wil6210_vif
*vif
= ndev_to_vif(wil
->main_ndev
);
352 struct wil_p2p_info
*p2p
= &vif
->p2p
;
353 struct cfg80211_scan_info info
= {
357 lockdep_assert_held(&wil
->mutex
);
358 lockdep_assert_held(&wil
->vif_mutex
);
360 if (wil
->radio_wdev
!= wil
->p2p_wdev
)
363 if (!p2p
->discovery_started
) {
364 /* Regular scan on the p2p device */
365 if (vif
->scan_request
&&
366 vif
->scan_request
->wdev
== wil
->p2p_wdev
)
367 wil_abort_scan(vif
, true);
371 /* Search or listen on p2p device */
372 mutex_unlock(&wil
->vif_mutex
);
373 wil_p2p_stop_discovery(vif
);
374 mutex_lock(&wil
->vif_mutex
);
376 if (vif
->scan_request
) {
378 cfg80211_scan_done(vif
->scan_request
, &info
);
379 vif
->scan_request
= NULL
;
382 cfg80211_remain_on_channel_expired(wil
->radio_wdev
,
389 wil
->radio_wdev
= wil
->main_ndev
->ieee80211_ptr
;