brcmfmac: Update AP mode for GO creation.
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / net / wireless / brcm80211 / brcmfmac / p2p.c
CommitLineData
9f440b7b
AS
1/*
2 * Copyright (c) 2012 Broadcom Corporation
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16#include <linux/slab.h>
17#include <linux/netdevice.h>
18#include <net/cfg80211.h>
19
20#include <brcmu_wifi.h>
21#include <brcmu_utils.h>
22#include <defs.h>
23#include <dhd.h>
24#include <dhd_dbg.h>
25#include "fwil.h"
d3c0b633 26#include "fwil_types.h"
9f440b7b
AS
27#include "p2p.h"
28#include "wl_cfg80211.h"
29
30/* parameters used for p2p escan */
31#define P2PAPI_SCAN_NPROBES 1
32#define P2PAPI_SCAN_DWELL_TIME_MS 80
33#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40
34#define P2PAPI_SCAN_HOME_TIME_MS 60
35#define P2PAPI_SCAN_NPROBS_TIME_MS 30
36#define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100
37#define WL_SCAN_CONNECT_DWELL_TIME_MS 200
38#define WL_SCAN_JOIN_PROBE_INTERVAL_MS 20
39
40#define BRCMF_P2P_WILDCARD_SSID "DIRECT-"
41#define BRCMF_P2P_WILDCARD_SSID_LEN (sizeof(BRCMF_P2P_WILDCARD_SSID) - 1)
42
43#define SOCIAL_CHAN_1 1
44#define SOCIAL_CHAN_2 6
45#define SOCIAL_CHAN_3 11
46#define SOCIAL_CHAN_CNT 3
47#define AF_PEER_SEARCH_CNT 2
48
d3c0b633
AS
49#define BRCMF_SCB_TIMEOUT_VALUE 20
50
9f440b7b
AS
51/**
52 * struct brcmf_p2p_disc_st_le - set discovery state in firmware.
53 *
54 * @state: requested discovery state (see enum brcmf_p2p_disc_state).
55 * @chspec: channel parameter for %WL_P2P_DISC_ST_LISTEN state.
56 * @dwell: dwell time in ms for %WL_P2P_DISC_ST_LISTEN state.
57 */
58struct brcmf_p2p_disc_st_le {
59 u8 state;
60 __le16 chspec;
61 __le16 dwell;
62};
63
64/**
65 * enum brcmf_p2p_disc_state - P2P discovery state values
66 *
67 * @WL_P2P_DISC_ST_SCAN: P2P discovery with wildcard SSID and P2P IE.
68 * @WL_P2P_DISC_ST_LISTEN: P2P discovery off-channel for specified time.
69 * @WL_P2P_DISC_ST_SEARCH: P2P discovery with P2P wildcard SSID and P2P IE.
70 */
71enum brcmf_p2p_disc_state {
72 WL_P2P_DISC_ST_SCAN,
73 WL_P2P_DISC_ST_LISTEN,
74 WL_P2P_DISC_ST_SEARCH
75};
76
77/**
78 * struct brcmf_p2p_scan_le - P2P specific scan request.
79 *
80 * @type: type of scan method requested (values: 'E' or 'S').
81 * @reserved: reserved (ignored).
82 * @eparams: parameters used for type 'E'.
83 * @sparams: parameters used for type 'S'.
84 */
85struct brcmf_p2p_scan_le {
86 u8 type;
87 u8 reserved[3];
88 union {
89 struct brcmf_escan_params_le eparams;
90 struct brcmf_scan_params_le sparams;
91 };
92};
93
9f440b7b
AS
94/**
95 * brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation.
96 *
97 * @p2p: P2P specific data.
98 */
99static int brcmf_p2p_set_firmware(struct brcmf_p2p_info *p2p)
100{
101 struct net_device *ndev = cfg_to_ndev(p2p->cfg);
102 u8 null_eth_addr[] = { 0, 0, 0, 0, 0, 0 };
103 s32 ret = 0;
104
105 brcmf_fil_iovar_int_set(netdev_priv(ndev), "apsta", 1);
106
107 /* In case of COB type, firmware has default mac address
108 * After Initializing firmware, we have to set current mac address to
109 * firmware for P2P device address
110 */
111 ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "p2p_da_override",
112 null_eth_addr, sizeof(null_eth_addr));
113 if (ret)
114 brcmf_err("failed to update device address ret %d\n", ret);
115
116 return ret;
117}
118
119/**
120 * brcmf_p2p_generate_bss_mac() - derive mac addresses for P2P.
121 *
122 * @p2p: P2P specific data.
123 *
124 * P2P needs mac addresses for P2P device and interface. These are
125 * derived from the primary net device, ie. the permanent ethernet
126 * address of the device.
127 */
128static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p)
129{
9f440b7b
AS
130 /* Generate the P2P Device Address. This consists of the device's
131 * primary MAC address with the locally administered bit set.
132 */
de66efca 133 memcpy(p2p->dev_addr, p2p->cfg->pub->mac, ETH_ALEN);
9f440b7b
AS
134 p2p->dev_addr[0] |= 0x02;
135
136 /* Generate the P2P Interface Address. If the discovery and connection
137 * BSSCFGs need to simultaneously co-exist, then this address must be
138 * different from the P2P Device Address, but also locally administered.
139 */
140 memcpy(p2p->int_addr, p2p->dev_addr, ETH_ALEN);
141 p2p->int_addr[4] ^= 0x80;
142}
143
144/**
145 * brcmf_p2p_scan_is_p2p_request() - is cfg80211 scan request a P2P scan.
146 *
147 * @request: the scan request as received from cfg80211.
148 *
149 * returns true if one of the ssids in the request matches the
150 * P2P wildcard ssid; otherwise returns false.
151 */
152static bool brcmf_p2p_scan_is_p2p_request(struct cfg80211_scan_request *request)
153{
154 struct cfg80211_ssid *ssids = request->ssids;
155 int i;
156
157 for (i = 0; i < request->n_ssids; i++) {
158 if (ssids[i].ssid_len != BRCMF_P2P_WILDCARD_SSID_LEN)
159 continue;
160
161 brcmf_dbg(INFO, "comparing ssid \"%s\"", ssids[i].ssid);
162 if (!memcmp(BRCMF_P2P_WILDCARD_SSID, ssids[i].ssid,
163 BRCMF_P2P_WILDCARD_SSID_LEN))
164 return true;
165 }
166 return false;
167}
168
169/**
170 * brcmf_p2p_set_discover_state - set discover state in firmware.
171 *
172 * @ifp: low-level interface object.
173 * @state: discover state to set.
174 * @chanspec: channel parameters (for state @WL_P2P_DISC_ST_LISTEN only).
175 * @listen_ms: duration to listen (for state @WL_P2P_DISC_ST_LISTEN only).
176 */
177static s32 brcmf_p2p_set_discover_state(struct brcmf_if *ifp, u8 state,
178 u16 chanspec, u16 listen_ms)
179{
180 struct brcmf_p2p_disc_st_le discover_state;
181 s32 ret = 0;
182 brcmf_dbg(TRACE, "enter\n");
183
184 discover_state.state = state;
185 discover_state.chspec = cpu_to_le16(chanspec);
186 discover_state.dwell = cpu_to_le16(listen_ms);
187 ret = brcmf_fil_bsscfg_data_set(ifp, "p2p_state", &discover_state,
188 sizeof(discover_state));
189 return ret;
190}
191
9f440b7b
AS
192/**
193 * brcmf_p2p_init_discovery() - enable discovery in the firmware.
194 *
195 * @p2p: P2P specific data.
196 *
197 * Configures the firmware to allow P2P peer discovery. Creates the
198 * virtual interface and consequently the P2P device for it.
199 */
200static s32 brcmf_p2p_init_discovery(struct brcmf_p2p_info *p2p)
201{
202 struct net_device *ndev = cfg_to_ndev(p2p->cfg);
203 struct brcmf_cfg80211_vif *vif;
204 struct brcmf_if *ifp;
205 struct p2p_bss *bss_dev;
206 s32 index;
207 s32 ret;
208
209 brcmf_dbg(TRACE, "enter\n");
210
211 bss_dev = &p2p->bss_idx[P2PAPI_BSSCFG_DEVICE];
212 if (bss_dev->vif != NULL) {
213 brcmf_dbg(INFO, "do nothing, already initialized\n");
214 return 0;
215 }
216
217 /* Enable P2P Discovery in the firmware */
218 ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "p2p_disc", 1);
219 if (ret < 0) {
220 brcmf_err("set discover error\n");
221 return ret;
222 }
223
224 /* obtain bsscfg index for P2P discovery */
225 ret = brcmf_fil_iovar_int_get(netdev_priv(ndev), "p2p_dev", &index);
226 if (ret < 0) {
227 brcmf_err("retrieving discover bsscfg index failed\n");
228 return ret;
229 }
230
231 /*
232 * need brcmf_if for setting the discovery state.
233 */
234 ifp = kzalloc(sizeof(*vif->ifp), GFP_KERNEL);
235 if (!ifp) {
236 brcmf_err("could not create discovery if\n");
237 return -ENOMEM;
238 }
239
240 /* set required fields */
241 ifp->drvr = p2p->cfg->pub;
242 ifp->ifidx = 0;
243 ifp->bssidx = index;
244
245 /* Set the initial discovery state to SCAN */
246 ret = brcmf_p2p_set_discover_state(ifp, WL_P2P_DISC_ST_SCAN, 0, 0);
247
248 if (ret != 0) {
249 brcmf_err("unable to set WL_P2P_DISC_ST_SCAN\n");
250 (void)brcmf_fil_iovar_int_set(netdev_priv(ndev), "p2p_disc", 0);
251 kfree(ifp);
252 return ret;
253 }
254
255 /* create a vif for it */
d3c0b633 256 vif = brcmf_alloc_vif(p2p->cfg, NL80211_IFTYPE_P2P_DEVICE, false);
9f440b7b
AS
257 if (IS_ERR(vif)) {
258 brcmf_err("could not create discovery vif\n");
259 kfree(ifp);
260 return PTR_ERR(vif);
261 }
262
263 vif->ifp = ifp;
264 ifp->vif = vif;
265 bss_dev->vif = vif;
266
267 return 0;
268}
269
270/**
271 * brcmf_p2p_deinit_discovery() - disable P2P device discovery.
272 *
273 * @p2p: P2P specific data.
274 *
275 * Resets the discovery state and disables it in firmware. The virtual
276 * interface and P2P device are freed.
277 */
278static s32 brcmf_p2p_deinit_discovery(struct brcmf_p2p_info *p2p)
279{
280 struct net_device *ndev = cfg_to_ndev(p2p->cfg);
281 struct brcmf_if *ifp;
282 struct p2p_bss *bss_dev;
283 brcmf_dbg(TRACE, "enter\n");
284
285 bss_dev = &p2p->bss_idx[P2PAPI_BSSCFG_DEVICE];
9f440b7b
AS
286 ifp = bss_dev->vif->ifp;
287
288 /* Set the discovery state to SCAN */
289 (void)brcmf_p2p_set_discover_state(ifp, WL_P2P_DISC_ST_SCAN, 0, 0);
290
291 /* Disable P2P discovery in the firmware */
292 (void)brcmf_fil_iovar_int_set(netdev_priv(ndev), "p2p_disc", 0);
293
294 /* remove discovery interface */
295 brcmf_free_vif(bss_dev->vif);
296 bss_dev->vif = NULL;
297 kfree(ifp);
298
299 return 0;
300}
301
302/**
303 * brcmf_p2p_enable_discovery() - initialize and configure discovery.
304 *
305 * @p2p: P2P specific data.
306 * @ie: buffer containing information elements.
307 * @ie_len: length of @ie buffer.
308 *
309 * Initializes the discovery device and configure the virtual interface.
310 */
0de8aace 311static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p)
9f440b7b
AS
312{
313 struct brcmf_cfg80211_vif *vif;
314 s32 ret = 0;
315
316 brcmf_dbg(TRACE, "enter\n");
317 vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
318 if (vif) {
0de8aace
HM
319 brcmf_dbg(INFO, "DISCOVERY init already done\n");
320 goto exit;
9f440b7b
AS
321 }
322
323 ret = brcmf_p2p_init_discovery(p2p);
324 if (ret < 0) {
325 brcmf_err("init discovery error %d\n", ret);
326 goto exit;
327 }
328
329 vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
330
331 /*
332 * Set wsec to any non-zero value in the discovery bsscfg
333 * to ensure our P2P probe responses have the privacy bit
334 * set in the 802.11 WPA IE. Some peer devices may not
335 * initiate WPS with us if this bit is not set.
336 */
337 ret = brcmf_fil_bsscfg_int_set(vif->ifp, "wsec", AES_ENABLED);
338 if (ret < 0)
339 brcmf_err("wsec error %d\n", ret);
340
9f440b7b
AS
341exit:
342 return ret;
343}
344
0de8aace 345/**
9f440b7b
AS
346 * brcmf_p2p_escan() - initiate a P2P scan.
347 *
348 * @p2p: P2P specific data.
349 * @num_chans: number of channels to scan.
350 * @chanspecs: channel parameters for @num_chans channels.
351 * @search_state: P2P discover state to use.
352 * @action: scan action to pass to firmware.
353 * @bss_type: type of P2P bss.
354 */
355static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
356 u16 chanspecs[], s32 search_state, u16 action,
357 enum p2p_bss_type bss_type)
358{
359 s32 ret = 0;
360 s32 memsize = offsetof(struct brcmf_p2p_scan_le,
361 eparams.params_le.channel_list);
362 s32 nprobes;
363 s32 active;
364 u32 i;
365 u8 *memblk;
366 struct brcmf_cfg80211_vif *vif;
367 struct brcmf_p2p_scan_le *p2p_params;
368 struct brcmf_scan_params_le *sparams;
369 struct brcmf_ssid ssid;
370
9f440b7b
AS
371 memsize += num_chans * sizeof(__le16);
372 memblk = kzalloc(memsize, GFP_KERNEL);
373 if (!memblk)
374 return -ENOMEM;
375
376 vif = p2p->bss_idx[bss_type].vif;
377 if (vif == NULL) {
378 brcmf_err("no vif for bss type %d\n", bss_type);
379 ret = -EINVAL;
380 goto exit;
381 }
382
383 switch (search_state) {
384 case WL_P2P_DISC_ST_SEARCH:
385 /*
386 * If we in SEARCH STATE, we don't need to set SSID explictly
387 * because dongle use P2P WILDCARD internally by default
388 */
389 /* use null ssid */
390 ssid.SSID_len = 0;
391 memset(ssid.SSID, 0, sizeof(ssid.SSID));
392 break;
393 case WL_P2P_DISC_ST_SCAN:
394 /*
395 * wpa_supplicant has p2p_find command with type social or
396 * progressive. For progressive, we need to set the ssid to
397 * P2P WILDCARD because we just do broadcast scan unless
398 * setting SSID.
399 */
400 ssid.SSID_len = BRCMF_P2P_WILDCARD_SSID_LEN;
401 memcpy(ssid.SSID, BRCMF_P2P_WILDCARD_SSID, ssid.SSID_len);
402 break;
403 default:
404 brcmf_err(" invalid search state %d\n", search_state);
405 ret = -EINVAL;
406 goto exit;
407 }
408
409 brcmf_p2p_set_discover_state(vif->ifp, search_state, 0, 0);
410
411 /*
412 * set p2p scan parameters.
413 */
414 p2p_params = (struct brcmf_p2p_scan_le *)memblk;
415 p2p_params->type = 'E';
416
417 /* determine the scan engine parameters */
418 sparams = &p2p_params->eparams.params_le;
419 sparams->bss_type = DOT11_BSSTYPE_ANY;
420 if (p2p->cfg->active_scan)
421 sparams->scan_type = 0;
422 else
423 sparams->scan_type = 1;
424
425 memset(&sparams->bssid, 0xFF, ETH_ALEN);
426 if (ssid.SSID_len)
427 memcpy(sparams->ssid_le.SSID, ssid.SSID, ssid.SSID_len);
428 sparams->ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
429 sparams->home_time = cpu_to_le32(P2PAPI_SCAN_HOME_TIME_MS);
430
431 /*
432 * SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan
433 * supported by the supplicant.
434 */
435 if (num_chans == SOCIAL_CHAN_CNT || num_chans == (SOCIAL_CHAN_CNT + 1))
436 active = P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS;
437 else if (num_chans == AF_PEER_SEARCH_CNT)
438 active = P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS;
439 else if (wl_get_vif_state_all(p2p->cfg, BRCMF_VIF_STATUS_CONNECTED))
440 active = -1;
441 else
442 active = P2PAPI_SCAN_DWELL_TIME_MS;
443
444 /* Override scan params to find a peer for a connection */
445 if (num_chans == 1) {
446 active = WL_SCAN_CONNECT_DWELL_TIME_MS;
447 /* XXX WAR to sync with presence period of VSDB GO.
448 * send probe request more frequently
449 */
450 nprobes = active / WL_SCAN_JOIN_PROBE_INTERVAL_MS;
451 } else {
452 nprobes = active / P2PAPI_SCAN_NPROBS_TIME_MS;
453 }
454
455 if (nprobes <= 0)
456 nprobes = 1;
457
458 brcmf_dbg(INFO, "nprobes # %d, active_time %d\n", nprobes, active);
459 sparams->active_time = cpu_to_le32(active);
460 sparams->nprobes = cpu_to_le32(nprobes);
461 sparams->passive_time = cpu_to_le32(-1);
462 sparams->channel_num = cpu_to_le32(num_chans &
463 BRCMF_SCAN_PARAMS_COUNT_MASK);
464 for (i = 0; i < num_chans; i++)
465 sparams->channel_list[i] = cpu_to_le16(chanspecs[i]);
466
467 /* set the escan specific parameters */
468 p2p_params->eparams.version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
469 p2p_params->eparams.action = cpu_to_le16(action);
470 p2p_params->eparams.sync_id = cpu_to_le16(0x1234);
471 /* perform p2p scan on primary device */
472 ret = brcmf_fil_bsscfg_data_set(vif->ifp, "p2p_scan", memblk, memsize);
473 if (!ret)
474 set_bit(BRCMF_SCAN_STATUS_BUSY, &p2p->cfg->scan_status);
475exit:
476 kfree(memblk);
477 return ret;
478}
479
480/**
481 * brcmf_p2p_run_escan() - escan callback for peer-to-peer.
482 *
483 * @cfg: driver private data for cfg80211 interface.
484 * @ndev: net device for which scan is requested.
485 * @request: scan request from cfg80211.
486 * @action: scan action.
487 *
488 * Determines the P2P discovery state based to scan request parameters and
489 * validates the channels in the request.
490 */
491static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
492 struct net_device *ndev,
493 struct cfg80211_scan_request *request,
494 u16 action)
495{
496 struct brcmf_p2p_info *p2p = &cfg->p2p;
497 s32 err = 0;
498 s32 search_state = WL_P2P_DISC_ST_SCAN;
499 struct brcmf_cfg80211_vif *vif;
500 struct net_device *dev = NULL;
501 int i, num_nodfs = 0;
502 u16 *chanspecs;
503
504 brcmf_dbg(TRACE, "enter\n");
505
506 if (!request) {
507 err = -EINVAL;
508 goto exit;
509 }
510
511 if (request->n_channels) {
512 chanspecs = kcalloc(request->n_channels, sizeof(*chanspecs),
513 GFP_KERNEL);
514 if (!chanspecs) {
515 err = -ENOMEM;
516 goto exit;
517 }
518 vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif;
519 if (vif)
520 dev = vif->wdev.netdev;
521 if (request->n_channels == 3 &&
522 request->channels[0]->hw_value == SOCIAL_CHAN_1 &&
523 request->channels[1]->hw_value == SOCIAL_CHAN_2 &&
524 request->channels[2]->hw_value == SOCIAL_CHAN_3) {
525 /* SOCIAL CHANNELS 1, 6, 11 */
526 search_state = WL_P2P_DISC_ST_SEARCH;
527 brcmf_dbg(INFO, "P2P SEARCH PHASE START\n");
528 } else if (dev != NULL && vif->mode == WL_MODE_AP) {
529 /* If you are already a GO, then do SEARCH only */
530 brcmf_dbg(INFO, "Already a GO. Do SEARCH Only\n");
531 search_state = WL_P2P_DISC_ST_SEARCH;
532 } else {
533 brcmf_dbg(INFO, "P2P SCAN STATE START\n");
534 }
535
536 /*
537 * no P2P scanning on passive or DFS channels.
538 */
539 for (i = 0; i < request->n_channels; i++) {
540 struct ieee80211_channel *chan = request->channels[i];
541
542 if (chan->flags & (IEEE80211_CHAN_RADAR |
543 IEEE80211_CHAN_PASSIVE_SCAN))
544 continue;
545
546 chanspecs[i] = channel_to_chanspec(chan);
547 brcmf_dbg(INFO, "%d: chan=%d, channel spec=%x\n",
548 num_nodfs, chan->hw_value, chanspecs[i]);
549 num_nodfs++;
550 }
551 err = brcmf_p2p_escan(p2p, num_nodfs, chanspecs, search_state,
552 action, P2PAPI_BSSCFG_DEVICE);
553 }
554exit:
555 if (err)
556 brcmf_err("error (%d)\n", err);
557 return err;
558}
559
560/**
561 * brcmf_p2p_scan_prep() - prepare scan based on request.
562 *
563 * @wiphy: wiphy device.
564 * @request: scan request from cfg80211.
0f8ffe17 565 * @vif: vif on which scan request is to be executed.
9f440b7b
AS
566 *
567 * Prepare the scan appropriately for type of scan requested. Overrides the
568 * escan .run() callback for peer-to-peer scanning.
569 */
570int brcmf_p2p_scan_prep(struct wiphy *wiphy,
0f8ffe17
HM
571 struct cfg80211_scan_request *request,
572 struct brcmf_cfg80211_vif *vif)
9f440b7b
AS
573{
574 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
575 struct brcmf_p2p_info *p2p = &cfg->p2p;
576 int err = 0;
577
578 if (brcmf_p2p_scan_is_p2p_request(request)) {
579 /* find my listen channel */
580 err = cfg80211_get_p2p_attr(request->ie, request->ie_len,
581 IEEE80211_P2P_ATTR_LISTEN_CHANNEL,
582 &p2p->listen_channel, 1);
583 if (err < 0)
584 return err;
585
586 clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status);
587 brcmf_dbg(INFO, "P2P: GO_NEG_PHASE status cleared\n");
588
0de8aace 589 err = brcmf_p2p_enable_discovery(p2p);
0f8ffe17
HM
590 if (err)
591 return err;
9f440b7b 592
0f8ffe17 593 vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
9f440b7b 594
0f8ffe17
HM
595 /* override .run_escan() callback. */
596 cfg->escan_info.run = brcmf_p2p_run_escan;
9f440b7b 597 }
0f8ffe17
HM
598 err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG,
599 request->ie, request->ie_len);
9f440b7b
AS
600 return err;
601}
602
0de8aace
HM
603
604/**
605 * brcmf_p2p_remain_on_channel() - put device on channel and stay there.
606 *
607 * @wiphy: wiphy device.
608 * @channel: channel to stay on.
609 * @duration: time in ms to remain on channel.
610 *
611 */
612int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
613 struct ieee80211_channel *channel,
614 unsigned int duration, u64 *cookie)
615{
616 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
617 struct brcmf_p2p_info *p2p = &cfg->p2p;
618 struct brcmf_cfg80211_vif *vif;
619 s32 err;
620 u16 chanspec;
621
622 brcmf_dbg(TRACE, "Enter, channel: %d, duration ms (%d)\n",
623 ieee80211_frequency_to_channel(channel->center_freq),
624 duration);
625
626 *cookie = 0;
627 err = brcmf_p2p_enable_discovery(p2p);
628 if (err)
629 goto exit;
630
631 chanspec = channel_to_chanspec(channel);
632 vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
633 err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN,
634 chanspec, (u16)duration);
635 if (err)
636 goto exit;
637
638 memcpy(&p2p->remain_on_channel, channel,
639 sizeof(p2p->remain_on_channel));
640
641 set_bit(BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL, &p2p->status);
642
643exit:
644 cfg80211_ready_on_channel(wdev, *cookie, channel, duration, GFP_KERNEL);
645 return err;
646}
647
648
649/**
650 * brcmf_p2p_notify_listen_complete() - p2p listen has completed.
651 *
652 * @ifp: interfac control.
653 * @e: event message. Not used, to make it usable for fweh event dispatcher.
654 * @data: payload of message. Not used.
655 *
656 */
657int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp,
658 const struct brcmf_event_msg *e,
659 void *data)
660{
661 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
662 struct brcmf_p2p_info *p2p = &cfg->p2p;
663
664 brcmf_dbg(TRACE, "Enter\n");
665 if (test_and_clear_bit(BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL,
666 &p2p->status))
667 cfg80211_remain_on_channel_expired(&ifp->vif->wdev, 0,
668 &p2p->remain_on_channel,
669 GFP_KERNEL);
670 return 0;
671}
672
673
674/**
675 * brcmf_p2p_cancel_remain_on_channel() - cancel p2p listen state.
676 *
677 * @ifp: interfac control.
678 *
679 */
680void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp)
681{
682 if (!ifp)
683 return;
684 brcmf_p2p_set_discover_state(ifp, WL_P2P_DISC_ST_SCAN, 0, 0);
685 brcmf_p2p_notify_listen_complete(ifp, NULL, NULL);
686}
687
688
9f440b7b
AS
689/**
690 * brcmf_p2p_attach() - attach for P2P.
691 *
692 * @cfg: driver private data for cfg80211 interface.
693 */
a0f07959
HM
694void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg,
695 struct brcmf_cfg80211_vif *vif)
9f440b7b
AS
696{
697 struct brcmf_p2p_info *p2p;
698
699 p2p = &cfg->p2p;
700
701 p2p->cfg = cfg;
a0f07959 702 p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = vif;
9f440b7b 703 brcmf_p2p_generate_bss_mac(p2p);
a0f07959 704 brcmf_p2p_set_firmware(p2p);
9f440b7b
AS
705}
706
707/**
708 * brcmf_p2p_detach() - detach P2P.
709 *
710 * @p2p: P2P specific data.
711 */
712void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
713{
0de8aace
HM
714 if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif != NULL) {
715 brcmf_p2p_cancel_remain_on_channel(
716 p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp);
717 brcmf_p2p_deinit_discovery(p2p);
718 }
9f440b7b
AS
719 /* just set it all to zero */
720 memset(p2p, 0, sizeof(*p2p));
721}
722
7a5c1f64
HM
723/**
724 * brcmf_p2p_get_current_chanspec() - Get current operation channel.
725 *
726 * @p2p: P2P specific data.
727 * @chanspec: chanspec to be returned.
728 */
729static void brcmf_p2p_get_current_chanspec(struct brcmf_p2p_info *p2p,
730 u16 *chanspec)
d3c0b633 731{
7a5c1f64 732 struct brcmf_if *ifp;
d3c0b633 733 struct brcmf_fil_chan_info_le ci;
7a5c1f64
HM
734 s32 err;
735
736 ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
737
738 *chanspec = 11 & WL_CHANSPEC_CHAN_MASK;
d3c0b633 739
d3c0b633
AS
740 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL, &ci, sizeof(ci));
741 if (!err) {
7a5c1f64
HM
742 *chanspec = le32_to_cpu(ci.hw_channel) & WL_CHANSPEC_CHAN_MASK;
743 if (*chanspec < CH_MAX_2G_CHANNEL)
744 *chanspec |= WL_CHANSPEC_BAND_2G;
d3c0b633 745 else
7a5c1f64
HM
746 *chanspec |= WL_CHANSPEC_BAND_5G;
747 }
748 *chanspec |= WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE;
749}
750
751/**
752 * Change a P2P Role.
753 * Parameters:
754 * @mac: MAC address of the BSS to change a role
755 * Returns 0 if success.
756 */
757int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
758 enum brcmf_fil_p2p_if_types if_type)
759{
760 struct brcmf_p2p_info *p2p = &cfg->p2p;
761 struct brcmf_cfg80211_vif *vif;
762 struct brcmf_fil_p2p_if_le if_request;
763 s32 err;
764 u16 chanspec;
765
766 brcmf_dbg(TRACE, "Enter\n");
767
768 vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
769 if (!vif) {
770 brcmf_err("vif for P2PAPI_BSSCFG_PRIMARY does not exist\n");
771 return -EPERM;
d3c0b633 772 }
7a5c1f64
HM
773 brcmf_notify_escan_complete(cfg, vif->ifp->ndev, true, true);
774 vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif;
775 if (!vif) {
776 brcmf_err("vif for P2PAPI_BSSCFG_CONNECTION does not exist\n");
777 return -EPERM;
778 }
779 brcmf_set_mpc(vif->ifp->ndev, 0);
780
781 /* In concurrency case, STA may be already associated in a particular */
782 /* channel. so retrieve the current channel of primary interface and */
783 /* then start the virtual interface on that. */
784 brcmf_p2p_get_current_chanspec(p2p, &chanspec);
785
786 if_request.type = cpu_to_le16((u16)if_type);
787 if_request.chspec = cpu_to_le16(chanspec);
788 memcpy(if_request.addr, p2p->int_addr, sizeof(if_request.addr));
789
790 brcmf_cfg80211_arm_vif_event(cfg, vif);
791 err = brcmf_fil_iovar_data_set(vif->ifp, "p2p_ifupd", &if_request,
792 sizeof(if_request));
793 if (err) {
794 brcmf_err("p2p_ifupd FAILED, err=%d\n", err);
795 brcmf_cfg80211_arm_vif_event(cfg, NULL);
796 return err;
797 }
798 err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_CHANGE,
799 msecs_to_jiffies(1500));
800 brcmf_cfg80211_arm_vif_event(cfg, NULL);
801 if (!err) {
802 brcmf_err("No BRCMF_E_IF_CHANGE event received\n");
803 return -EIO;
804 }
805
806 err = brcmf_fil_cmd_int_set(vif->ifp, BRCMF_C_SET_SCB_TIMEOUT,
807 BRCMF_SCB_TIMEOUT_VALUE);
808
809 return err;
810}
811
812static int brcmf_p2p_request_p2p_if(struct brcmf_p2p_info *p2p,
813 struct brcmf_if *ifp, u8 ea[ETH_ALEN],
814 enum brcmf_fil_p2p_if_types iftype)
815{
816 struct brcmf_fil_p2p_if_le if_request;
817 int err;
818 u16 chanspec;
819
820 /* we need a default channel */
821 brcmf_p2p_get_current_chanspec(p2p, &chanspec);
d3c0b633
AS
822
823 /* fill the firmware request */
824 memcpy(if_request.addr, ea, ETH_ALEN);
7ee2d926 825 if_request.type = cpu_to_le16((u16)iftype);
d3c0b633
AS
826 if_request.chspec = cpu_to_le16(chanspec);
827
828 err = brcmf_fil_iovar_data_set(ifp, "p2p_ifadd", &if_request,
829 sizeof(if_request));
830 if (err)
831 return err;
832
d3c0b633
AS
833 return err;
834}
835
5f4f9f11
AS
836static int brcmf_p2p_disable_p2p_if(struct brcmf_cfg80211_vif *vif)
837{
838 struct brcmf_cfg80211_info *cfg = wdev_to_cfg(&vif->wdev);
839 struct net_device *pri_ndev = cfg_to_ndev(cfg);
840 struct brcmf_if *ifp = netdev_priv(pri_ndev);
841 u8 *addr = vif->wdev.netdev->dev_addr;
842
843 return brcmf_fil_iovar_data_set(ifp, "p2p_ifdis", addr, ETH_ALEN);
844}
845
846static int brcmf_p2p_release_p2p_if(struct brcmf_cfg80211_vif *vif)
847{
848 struct brcmf_cfg80211_info *cfg = wdev_to_cfg(&vif->wdev);
849 struct net_device *pri_ndev = cfg_to_ndev(cfg);
850 struct brcmf_if *ifp = netdev_priv(pri_ndev);
851 u8 *addr = vif->wdev.netdev->dev_addr;
852
853 return brcmf_fil_iovar_data_set(ifp, "p2p_ifdel", addr, ETH_ALEN);
854}
855
9f440b7b
AS
856/**
857 * brcmf_p2p_add_vif() - create a new P2P virtual interface.
858 *
859 * @wiphy: wiphy device of new interface.
860 * @name: name of the new interface.
861 * @type: nl80211 interface type.
862 * @flags: TBD
863 * @params: TBD
9f440b7b
AS
864 */
865struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
866 enum nl80211_iftype type, u32 *flags,
867 struct vif_params *params)
868{
d3c0b633
AS
869 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
870 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
871 struct brcmf_cfg80211_vif *vif;
872 enum brcmf_fil_p2p_if_types iftype;
873 enum wl_mode mode;
874 int err;
875
876 if (brcmf_cfg80211_vif_event_armed(cfg))
877 return ERR_PTR(-EBUSY);
878
9f440b7b 879 brcmf_dbg(INFO, "adding vif \"%s\" (type=%d)\n", name, type);
d3c0b633
AS
880
881 switch (type) {
882 case NL80211_IFTYPE_P2P_CLIENT:
883 iftype = BRCMF_FIL_P2P_IF_CLIENT;
884 mode = WL_MODE_BSS;
885 break;
886 case NL80211_IFTYPE_P2P_GO:
887 iftype = BRCMF_FIL_P2P_IF_GO;
888 mode = WL_MODE_AP;
889 break;
890 default:
891 return ERR_PTR(-EOPNOTSUPP);
892 }
893
894 vif = brcmf_alloc_vif(cfg, type, false);
7ee2d926
HM
895 if (IS_ERR(vif))
896 return (struct wireless_dev *)vif;
d3c0b633
AS
897 brcmf_cfg80211_arm_vif_event(cfg, vif);
898
7a5c1f64
HM
899 err = brcmf_p2p_request_p2p_if(&cfg->p2p, ifp, cfg->p2p.int_addr,
900 iftype);
7ee2d926
HM
901 if (err) {
902 brcmf_cfg80211_arm_vif_event(cfg, NULL);
d3c0b633 903 goto fail;
7ee2d926 904 }
d3c0b633
AS
905
906 /* wait for firmware event */
907 err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_ADD,
908 msecs_to_jiffies(1500));
909 brcmf_cfg80211_arm_vif_event(cfg, NULL);
910 if (!err) {
911 brcmf_err("timeout occurred\n");
912 err = -EIO;
913 goto fail;
914 }
915
916 /* interface created in firmware */
917 ifp = vif->ifp;
918 if (!ifp) {
919 brcmf_err("no if pointer provided\n");
920 err = -ENOENT;
7ee2d926 921 goto fail;
d3c0b633
AS
922 }
923
924 strncpy(ifp->ndev->name, name, sizeof(ifp->ndev->name) - 1);
925 brcmf_cfg80211_vif_complete(cfg);
7ee2d926
HM
926 cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif;
927 /* Disable firmware roaming for P2P interface */
928 brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
929 if (iftype == BRCMF_FIL_P2P_IF_GO) {
930 /* set station timeout for p2p */
931 brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCB_TIMEOUT,
932 BRCMF_SCB_TIMEOUT_VALUE);
933 }
d3c0b633
AS
934 return &ifp->vif->wdev;
935
936fail:
937 brcmf_free_vif(vif);
938 return ERR_PTR(err);
9f440b7b
AS
939}
940
941/**
942 * brcmf_p2p_del_vif() - delete a P2P virtual interface.
943 *
944 * @wiphy: wiphy device of interface.
945 * @wdev: wireless device of interface.
946 *
947 * TODO: not yet supported.
948 */
949int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
950{
d3c0b633 951 struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
9f440b7b 952 struct brcmf_cfg80211_vif *vif;
5f4f9f11
AS
953 unsigned long jiffie_timeout = msecs_to_jiffies(1500);
954 bool wait_for_disable = false;
d3c0b633 955 int err;
9f440b7b 956
5f4f9f11 957 brcmf_dbg(TRACE, "delete P2P vif\n");
9f440b7b 958 vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
d3c0b633 959
5f4f9f11
AS
960 switch (vif->wdev.iftype) {
961 case NL80211_IFTYPE_P2P_CLIENT:
962 if (test_bit(BRCMF_VIF_STATUS_DISCONNECTING, &vif->sme_state))
963 wait_for_disable = true;
964 break;
965
966 case NL80211_IFTYPE_P2P_GO:
967 if (!brcmf_p2p_disable_p2p_if(vif))
968 wait_for_disable = true;
969 break;
970
971 case NL80211_IFTYPE_P2P_DEVICE:
972 default:
973 return -ENOTSUPP;
974 break;
975 }
976
977 if (wait_for_disable)
7ee2d926
HM
978 wait_for_completion_timeout(&cfg->vif_disabled,
979 msecs_to_jiffies(500));
5f4f9f11
AS
980
981 brcmf_vif_clear_mgmt_ies(vif);
d3c0b633
AS
982
983 brcmf_cfg80211_arm_vif_event(cfg, vif);
5f4f9f11 984 err = brcmf_p2p_release_p2p_if(vif);
7ee2d926 985 if (!err) {
5f4f9f11
AS
986 /* wait for firmware event */
987 err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_DEL,
988 jiffie_timeout);
7ee2d926
HM
989 if (!err)
990 err = -EIO;
991 else
992 err = 0;
993 }
d3c0b633 994 brcmf_cfg80211_arm_vif_event(cfg, NULL);
5f4f9f11 995 brcmf_free_vif(vif);
7ee2d926 996 cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL;
5f4f9f11
AS
997
998 return err;
9f440b7b 999}